前一阵和前同事交流在检测webshell方面的相关方法,其中提出了使用lex yacc做一套语法解析来解析字节码段来判断是否存在webshell。
后来在查找相关资料中,找到了github开源的一个工具:PHP-Parser。能够把php文件解析AST(抽象语法树)
Project:/nikic/PHP-Parser
安装:
php composer.phar require nikic/php-parser
例如:
{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 = newNodeDumper;echo $dumper->dump($ast) . "\n";
转储AST为:
array(0:Stmt_Function(
byRef: falsename:Identifier(
name:test
)
params: array(0:Param(
type: nullbyRef: falsevariadic: false
var:Expr_Variable(
name:foo
)default: null)
)
returnType: nullstmts: 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的文档也有很多:
/nikic/PHP-Parser/tree/master/doc
我个人的目前思路:
1、获取web目录
2、对每个php文件生成AST
3、解析AST,进行语法回归,转储原始代码 // 这个地方比较有难度
4、使用多引擎(正则、机器学习、第三方接口)进行判断文件是否异常。