WeChall - Smile
Challenge
WeChall 邀请用户帮忙添加新表情(smiley)到
bb_decoder。提交表单需要提供正则 pattern 和替换路径。源码文件为
smile.php 和 LIVIN_Smile.php。
Source Analysis
LIVIN_Smile.php 中的核心函数:
1 | public static function replaceSmiley($smiley, $path, $text) |
$smiley(用户输入的 pattern)直接被传入
preg_replace()。如果 pattern 包含 /e
修饰符,preg_replace 会把
$path(替换字符串)当作 PHP 代码执行。PHP 5.5 起废弃了
/e,并在 PHP 7.0 移除,因为它极易导致代码注入。
solution 以常量形式定义在 smile.php:
1 | define('LIVINSKULL_SMILEY_SOLUTION', LIVIN_Smile::getSolution()); |
通过 LIVIN_Smile::getSolution() 返回一个 32
位随机字符串,存储在 session 中。
Exploit
secure.php 对 filename 字段做了过滤:禁止
$、(、`、GWF、Common、include、require、eval
等关键字。但常量名 LIVINSKULL_SMILEY_SOLUTION
不包含任何被禁字符,可以直接通过检查。
攻击步骤:
- GET
smile.php获取 CSRF token - POST 到
smile.php,pattern 为/.*/e(启用 eval),filename 为LIVINSKULL_SMILEY_SOLUTION(PHP 常量名) testSmiley()调用preg_replace('/.*/e', 'LIVINSKULL_SMILEY_SOLUTION', $text),/e使LIVINSKULL_SMILEY_SOLUTION被当作 PHP 代码执行,返回常量值(32 位 solution 字符串)- 测试输出框中直接显示 solution
looksHarmless()检查会失败,但 solution 已经泄露
1 | import requests, re |