PHP代码审计-入门指南篇

举报
亿人安全 发表于 2023/05/29 11:08:55 2023/05/29
【摘要】 序⾔PHP代码审计PHP代码审计是指对PHP程序源代码进⾏系统性的检查,它的⽬的是为了发现PHP程序存在的⼀些漏洞或者逻辑问题,避免程序缺陷被⾮法利⽤从⽽带来不必要的安全⻛险.⼯具准备Visual Studio Code 是⼀个开源免费的代码编辑器 本指南中使⽤该编辑器作为示例安装前往微软官⽹下载安装https://code.visualstudio.com/VS CODE 扩展商店拥有⼤量...

序⾔

PHP代码审计

PHP代码审计是指对PHP程序源代码进⾏系统性的检查,它的⽬的是为了发现PHP程序存在的⼀些漏洞或

者逻辑问题,避免程序缺陷被⾮法利⽤从⽽带来不必要的安全⻛险.

⼯具准备

Visual Studio Code 是⼀个开源免费的代码编辑器 本指南中使⽤该编辑器作为示例

安装

前往微软官⽹下载安装

https://code.visualstudio.com/

VS CODE 扩展商店拥有⼤量实⽤的扩展插件. 本⽂使⽤PHP Intelephense扩展⽤于辅助审计

插件

VS CODE 扩展商店拥有⼤量实⽤的扩展插件. 本⽂使⽤PHP Intelephense扩展⽤于辅助审计

点击左侧⼯具条扩展按钮安装图示进⾏安装

VS CODE 常⽤快捷键

使⽤快捷键可以⼤幅度地提升审计效率

关闭当前窗⼝: Ctrl+W

⽂件之间切换: Ctrl+T_a_b

移动到⾏⾸: Home

移动到⾏尾: End

移动到⽂件开头: Ctrl+Home

移动到⽂件结尾: Ctrl+End

查找/转到定义: F12

查找/转到引⽤: Shift+F12

代码格式化: Shift+Alt+F

查找: Ctrl+F

F9 打断点

F5 开始调试

在项⽬⽂件中搜索: Ctrl+Shift+F

插件辅助功能

前⽂中安装的插件提供了⼀些强⼤的功能 本书主要使⽤该插件的函数跳转追踪功能

该插件可以帮助你快速查找代码引⽤的函数/类/变量/常量 以及被引⽤的代码位置

将⿏标指针指向要查找的内容可以预览定义

按住ctrl 点击被引⽤对象可以快速跳转定义位置(或把光标放在查找位置 点击F12)

按住ctrl 点击定义可以快速查找项⽬中所有的引⽤位置(或把光标放在查找位置 点击Shift+F12)

这个功能在有复杂的⽂件包含时(如CMS框架)可以快速在众多⽂件中找到定义位置

PHP代码审计思路

这⾥列出⼏个审计思路 除了PHP外其他的⼤部分web开发语⾔

也可按照这个思路审计

PHP代码审计思路

敏感函数⽅法回溯(反向审计)

查找项⽬中的敏感函数⽅法 回溯传⼊的参数 判断⽤户是否可控 是否得到有效的过滤

缺点:很难发现越权等逻辑漏洞

⽤户可控参数追踪(正向审计)

查找项⽬中的⽤户输⼊ 追踪⽤户输⼊ 判断是否得到有效的过滤/调⽤敏感函数/存在逻辑问题

关键业务功能分析(功能审计)

专⻔审计易出现漏洞的关键功能点

如 头像上传 系统登陆 ⽂件下载 等功能

优点:可以快速完成审计 减少审计⾯ 可发现越权等逻辑漏洞

缺点:审计不完全

完全审计源代码

优点:完全覆盖源代码 可发现⼀些特殊条件的漏洞

缺点:耗时⻓ 容易遗漏

PHP⽤户可控输⼊速查表

来⾃⽤户可控的输⼊ --永远不要相信⽤户的输⼊

PHP敏感函数速查表

PHP⼀些容易出现安全问题的函数⽅法

命令执⾏

⼀些常⻅的可以执⾏系统命令的函数/语法

函数/语法 描述 例⼦

system 执⾏命令并输出结果 system('id');

exec 执⾏命令 只可获取最后⼀⾏结

exec('id',$a); print_r($a);

passthru 同 system passthru('id');

shell_exec ` (反引号) 执⾏命令并返回结果 $a=shell_exec('id');print_r($a);

$a=`id`;print_r($a);

popen 执⾏命令并建⽴管道 返回⼀个

指针 使⽤fread等函数操作指针

进⾏读写

$a=popen("id", "r"); echo

fread($a, 2096);

proc_open 同 popen (进程控制功能更强

⼤)

⻅PHP⼿册

pcntl_exec 执⾏命令 只返回是否发⽣错误 pcntl_exec('id');

代码注⼊/⽂件包含

函数/语法结构 描述 例⼦

eval 将传⼊的参数内容作为PHP代

码执⾏ eval 不是函数 是⼀种语

法结构 不能当做函数动态调⽤

eval('phpinfo();');

assert 将传⼊的参数内容作为PHP代

码执⾏ 版本在PHP7以下是函

数 PHP7及以上为语法结构

assert('phpinfo();');

preg_replace 当preg_replace使⽤/e修饰符

且原字符串可控时时 有可能执

⾏php代码

echo preg_replace("/e","

{${PHPINFO()}}","123");

call_user_func 把第⼀个参数作为回调函数调

⽤ 需要两个参数都完全可控才

可利⽤ 只能传⼊⼀个参数调⽤

call_user_func('assert',

'phpinfo();');

call_user_func_array 同call_user_func 可传⼊⼀个

数组带⼊多个参数调⽤函数

call_user_func_array

('file_put_contents',

['1.txt','6666']);

create_function 根据传递的参数创建匿名函

数,并为其返回唯⼀名称 利⽤

需要第⼆个参数可控 且创建的

函数被执⾏

$f =

create_function('','system($_

GET[123]);'); $f();

include 包含并运⾏指定⽂件 执⾏出错

会抛出错误

include 'vars.php'; (括号可有可

⽆)

require 同include 执⾏出错会抛出警告 require('somefile.php'); (括号

可有可⽆)

require_once 同require 但会检查之前是否已

经包含该⽂件 确保不重复包含

include_once 同include 但会检查之前是否已

经包含该⽂件 确保不重复包含

SQL/LDAP注⼊

函数/⽅法 备注

mysql_query

odbc_exec

mysqli_query

mysql_db_query

mysql_unbuffered_query

mysqli::query

⽤法

$mysqli = new mysqli("localhost", "my_user",

"my_password", "world");

$mysqli->query();

pg_query

pg_query_params

pg_send_query

pg_send_query_params

sqlsrv_query

pdo::query

$pdo=new

PDO("mysql:host=localhost;dbname=phpdem

o","root","1234"); $pdo->query($sql);;

PDO

SQLite3::query

SQLite3::exec

$db = new SQLite3('mysqlitedb.db'); $db-

>query('SELECT bar FROM foo'); $db-

>exec('CREATE TABLE bar (bar STRING)');

$mongo = new mongoclient(); $data = $coll-

>find($data);

https://wooyun.js.org/drops/Mongodb%E6%

B3%A8%E5%85%A5%E6%94%BB%E5%87

%BB.html

$ld = ldap_connect("localhost");…. $lb =

@ldap_bind($ld, "cn=test,dc=test,dc=com",

https://www.cnblogs.com/0nc3/p/12063436.

html

19

⽂件读取/SSRF

"test");

Db::query Thinkphp

Db::execute Thinkphp

⽂件上传/写⼊/其他

PHP原⽣过滤⽅法

过滤函数

escapeshellarg 传⼊参数添加单引号并转义原有单引号 ⽤于防⽌命令注⼊

例 传⼊ ' id # 处理后 '\' id #' 处理后的字符串可安全的添加到命令执⾏参数

escapeshellcmd 转义字符串中的特殊符号 ⽤于防⽌命令注⼊

反斜线(\)会在以下字符之前插⼊: &#;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 ' 和 " 仅在不配对⼉的时候被

转义

来⾃ <https://www.php.net/manual/zh/function.escapeshellcmd.php>

__

addslashes 在单引号(')、双引号(")、反斜线(\)与 NUL前加上反斜线 可⽤于防⽌SQL注⼊

mysqli::real_escape_string mysqli::escape_string mysqli_real_escape_string

mysql_real_escape_string SQLite3::escapeString

以上函数会在\x00(NULL), \n, \r, , ', " 和 \x1a (CTRL-Z) 前加上反斜线 并考虑了当前数据库连接字符

集进⾏处理

注意: 经过以上函数处理后的字符串不可直接⽤于sql查询拼接 需要使⽤引号包裹后拼接到sql语句中 否

则仍可导致sql注⼊

PDO::quote 转义特殊字符 并添加引号

PDO::prepare 预处理SQL语句 有效防⽌SQL注⼊ (推荐)

htmlspecialchars 和 htmlentities 将特殊字符转义成html实体 可⽤于防⽌XSS

intval($input) floatval() floatval() floor() (int)$input num+0 将输⼊强制转换为整数/浮点 常⻅于防⽌

SQL注⼊

todo

防护配置项

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。