前一陣和前同事交流在檢測webshell方面的相關方法,其中提出了使用lex yacc做一套語法解析來解析字節碼段來判斷是否存在webshell。
后來在查找相關資料中,找到了github開源的一個工具:PHP-Parser。能夠把php文件解析AST(抽象語法樹)
Project: https://github.com/nikic/PHP-Parser
安裝:
php composer.phar require nikic/php-parser
例如:
<?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";
轉儲AST為:
array( 0: Stmt_Function( byRef: false name: Identifier( name: test ) params: array( 0: Param( type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( 0: Stmt_Expression( expr: Expr_FuncCall( name: Name( parts: array( 0: var_dump ) ) args: array( 0: Arg( value: Expr_Variable( name: foo ) byRef: false unpack: false ) ) ) ) ) ) )
可以看到各個節點的含義,相比較查看opcode然后再去解析容易的多,opcode比較晦澀難懂。
如果做得好,再進行回歸成原始的代碼,例如webshell中存在很多字符串拼接、函數拼接等操作。回歸最終原始代碼,再去檢測會變得容易的多。
關於php-parser的文檔也有很多:
https://github.com/nikic/PHP-Parser/tree/master/doc
我個人的目前思路:
1、獲取web目錄
2、對每個php文件生成AST
3、解析AST,進行語法回歸,轉儲原始代碼 // 這個地方比較有難度
4、使用多引擎(正則、機器學習、第三方接口)進行判斷文件是否異常。
