学习静态代码审计_第二站:简单解读php-parser项目
Posted 南瓜__pumpkin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习静态代码审计_第二站:简单解读php-parser项目相关的知识,希望对你有一定的参考价值。
前言
第一次接触这个项目,是2021强网杯的pop-master题目,也是这道题目给我打开了静态代码审计的大门。后来了解静态代码审计的发展历程,又接触到了昆仑镜项目。php-parse项目都下载三遍了,这次要搞定她!
PHP Parser 是由 nikic 开发的一款 php 抽象语法树(AST)解析工具。项目地址:https://github.com/nikic/PHP-Parser。
项目作者:nikic是PHP的主要contributor,目前在Jetbrains旗下的PhpStorm项目工作,并且开发过许多PHP的开源库。他也是LLVM项目的开发者。
项目官方说明
0x01 PHP解析器
使用PHP编写的适合 php5.2 - php8.0 的解析器,用于简化静态代码分析和操作。
Documentation for version 4.x (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.0),文档地址:https://github.com/nikic/PHP-Parser/tree/master/doc.
Documentation for version 3.x (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2),文档地址:https://github.com/nikic/PHP-Parser/tree/3.x/doc.
0x02 功能
主要功能如下,其中前4项功能相比之下更具可用性。
- 把PHP5、PHP7、PHP8的代码转换成抽象语法树AST
- 无效代码会被解析成一个部分抽象语法树
- 生成的AST包含准确的位置信息
- 使用可读性高的表格转储生成的AST
- 把AST转回PHP代码
- 试验的:修改后的AST可以被格式化保存
- 遍历和修改AST
- 命名空间名称的解析
- 常数表达式的求值
- 简化AST结构的构造器 for 代码生成
- 来回转换抽象语法树和Json数据
0x03 快速开始
(1)使用PHP依赖管理工具Composer安装,由于本地Composer是全局配置,所以命令有所不同。
composer require nikic/php-parser
cd ./vendor/nikic/php-parser/
(2)运行测试代码:nikic给出的代码示例如下,使用该软件,只需要把需要审计的代码放到$code变量中即可。
<?php
use PhpParser\\Error;
use PhpParser\\NodeDumper;
use PhpParser\\ParserFactory;
$code = <<<'CODE'
<?php
function test($foo)
{
var_dump($foo);
}
CODE;
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
$ast = $parser->parse($code);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\\n";
return;
}
$dumper = new NodeDumper;
echo $dumper->dump($ast) . "\\n";
测试:在nikic/php-parser/lib/目录下新建MyASTest.php,复制粘贴示例代码,使用测试代码替换7-12行的代码。
<?php
var_dump(token_get_all('<?php echo "hello"; $a=1;echo $a+$a;?>'));
?>
报错信息:使用PHPStorm打开MyASTest.php文件,使用PHP7.3.24命令解释器,发生报错。(完全使用示例代码也有相同报错)
PHP Fatal error: Uncaught Error: Class 'PhpParser\\ParserFactory' not found in /Users/didi/Downloads/vendor/nikic/php-parser/lib/MyASTest.php:15
Stack trace:
#0 {main}
thrown in xxx.php on line 15
网上并没有找到明确的解决方式,但通过查阅use相关资料得知,use只是使用了命名空间,但是要想调用类,必须要加载类文件,或者自动加载。根据报错信息可以知道,use起作用了,但class类没有引用成功。
尝试1-可行:使用自动加载。autoload.php文件在vendor目录下,通过目录遍历去包含该文件。比如本地在MyASTest.php文件第5行添加的代码如下,运行结果如图。
require_once __DIR__ . '/../../../autoload.php';
(3)遍历AST并执行某种操作,比如丢掉抽象语法树AST中某个函数的所有函数体。
使用Class NodeTraverser,运行相关代码之后可以发现,只保留了Stmt_Function数组,stmts数组的内容被清空了。这意味着,我们可以对得到的AST语法树进行比较灵活的操作。(我愿称之为二次操作)
(4)把得到的AST语法树转回PHP代码。
这个步骤很适合Webshell检测。使用PrettyPrinter文件中的Class PrettyPrinter\\Standard,但是作者给出的例子中,却没有还原函数体,具体点就是 减去了函数中var_dump()的调用
。该软件还原代码的可用性有多大,还需要进一步探究。
(5)For a more comprehensive introduction, see the documentation。
0x04 文档
基础组件的使用这部分,其实相当重要。但持恒之初忌深远,贪多嚼不烂,后续更文再深入分析,一定记得多读文档方能熟能生巧。
- Introduction
- Usage of basic components
下一篇学习研究PHP-Parse的使用,通过聚焦某些应用场景,比如基于该软件寻找强网杯pop-master题目的RCE pop链、探索该软件在代码审计领域的应用场景等。希望可以做到对这个PHP编写的PHP解析器项目烂熟于心,成为迈向代码安全领域坚实的一步。
参考
《PHP Parser 简介和应用 - 为你的代码自动补全单元测试》,文章地址:https://learnku.com/articles/21846。
《PHP中的use、命名空间、引入类文件、自动加载类的理解》,文章地址:https://blog.csdn.net/github_37767025/article/details/68064974
以上是关于学习静态代码审计_第二站:简单解读php-parser项目的主要内容,如果未能解决你的问题,请参考以下文章