PHP代码审计:从入门到懵逼
代码审计顾名思义就是检查源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞,并提供代码修订措施和建议。
PHP代码审计
审计套路
通读全文法 (麻烦,但是最全面)
敏感函数参数回溯法 (最高效,最常用)
定向功能分析法 (根据程序的业务逻辑来审计)
初始安装
信息泄露
文件上传
文件管理
登录认证
数据库备份恢复
找回密码
验证码
越权
注入
第三方组件
CSRF,SSRF,XSS......
审计方法
1.获取源码
2.本地搭建调试可先使用扫描器识别常见传统漏洞,验证扫描器结果,手动正则
3.把握大局对网站结构,入口文件(查看包含了哪些文件),配置文件(看数据库编码),路由,伪全局变量和全局 filter,资源加载顺序,了解数据库处理模式,考察 filter 是否绕过,了解 XSS 过滤机制,考察 filter 是否可绕过,错误信息输出控制,对每个模块的功能进行了解,配合文件数据库监控,从安装到后台功能使用和前台功能使用走一波,仔细观察每步的变化,找不到问题再开始认真审计
常见漏洞
安装问题
1.自动删除这个安装文件
通过生成一个lock文件来判断程序是否安装过
2.根本无验证
安装完成后不会自动删除文件,又不会生成lock判断是否安装过
参考漏洞:PHPSHE B2C 重装
wooyun-2014-062047.html
3.安装 file
直接用 GET 提交 step 绕过,直接进入下一步
4.变量覆盖导致重装
可以 GET,POST,COOKIE 任意提交一个变量名 $insLockfile, 给其赋空值,覆盖掉 $insLockfile, 从而让 file_exists 为 false 就不会退出
参考漏洞:frcms 重装系统
wooyun-2014-073244.html
5.判断 lock 后,无 exit
判断是否存在 lock 文件,如果存在 lock 文件,就会 header 到 index.php, 但是 header 后并没有 exit,所以 并不会退出,类似的还有 javascript 弹个框
参考漏洞:开源轻论坛 StartBBS 前台 getshell
wooyun-2013-045143.html
6.解析漏洞
在安装完成后会将 install.php 重命名为 index.php.bak, 但是由于 Apache 的解析漏洞:如果无法识别到最后一个后缀的话,就会向上解析,那么就又变成了 php 了,然后结合安装时的变量覆盖又成重装了。
7.满足一些条件不会退出的
参考漏洞:建站之星 Sitestar 前台 Getshell 一枚
wooyun-2014-054387.html
包含漏洞
1.本地文件包含
很多都限制了包含的后缀结尾必须为.php,例如
include($a.".php")
,需要截断后面的.php
截取字符判断是不是 .php
用 zip (或者 phar )协议绕过
首先新建一个 1.php,里面 phpinfo,然后压缩成 .zip,然后把 zip 的名字改成 yu.jpg,然后把这个 .jpg 上传上去,然后包含Example:
http://localhost/php/include.php?include_file=zip://C:wampwww.php1.jpg%231.php`
00 截断
gpc off && php < 5.3.4
长文件名截断
转换字符集造成的截断
<iconv()截断>
伪协议
包含日志,环境变量
2.见 <PHP技巧之截断>
3.远程文件包含
allow_url_include 为 on ,allow_url_fopen 为 off
伪协议:
allow_url_include && allow_url_fopen 为 off
包含共享文件:
互联网上 445 端口基本上被过滤
包含远程文件,或者伪协议
php://input data
等条件:
allow_url_include on
,默认是off
allow_url_include off
条件下 RFIallow_url_fopen 默认是 on
找回密码
1.验证token
在找回密码的时候生成一个 token, 然后存储到数据库中,然后把找回密码的地址发到邮箱中,url 中就含有 token,由用户点开后就能修改密码
2.延伸
一些 cms 的密码加密方式很难破掉,有时候拿到了管理的密码破不开,利用方法:一般找回密码是用的邮箱,首先把管理的邮箱注入出来,然后再去找回密码,再把数据库的 token 注入出来,构造一下地址,就能重置密码
3.rand函数生成token
$resetpwd=md5((rand());
对 rand() 函数生成出来的数字进行 MD5
某些平台下( 例如 windows ) RAND_MAX 只有 32768,如果需要的范围大于 32768,那么指定 min 和 max 参数就可以生成大于 RAND_MAX 的数了,或者考虑用 mt_rand() 来替代它
参考漏洞:Thinksaas 找回密码处设计错误利用账户可找回密码
wooyun-2014-050304.html
$encryptstring=md5($this->time.$verification.$auth);
$timetemp=date("Y-m-d H:i:s",$this->time);$auth=util::strcode($timetemp,"ENCODE");`
算法的 KEY 并没有初始化,如果知道了这个时间,就可以生成加密的字符串
参考漏洞:Hdwiki 设计缺陷知邮箱可改密码(包括管理员)
wooyun-2014-067410.html
上传漏洞
1.未验证上传后缀
2.验证上传后缀被bypass
3.上传的文件验证了上传后缀,但是文件名不重命名
截断
yu.php%00.jpg
4.上传路径可控
5.解析漏洞
Nginx
yu.jpg/1.php
Apache
yu.php.xxx
6.验证方法
MIME, 客户端的 JS 验证,白名单,黑名单
7.绕过
大小写
文件名没 trim
在文件名后面加空格,windows 下的
x.php%81-%99
decode 后仍为x.php
, windows 下的特性.php::$data
文件操作
任意文件删除,任意文件复制,任意文件重命名,任意文件移动,任意文件下载
首先尝试拿到配置文件中的数据库连接账号和密码,然后外链
拿到配置文件,拿到加密解密函数的 key,生成加密字符串,结合具体的代码利用
1.文件删除
由于全局的过滤而不能注入时,可以用任意文件删除删掉这个文件
删除安装文件生成的 lock 文件,重装
参考漏洞:phpcms 2008 sp4 爆路径及任意文件删除漏洞
wooyun-2010-0412.html
2.文件复制
要复制的文件 要复制的路径
当两个都完全可控,可以直接把自己上传的图片复制成一个 .php 马
复制的文件可控 要复制的路径不可控
copy(ROOT_PATH."$webdb[updir]/$value",ROOT_PATH."$webdb[updir]/{$value}.jpg")
可以把 $value 控制为保存了 qibocms 的加密函数的 key 的配置文件,复制后成一个 .jpg 直接打开就可以看到 key
3.文件下载
下载配置文件,拿到 key
参考漏洞:qibocmsV7 整站系统任意文件下载导致无限制注入多处
wooyun-2014-066459.html
4.文件写入
5.文件包含
加密函数
拿到加密函数的 key, 加密一些特殊字符然后拿到加密的字符串
1.加密可逆
弱算法导致了知道明文,知道密文,可逆,拿到加密函数的 key,从而自己生成一个想要的加密字符串
参考漏洞:DedeCMS-V5.7-SP1(2014-07-25)sql 注入+新绕过思路
wooyun-2014-071655.html
参考漏洞:phpcms 最新版绕过全局防御暴力注入
wooyun-2014-066138.html
2.加密可控
要加密的内容是可控的,密文会输出,这个可控的点能引入特殊字符,那么把一些特殊字符带入到这里面,拿到密文,再找到一处 decode 后会进行特殊操作的点,然后进行各种操作。
参考漏洞:程氏舞曲 CMS 某泄露,导致 sql 注入
wooyun-2014-080370.html
参考漏洞:PHPCMS最新版 ( V9 ) SQL 注入一枚
wooyun-2013-024984.html
3.key泄露
参考漏洞:一个 PHPWIND 可拿 shell 的高危漏洞
wooyun-2014-072727.html
XSS
1.输入输出
2.foreach()的key值
3.removeXSS函数
多个函数处理,插入辣鸡数据绕过第一个函数后,第二个函数过滤了辣鸡数据
CSRF
1.后台敏感操作
2.修改权限、导出数据等高危功能
3.Login Form CSRF
SSRF
1.绕过本地 IP 过滤(畸形 IP,本地网段覆盖不完全)
2.协议白名单
3.跳转到本地 IP
4.DNS 解析到本地 IP
5.DNS rebinding
6.Content-Disposition:attachment;filename="evil_file.exe;.txt" 分号截断可绕过跳板机的 filter
撸库
1.失败后没有清空 session 中的验证码
2.ip 第一次出现,验证码为默认值
3.验证码 md5 显示在 cookie 中
4.session 保存到文件
命令注入
常见命令注入函数
sysytem()
exec()
passthru()
shell_exec()
call_user_func()
array_map()
array_filter()
usort()
pcntl_exec()
popen()
proc_open()
mail() ---> PHPmail RCE
$_GET["a"]($_GET["b"])
登录认证
1.session
2.算法
XXE
simplexml_load_string()
默认情况下会解析外部实体,造成安全威胁,导致任意文件读取、命令执行漏洞。
越权
1.通过 ID 操作
2.通过 cookie 操作
注入
把用户可控的一些变量,带入到了数据库的各种操作中,并且没有做好过滤,例如:在注册用户的时候检测用户名是否存在,SQL 语句是拼接 SQL
1.select注入
一般使用 union select 联合查询
2.update注入
update set 的位置
看这个表的哪个 column 会被展示出来,就把查询出来的内容显示到这里
where 后
通过盲注的方式列出数据
3.insert注入
把要输出的数据插入到这个 column 里面去
4.delete注入
通过盲注的方式列出数据
5.数字型注入
变量并没有用单引号括住,不需要用单引号区分数据与 SQL 命令,这样就会让一般的GPC等机制无用,因为不包括特殊字符强制类型转换 intval
6.字符型、搜索型
有单引号括住,需要闭合单引号
全局没有做 addslashes,在查询的时候再对一些用户可控的变量进行 addslashes, 遗漏了某些变量没 addslashes
全局做 addslashes,在全局文件中对 GET POST COOKIE 做 addslashes
首先
get magic quotes gpc
判断 GPC 是否开启,如果没开启就调用 addslashes 来转义,如果开启就不调用 addslashes
7.Magic_quotes_gpc
Magic_quotes_gpc 在稍微高点的版本默认都是 on,5.4 已经废除,
",",,NULL
会在前面添加上一个转义符
8.宽字节注入
数据库字符集 GBK 的宽字节注入
数据库的连接方式不同,数据库与 PHP 的编码不一致,转换过程中可能存在
错误方法:
set names gbk
转换字符集造成的宽字节注入
从 gbk 转到 utf8
参考漏洞:74cms 最新版 注入 8-9
wooyun-2014-063225.html
从 utf8 转到 gbk,尽从 UTF8 转成 GBK 之后成了
%e5%5c
,对 GET POST COOKIE 做了 addslashes,"
转义后为"->%5c %e5%5c5c"
两个,则引号出来
参考漏洞:qibocms 下载系统 SQL 注入一枚
wooyun-2014-055842.html
9.解码导致
先提交 encode 的,那么就能不被转义,decode 后再带入查询,造成了注入,无视 GPC
urlencode
base64_decode
XML
Json_decode
参考漏洞:qibocms B2b 注入一枚
wooyun-2014-053187.html
参考链接:phpdisk V7 sql 注入 2
wooyun-2014-056822.html
10.变量覆盖
变量覆盖有 extract、parse_str、$$
$$
参考漏洞:MetInfo 最新版 (5.2.4) 一处 SQL 盲注漏洞
wooyun-2014-055338.html
extract
extract($_POST)
直接从 POST 数组中取出变量,覆盖掉之前的一些变量,覆盖的话,一般是覆盖掉表前缀之类的。selet * from $pre_admin where xxx
像这种就覆盖掉 $pre,然后直接补全语句注入
参考漏洞:qibocms 分类注入一枚可提升自己为管理
wooyun-2014-053189.html
参考漏洞:phpdisk V7 sql 注入 2
wooyun-2014-051734.html
11.Replace
有时会把
""
都替换成空,然后提交之后去掉了"
,不把"
替换成空,但是"
也会被转义,那么提交一个"
就又剩下了一个转义符了。参考漏洞:PHPCMS 全版本通杀 SQL 注入漏洞
wooyun-2014-050636.html
一些 replace 是用户可控的,就是说用户可以控制替换为空的内容
$order_sn=str_replace($_GET["subject"],"",$_GET["out_trade_no"]);
这里因为会被转义,如果提交
"
就变成"
,并且这里替换为空的内容 get 来的,那就想办法把替换掉 addslashes 会对
", ", , NULL
转义,"
变成"
,"
变成"
,变成
\
,NULL
变成