一篇文章带你了解PHP静态分析工具RIPS
字数 2766 2025-08-24 23:51:09

PHP静态分析工具RIPS深入解析

一、RIPS工具概述

RIPS是一款用于PHP代码静态分析的开源工具,主要用于检测PHP应用程序中的安全漏洞。其核心功能包括:

  1. 静态分析能力:通过解析PHP代码的token流来检测潜在漏洞
  2. 漏洞检测范围:支持15种预配置的漏洞类型(3种客户端+12种服务端)
  3. 开源版本:本文基于RIPS v0.55开源版本进行分析

二、核心架构与处理流程

1. 整体处理流程

RIPS的静态分析过程主要分为以下几个阶段:

  1. Token流解析:使用PHP内置函数token_get_all()将源代码转换为token数组
  2. Token流重构:对原始token流进行标准化处理
  3. Source识别:识别用户输入点
  4. Sink识别:识别危险函数调用
  5. 污点分析:追踪数据从source到sink的传播路径

2. Token流解析与重构

RIPS使用PHP的Tokenizer类(位于lib/scanner.php)进行token处理,主要包含以下重构步骤:

(1) prepare_tokens()

function prepare_tokens() {
    // 删除空白和无关token
    // 重写特殊token(如将<?=重写为echo)
    // 处理@错误抑制符
    // 将$array{index}重写为$array[index]
}

关键处理:

  • 删除PHP开始标签<?php和空格
  • 将闭合标签?>替换为分号;
  • <?=标签替换为echo
  • 删除错误抑制符@
  • 将数组花括号语法$array{index}转换为方括号语法$array[index]

(2) array_reconstruct_tokens()

function array_reconstruct_tokens() {
    // 处理多维数组
    // 将数组键名信息存储在token数组的第4个元素中
}

处理示例:

  • 对于$a[$b][][],将所有维度的键名存储在$a token的第四个数组元素中

(3) fix_tokens()

function fix_tokens() {
    // 处理反引号`xxx`转换为backticks()
    // 重构控制结构(if/for/foreach/while等)的花括号
    // 函数名小写处理
    // 处理do-while结构
}

关键处理:

  • 将反引号`command`转换为backticks(command)
  • 为没有花括号的控制结构添加花括号
  • 统一函数名为小写(PHP不区分大小写)
  • 将do-while结构转换为while结构

(4) fix_ternary()

function fix_ternary() {
    // 处理三元操作符
    // 删除?前面的判断条件,只保留两种取值情况
}

3. Source与Sink识别

(1) Source点(用户输入)

RIPS定义的source点主要包括三类:

  1. Other Input:HTTP头部、超全局数组等
    • $_GET, $_POST, $_COOKIE, $_REQUEST
    • $_SERVER中的特定参数
  2. 文件输入:从文件中读取的数据
  3. 数据库输入:从数据库查询获取的数据

(2) Sink点(危险函数)

RIPS预定义了15种漏洞类型的sink函数:

客户端漏洞(3种)

  1. XSSecho, print, printf, die, exit等输出函数
    • 过滤函数:htmlentities(), htmlspecialchars()
  2. HTTP头注入header(), setcookie()
  3. 会话固定session_start(), session_id()

服务端漏洞(12种)

  1. 代码执行eval(), assert(), preg_replace()(带/e修饰符)等
    • 过滤函数:preg_quote()
  2. 反射注入include, require
  3. 文件读取file_get_contents(), readfile()
    • 过滤函数:basename(), realpath()
  4. 文件系统操作unlink(), mkdir()
  5. 文件包含include, require
  6. 命令执行exec(), system(), passthru()
    • 过滤函数:escapeshellarg(), escapeshellcmd()
  7. SQL注入mysql_query(), mysqli_query()
  8. XPath注入xpath_eval()
  9. 反序列化unserialize()
  10. LDAP注入ldap_search()
  11. XXEsimplexml_load_string()
  12. 其他危险函数extract(), parse_str()

三、污点分析实现

1. 变量追踪

RIPS通过variable_add()函数跟踪变量赋值:

function variable_add($var_name, $tokens, $comment='', $tokenscanstart, $tokenscanstop, $linenr, $id, $array_keys=array(), $additional_keys=array()) {
    // 创建VarDeclare对象存储变量声明信息
    // 根据变量作用域(全局/局部)存储变量声明
}

处理逻辑:

  1. 创建VarDeclare对象存储变量信息(tokens子集、行号、token索引等)
  2. 根据变量作用域(函数内/外)将变量声明存入相应列表
  3. 处理全局变量$GLOBALS['x']转换为$x

2. 函数分析

当扫描到函数定义时:

else if($token_name === T_FUNCTION) {
    // 处理函数定义
    // 记录函数名、参数、位置等信息
    // 检查是否为POP gadget(反序列化利用链)
}

关键处理:

  1. 创建FunctionDeclare对象存储函数信息
  2. 记录函数参数(用于参数追踪)
  3. 检查是否为POP gadget(反序列化利用链中的方法)

3. 动态函数调用检测

RIPS通过variable_scan()检测动态函数调用:

function variable_scan($i, $offset, $category, $title) {
    // 检测变量作为函数名调用的情况
    // 如$func = $_GET['f']; $func();
}

处理逻辑:

  1. 创建VulnTreeNode记录漏洞信息
  2. 追踪变量值来源,检查是否包含用户输入
  3. 如果发现用户输入作为函数名,标记为代码执行漏洞

四、实际案例分析

1. 动态函数调用漏洞检测

示例代码:

$a = $_GET['tr1ple'];
function test() {
    $a();
}

RIPS检测流程:

  1. 扫描到$_GET['tr1ple']标记为source点
  2. 扫描到$a()函数调用,进入variable_scan()
  3. 追踪$a的值来源,发现来自$_GET
  4. 标记为代码执行漏洞

2. 数组键名处理

示例代码:

$a = array("key" => "value");
echo $a["key"];

处理流程:

  1. array_reconstruct_tokens()将数组键名"key"存储在$a token的第四个元素中
  2. 访问$a["key"]时可以直接获取键名信息

五、工具局限性

  1. PHP版本:开源版本较老(v0.55),不支持新版本PHP特性
  2. 漏洞覆盖
    • 缺少CSRF、SSRF、XXE等漏洞检测
    • 无法检测越权等逻辑漏洞
    • 反序列化仅检测unserialize(),不检测phar反序列化
  3. 误报/漏报:静态分析固有的问题

六、扩展建议

  1. 添加新漏洞检测
    • 实现SSRF检测(file_get_contents()带URL参数等)
    • 增强反序列化检测(支持phar)
  2. 改进分析算法
    • 实现更精确的跨文件分析
    • 添加过程间分析能力
  3. 支持新PHP特性
    • 命名空间
    • 匿名函数
    • 类型声明等

七、总结

RIPS作为PHP静态分析工具,其核心价值在于:

  1. 完整的token流解析与重构流程
  2. 精心设计的source与sink点定义
  3. 实用的污点分析实现
  4. 对PHP语言特性的深入理解

通过研究RIPS的实现,可以学习到:

  1. PHP静态分析的基本方法
  2. 如何设计一个实用的漏洞检测工具
  3. PHP语言特性与安全漏洞的关系
  4. 静态分析工具的常见挑战与解决方案
PHP静态分析工具RIPS深入解析 一、RIPS工具概述 RIPS是一款用于PHP代码静态分析的开源工具,主要用于检测PHP应用程序中的安全漏洞。其核心功能包括: 静态分析能力 :通过解析PHP代码的token流来检测潜在漏洞 漏洞检测范围 :支持15种预配置的漏洞类型(3种客户端+12种服务端) 开源版本 :本文基于RIPS v0.55开源版本进行分析 二、核心架构与处理流程 1. 整体处理流程 RIPS的静态分析过程主要分为以下几个阶段: Token流解析 :使用PHP内置函数 token_get_all() 将源代码转换为token数组 Token流重构 :对原始token流进行标准化处理 Source识别 :识别用户输入点 Sink识别 :识别危险函数调用 污点分析 :追踪数据从source到sink的传播路径 2. Token流解析与重构 RIPS使用PHP的 Tokenizer 类(位于 lib/scanner.php )进行token处理,主要包含以下重构步骤: (1) prepare_ tokens() 关键处理: 删除PHP开始标签 <?php 和空格 将闭合标签 ?> 替换为分号 ; 将 <?= 标签替换为 echo 删除错误抑制符 @ 将数组花括号语法 $array{index} 转换为方括号语法 $array[index] (2) array_ reconstruct_ tokens() 处理示例: 对于 $a[$b][][] ,将所有维度的键名存储在 $a token的第四个数组元素中 (3) fix_ tokens() 关键处理: 将反引号 `command` 转换为 backticks(command) 为没有花括号的控制结构添加花括号 统一函数名为小写(PHP不区分大小写) 将do-while结构转换为while结构 (4) fix_ ternary() 3. Source与Sink识别 (1) Source点(用户输入) RIPS定义的source点主要包括三类: Other Input :HTTP头部、超全局数组等 $_GET , $_POST , $_COOKIE , $_REQUEST $_SERVER 中的特定参数 文件输入 :从文件中读取的数据 数据库输入 :从数据库查询获取的数据 (2) Sink点(危险函数) RIPS预定义了15种漏洞类型的sink函数: 客户端漏洞(3种) : XSS : echo , print , printf , die , exit 等输出函数 过滤函数: htmlentities() , htmlspecialchars() 等 HTTP头注入 : header() , setcookie() 等 会话固定 : session_start() , session_id() 等 服务端漏洞(12种) : 代码执行 : eval() , assert() , preg_replace() (带/e修饰符)等 过滤函数: preg_quote() 反射注入 : include , require 等 文件读取 : file_get_contents() , readfile() 等 过滤函数: basename() , realpath() 文件系统操作 : unlink() , mkdir() 等 文件包含 : include , require 等 命令执行 : exec() , system() , passthru() 等 过滤函数: escapeshellarg() , escapeshellcmd() SQL注入 : mysql_query() , mysqli_query() 等 XPath注入 : xpath_eval() 等 反序列化 : unserialize() LDAP注入 : ldap_search() 等 XXE : simplexml_load_string() 等 其他危险函数 : extract() , parse_str() 等 三、污点分析实现 1. 变量追踪 RIPS通过 variable_add() 函数跟踪变量赋值: 处理逻辑: 创建 VarDeclare 对象存储变量信息(tokens子集、行号、token索引等) 根据变量作用域(函数内/外)将变量声明存入相应列表 处理全局变量 $GLOBALS['x'] 转换为 $x 2. 函数分析 当扫描到函数定义时: 关键处理: 创建 FunctionDeclare 对象存储函数信息 记录函数参数(用于参数追踪) 检查是否为POP gadget(反序列化利用链中的方法) 3. 动态函数调用检测 RIPS通过 variable_scan() 检测动态函数调用: 处理逻辑: 创建 VulnTreeNode 记录漏洞信息 追踪变量值来源,检查是否包含用户输入 如果发现用户输入作为函数名,标记为代码执行漏洞 四、实际案例分析 1. 动态函数调用漏洞检测 示例代码: RIPS检测流程: 扫描到 $_GET['tr1ple'] 标记为source点 扫描到 $a() 函数调用,进入 variable_scan() 追踪 $a 的值来源,发现来自 $_GET 标记为代码执行漏洞 2. 数组键名处理 示例代码: 处理流程: array_reconstruct_tokens() 将数组键名"key"存储在 $a token的第四个元素中 访问 $a["key"] 时可以直接获取键名信息 五、工具局限性 PHP版本 :开源版本较老(v0.55),不支持新版本PHP特性 漏洞覆盖 : 缺少CSRF、SSRF、XXE等漏洞检测 无法检测越权等逻辑漏洞 反序列化仅检测 unserialize() ,不检测phar反序列化 误报/漏报 :静态分析固有的问题 六、扩展建议 添加新漏洞检测 : 实现SSRF检测( file_get_contents() 带URL参数等) 增强反序列化检测(支持phar) 改进分析算法 : 实现更精确的跨文件分析 添加过程间分析能力 支持新PHP特性 : 命名空间 匿名函数 类型声明等 七、总结 RIPS作为PHP静态分析工具,其核心价值在于: 完整的token流解析与重构流程 精心设计的source与sink点定义 实用的污点分析实现 对PHP语言特性的深入理解 通过研究RIPS的实现,可以学习到: PHP静态分析的基本方法 如何设计一个实用的漏洞检测工具 PHP语言特性与安全漏洞的关系 静态分析工具的常见挑战与解决方案