[红日安全]代码审计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任意文件删除漏洞

漏洞链分析

  1. 入口点web/source/site/category.ctrl.php

    • 第14行调用file_delete函数
    • 未对文件名参数进行过滤
  2. 文件删除函数framework/function/file.func.php

    function file_delete($file) {
        if (file_exists($file)) {
            @unlink($file);
        }
        return true;
    }
    
    • 直接接受文件路径参数,无任何过滤
  3. 参数来源追溯

    • $file来自$row['icon']
    • $row来自数据库site_nav表的查询结果
    • site_nav表的icon字段值来自用户可控的$_GPC['iconfile']

漏洞利用步骤

  1. 添加文章分类时,在"上传图标"字段输入要删除的文件路径(如../../config.php
  2. 该恶意路径被存储到数据库site_nav表的icon字段
  3. 当删除该分类时,程序从数据库读取路径并传给file_delete函数
  4. 系统删除指定文件,实现任意文件删除

漏洞验证

  1. 创建测试文件delete.txt
  2. 在添加分类时,图标字段输入../../delete.txt
  3. 删除该分类时,delete.txt文件被删除

修复方案

修复建议

  1. 输入过滤:对文件名参数进行严格过滤,移除所有目录穿越字符

    function checkstr($str) {
        return preg_replace('/\.\.\/|\.\/|\/|\\\/', '', $str);
    }
    
  2. 防御措施

    • 限制文件名只能包含合法字符(如字母、数字、特定符号)
    • 禁止路径分隔符(/\
    • 使用basename()函数获取文件名部分
    • 设置文件操作白名单目录
  3. 修复代码示例

    $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__);
?>

解题要点:

  1. 密码必须满足:
    • 长度≥12的可打印字符([[:graph:]]
    • 必须包含至少3种字符类型(标点、数字、大写、小写)
    • 最终值必须等于"42"
  2. 解法:利用正则替换特性
    • 构造包含"42"的字符串,如aA1!aA1!aA1!42
    • 利用preg_replace将前面部分替换为空

总结

  1. 正则表达式风险

    • 字符范围定义不当可能导致过滤绕过
    • 特别注意._的范围包含许多特殊字符
  2. 安全开发建议

    • 对文件操作参数进行严格过滤
    • 最小权限原则:限制文件操作目录
    • 避免直接使用用户输入作为文件路径
  3. 审计要点

    • 查找所有文件操作函数(unlinkfile_get_contents等)
    • 检查参数是否经过充分过滤
    • 特别注意数据库存储再取出的"二次注入"场景

通过本案例,开发者应充分认识到正则表达式使用不当可能导致的安全风险,并在代码审计中特别关注路径操作相关的安全防护。

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