[红日安全]代码审计Day6 - 正则使用不当导致的路径穿越问题
字数 1434 2025-08-18 11:37:33
正则表达式使用不当导致的路径穿越漏洞分析与防御
漏洞概述
本教学文档将详细分析由正则表达式使用不当导致的路径穿越(Path Traversal)漏洞,通过WeEngine 0.8版本的实际案例,展示漏洞原理、利用方式及修复方法。
漏洞原理
核心问题
当使用preg_replace等正则函数进行输入过滤时,如果正则表达式设计不严谨,攻击者可能绕过过滤机制,通过构造特殊输入(如../)实现路径穿越,最终导致任意文件删除等严重后果。
示例代码分析
原始漏洞代码的正则表达式:
preg_replace('/[^a-z.-_]/', '', $input);
问题分析:
[^a-z.-_]表示匹配除了以下字符外的所有字符:- a-z:小写字母
- .-:从点号(.)到下划线()之间的ASCII字符(包括斜杠
/)
- 由于斜杠
/位于.和_之间(ASCII码:.=46,/=47,_=95),攻击者仍可使用../进行路径穿越
实际案例分析:WeEngine 0.8任意文件删除漏洞
漏洞链分析
-
入口点:
web/source/site/category.ctrl.php- 第14行调用
file_delete函数 - 未对文件名参数进行过滤
- 第14行调用
-
文件删除函数:
framework/function/file.func.phpfunction file_delete($file) { if (file_exists($file)) { @unlink($file); } return true; }- 直接接受文件路径参数,无任何过滤
-
参数来源追溯:
$file来自$row['icon']$row来自数据库site_nav表的查询结果site_nav表的icon字段值来自用户可控的$_GPC['iconfile']
漏洞利用步骤
- 添加文章分类时,在"上传图标"字段输入要删除的文件路径(如
../../config.php) - 该恶意路径被存储到数据库
site_nav表的icon字段 - 当删除该分类时,程序从数据库读取路径并传给
file_delete函数 - 系统删除指定文件,实现任意文件删除
漏洞验证
- 创建测试文件
delete.txt - 在添加分类时,图标字段输入
../../delete.txt - 删除该分类时,
delete.txt文件被删除
修复方案
修复建议
-
输入过滤:对文件名参数进行严格过滤,移除所有目录穿越字符
function checkstr($str) { return preg_replace('/\.\.\/|\.\/|\/|\\\/', '', $str); } -
防御措施:
- 限制文件名只能包含合法字符(如字母、数字、特定符号)
- 禁止路径分隔符(
/、\) - 使用
basename()函数获取文件名部分 - 设置文件操作白名单目录
-
修复代码示例:
$safe_icon = checkstr($row['icon']); file_delete($safe_icon);
CTF题目分析
题目代码:
<?php
include 'flag.php';
if ("POST" == $_SERVER['REQUEST_METHOD']) {
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) {
echo 'Wrong Format';
exit;
}
while (TRUE) {
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr)) break;
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower');
foreach ($ps as $pt) {
if (preg_match("/[[:$pt:]]+/", $password)) $c += 1;
}
if ($c < 3) break;
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
highlight_file(__FILE__);
?>
解题要点:
- 密码必须满足:
- 长度≥12的可打印字符(
[[:graph:]]) - 必须包含至少3种字符类型(标点、数字、大写、小写)
- 最终值必须等于"42"
- 长度≥12的可打印字符(
- 解法:利用正则替换特性
- 构造包含"42"的字符串,如
aA1!aA1!aA1!42 - 利用
preg_replace将前面部分替换为空
- 构造包含"42"的字符串,如
总结
-
正则表达式风险:
- 字符范围定义不当可能导致过滤绕过
- 特别注意
.到_的范围包含许多特殊字符
-
安全开发建议:
- 对文件操作参数进行严格过滤
- 最小权限原则:限制文件操作目录
- 避免直接使用用户输入作为文件路径
-
审计要点:
- 查找所有文件操作函数(
unlink、file_get_contents等) - 检查参数是否经过充分过滤
- 特别注意数据库存储再取出的"二次注入"场景
- 查找所有文件操作函数(
通过本案例,开发者应充分认识到正则表达式使用不当可能导致的安全风险,并在代码审计中特别关注路径操作相关的安全防护。