代码审计顾名思义就是检查源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞,并提供代码修订措施和建议。PHP代码审计审计套路通读全文法 (麻烦,但是最全面)敏感函数参数回溯法 (最高效,最常用)定向功能分析法 (根据程序的业务逻辑来审计)初始安装信息泄露文件上传文件管理登录认证数据库备份恢复找回密码验证码越权注入第三方组件CSRF,SSRF,XSS......审计方法1.获取源码2.本地搭建调试可先使用扫描器识别常见传统漏洞,验证扫描器结果,手动正则3.把握大局对网站结构,入口文件(查看包含了哪些文件),配置文件(看数据库编码),路由,伪全局变量和全局 filter,资源加载顺序,了解数据库处理模式,考察 filter 是否绕过,了解 XSS 过滤机制,考察 filter 是否可绕过,错误信息输出控制,对每个模块的功能进行了解,配合文件数据库监控,从安装到后台功能使用和前台功能使用走一波,仔细观察每步的变化,找不到问题再开始认真审计常见漏洞安装问题1.自动删除这个安装文件通过生成一个lock文件来判断程序是否安装过2.根本无验证安装完成后不会自动删除文件,又不会生成lock判断是否安装过参考漏洞:PHPSHE B2C 重装3.安装 file直接用 GET 提交 step 绕过,直接进入下一步4.变量覆盖导致重装可以 GET,POST,COOKIE 任意提交一个变量名$insLockfile, 给其赋空值,覆盖掉 $insLockfile, 从而让 file_exists 为 false 就不会退出参考漏洞:frcms 重装系统5.判断 lock 后,无 exit判断是否存在 lock 文件,如果存在 lock 文件,就会 header 到 index.php, 但是 header 后并没有 exit,所以 并不会退出,类似的还有 javascript 弹个框参考漏洞:开源轻论坛 StartBBS 前台 getshell6.解析漏洞在安装完成后会将 install.php 重命名为 index.php.bak, 但是由于 Apache 的解析漏洞:如果无法识别到最后一个后缀的话,就会向上解析,那么就又变成了 php 了,然后结合安装时的变量覆盖又成重装了。7.满足一些条件不会退出的参考漏洞:建站之星 Sitestar 前台 Getshell 一枚包含漏洞1.本地文件包含很多都限制了包含的后缀结尾必须为.php,例如,需要截断后面的截取字符判断是不是 .php用 zip (或者 phar )协议绕过首先新建一个 1.php,里面 phpinfo,然后压缩成 .zip,然后把 zip 的名字改成 yu.jpg,然后把这个 .jpg 上传上去,然后包含Example:http://localhost/php/include.php?include_file=zip://C:\wamp\www.php\1.jpg%231.php`00 截断长文件名截断转换字符集造成的截断伪协议包含日志,环境变量
2.见3.远程文件包含
allow_url_include 为 on ,allow_url_fopen 为 off伪协议:
allow_url_include && allow_url_fopen 为 off包含共享文件:
互联网上 445 端口基本上被过滤
包含远程文件,或者伪协议等条件:,默认是条件下 RFIallow_url_fopen 默认是 on找回密码1.验证token在找回密码的时候生成一个 token, 然后存储到数据库中,然后把找回密码的地址发到邮箱中,url 中就含有 token,由用户点开后就能修改密码2.延伸一些 cms 的密码加密方式很难破掉,有时候拿到了管理的密码破不开,利用方法:一般找回密码是用的邮箱,首先把管理的邮箱注入出来,然后再去找回密码,再把数据库的 token 注入出来,构造一下地址,就能重置密码3.rand函数生成token对 rand() 函数生成出来的数字进行 MD5某些平台下( 例如 windows ) RAND_MAX 只有 32768,如果需要的范围大于 32768,那么指定 min 和 max 参数就可以生成大于 RAND_MAX 的数了,或者考虑用 mt_rand() 来替代它参考漏洞:Thinksaas 找回密码处设计错误利用账户可找回密码$timetemp=date("Y-m-d H:i:s",$this->time);$auth=util::strcode($timetemp,'ENCODE');`算法的 KEY 并没有初始化,如果知道了这个时间,就可以生成加密的字符串参考漏洞:Hdwiki 设计缺陷知邮箱可改密码(包括管理员)上传漏洞1.未验证上传后缀2.验证上传后缀被bypass3.上传的文件验证了上传后缀,但是文件名不重命名截断4.上传路径可控5.解析漏洞NginxApache
6.验证方法
MIME, 客户端的 JS 验证,白名单,黑名单
7.绕过
大小写文件名没 trim在文件名后面加空格,windows 下的decode 后仍为, windows 下的特性文件操作任意文件删除,任意文件复制,任意文件重命名,任意文件移动,任意文件下载首先尝试拿到配置文件中的数据库连接账号和密码,然后外链拿到配置文件,拿到加密解密函数的 key,生成加密字符串,结合具体的代码利用1.文件删除由于全局的过滤而不能注入时,可以用任意文件删除删掉这个文件删除安装文件生成的 lock 文件,重装参考漏洞:phpcms 2008 sp4 爆路径及任意文件删除漏洞
2.文件复制
要复制的文件 要复制的路径当两个都完全可控,可以直接把自己上传的图片复制成一个 .php 马复制的文件可控 要复制的路径不可控copy(ROOT_PATH."$webdb[updir]/$value",ROOT_PATH."$webdb[updir]/{$value}.jpg")可以把 $value 控制为保存了 qibocms 的加密函数的 key 的配置文件,复制后成一个 .jpg 直接打开就可以看到 key
3.文件下载下载配置文件,拿到 key参考漏洞:qibocmsV7 整站系统任意文件下载导致无限制注入多处4.文件写入5.文件包含
加密函数拿到加密函数的 key, 加密一些特殊字符然后拿到加密的字符串1.加密可逆弱算法导致了知道明文,知道密文,可逆,拿到加密函数的 key,从而自己生成一个想要的加密字符串参考漏洞:DedeCMS-V5.7-SP1(2014-07-25)sql 注入+新绕过思路参考漏洞:phpcms 最新版绕过全局防御暴力注入2.加密可控要加密的内容是可控的,密文会输出,这个可控的点能引入特殊字符,那么把一些特殊字符带入到这里面,拿到密文,再找到一处 decode 后会进行特殊操作的点,然后进行各种操作。参考漏洞:程氏舞曲 CMS 某泄露,导致 sql 注入参考漏洞:PHPCMS最新版 ( V9 ) SQL 注入一枚3.key泄露参考漏洞:一个 PHPWIND 可拿 shell 的高危漏洞XSS1.输入输出2.foreach()的key值3.removeXSS函数多个函数处理,插入辣鸡数据绕过第一个函数后,第二个函数过滤了辣鸡数据CSRF1.后台敏感操作2.修改权限、导出数据等高危功能3.Login Form CSRFSSRF1.绕过本地 IP 过滤(畸形 IP,本地网段覆盖不完全)2.协议白名单3.跳转到本地 IP4.DNS 解析到本地 IP5.DNS rebinding6.分号截断可绕过跳板机的 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登录认证1.session2.算法XXEsimplexml_load_string()默认情况下会解析外部实体,造成安全威胁,导致任意文件读取、命令执行漏洞。越权1.通过 ID 操作2.通过 cookie 操作注入把用户可控的一些变量,带入到了数据库的各种操作中,并且没有做好过滤,例如:在注册用户的时候检测用户名是否存在,SQL 语句是拼接 SQL1.select注入一般使用 union select 联合查询2.update注入update set 的位置看这个表的哪个 column 会被展示出来,就把查询出来的内容显示到这里where 后通过盲注的方式列出数据
3.insert注入把要输出的数据插入到这个 column 里面去4.delete注入通过盲注的方式列出数据5.数字型注入变量并没有用单引号括住,不需要用单引号区分数据与 SQL 命令,这样就会让一般的GPC等机制无用,因为不包括特殊字符强制类型转换intval6.字符型、搜索型
有单引号括住,需要闭合单引号全局没有做 addslashes,在查询的时候再对一些用户可控的变量进行 addslashes, 遗漏了某些变量没 addslashes全局做 addslashes,在全局文件中对 GET POST COOKIE 做 addslashes首先判断 GPC 是否开启,如果没开启就调用 addslashes 来转义,如果开启就不调用 addslashes
7.Magic_quotes_gpc
Magic_quotes_gpc 在稍微高点的版本默认都是 on,5.4 已经废除,会在前面添加上一个转义符
8.宽字节注入
数据库字符集 GBK 的宽字节注入数据库的连接方式不同,数据库与 PHP 的编码不一致,转换过程中可能存在错误方法:转换字符集造成的宽字节注入从 gbk 转到 utf8参考漏洞:74cms 最新版 注入 8-9从 utf8 转到 gbk,尽从 UTF8 转成 GBK 之后成了,对 GET POST COOKIE 做了 addslashes,转义后为两个,则引号出来参考漏洞:qibocms 下载系统 SQL 注入一枚
9.解码导致
先提交 encode 的,那么就能不被转义,decode 后再带入查询,造成了注入,无视 GPCurlencodebase64_decodeXMLJson_decode参考漏洞:qibocms B2b 注入一枚参考链接:phpdisk V7 sql 注入 2
10.变量覆盖变量覆盖有 extract、parse_str、$$
$$参考漏洞:MetInfo 最新版 (5.2.4) 一处 SQL 盲注漏洞extract直接从 POST 数组中取出变量,覆盖掉之前的一些变量,覆盖的话,一般是覆盖掉表前缀之类的。selet * from $pre_admin where xxx像这种就覆盖掉 $pre,然后直接补全语句注入参考漏洞:qibocms 分类注入一枚可提升自己为管理参考漏洞:phpdisk V7 sql 注入 2
11.Replace
有时会把都替换成空,然后提交之后去掉了,不把替换成空,但是也会被转义,那么提交一个就又剩下了一个转义符了。参考漏洞:PHPCMS 全版本通杀 SQL 注入漏洞一些 replace 是用户可控的,就是说用户可以控制替换为空的内容$order_sn=str_replace($_GET['subject'],'',$_GET['out_trade_no']);这里因为会被转义,如果提交就变成,并且这里替换为空的内容 get 来的,那就想办法把替换掉 addslashes 会对转义,变成,变成,变成,变成, 提交会被转义生成,这时候再提交把 0 替换成空,那么就剩下,表示的转义,单引号也就成功出来了。参考漏洞:cmseasy 绕过补丁 SQL 注入一枚把替换成空,但是通过又全局有转义单引号转义为,然后替换为空格,留下,注释掉, 破坏原本的 SQL, 用户提交一个全局转义成, 然后这过滤函数又会把替换成空,那么就留下导致可以吃掉一个单引号。需要 double query ,两处可控输入select * from c_admin where username=' admin\' and email=' inject#'
12.server 注入-只对 GET POST COOKIE 进行 addslashes,没有对 SERVER 进行转义,一些 server 的变量,用户可控并写入数据库QUERY_STRING , X_FORWARDED_FOR , CLIENT_IP , HTTP_HOST , ACCEPT_LANGUAGE最常见的当然也就是 X_FORWARDED_FOR,一般是在 IP 函数中用户,没有验证 ip 是否合法,直接 return。参考漏洞:Phpyun 注入漏洞二
正则验证错误参考漏洞:CmsEasy 最新版本无限制 SQL 注射
13.file 注入
全局只对 GET POST COOKIE 转义,遗漏了 files,,且不受 GPC,files 注入一般是因为上传,会把上传的名字带到 insert 当中入库参考漏洞:qibocms 黄页系统 SQL 注入一枚在入库的时候对文件的名字进行转义,在获取后缀后再入库时对文件名转义了却没有对后缀转义也导致了注入参考漏洞:Supesite 前台注入 #2 (Insert)
14.未初始化造成的注入php < 4.20 时,register_globals 默认都是 on, 逐渐 register_globals 默认都是 off伪全局机制,遗漏了初始化参考漏洞:qibocms 地方门户系统注入一个问题参考漏洞:qibocms 地方门户系统注入参考漏洞:齐博地方门户系统 SQL 注入漏洞参考漏洞:齐博整站/地方门户 SQL 注入漏洞15.数组中的key判断 GPC 是否开启,如果 off 就对数组中的 value 进行 addslashes,没有对数组中的 key 进行转义,key 带入 sql,听说低版本的 php 对二维数组中的 key 就算 GPC ON 也不会转义参考漏洞:qibocms V7 整站系统最新版 SQL 注入一枚 & 另外一处能引入转义符的地方。参考漏洞:qibocms 多个系统绕过补丁继续注入参考漏洞:qibocms全部开源系统 Getshell参考漏洞:Discuz 5.x 6.x 7.x 前台 SQL 注入漏洞一枚16.offset提交的是一个数组,且含有一个 key 为 0,那么就是对应的这个 key 的 value,但是这里并没有强制要求为数组。提交一个字符串就为了, 吃掉一个单引号,然后就在 $b 处写入 inject 可以注入参考漏洞:qibocms 地方门户系统17.第三方插件常见的 uc_cencert / alipay / tenpay / chinabank
默认 UC 里面都会 striplashesuckey 默认的uckey 这个常量没有初始化uckey 可控参考漏洞:phpmps 注入 (可修改其他用户密码,官网成功)--UC参考漏洞:PHPEMS (在线考试系统) 设计缺陷 Getshell一枚(官网已 shell )--UC参考漏洞:最土团购注入一枚可直接提升自己为管理 & 无限刷钱。--CHINABANK参考漏洞:Destoon Sql 注入漏洞 2(有条件)--TENPAY参考漏洞:Destoon Sql 注入漏洞一枚(有条件)--TENPAY参考漏洞:CSDJCMS 程式舞曲最新版 Sql 一枚--TENPAY
18.数字型注入
PHP 弱类型语言参考漏洞:phpyun v3.2 (20141226) 两处注入。一般数字型的都不会加单引号,$id 没被单引号且没有被强制类型转换参考漏洞:qibocms 地方门户系统 注入#3不是一些数字型,忘记加单引号$query=$_SGLOBAL['db']->query('select * from '.tname('spacetags').' where itemid=\''.$itemid.'\' and status = \''.status.'\'');$itemid 首先带入查询中,被单引号,如果查询有接过才会带入到 delete 中,如果无接过就不执行 delete。在数据库中 itemid 中存储的是 int 类型,所以这里本意是只能提交数字型才能查询出结果,如果不是提交数字的话,那么就查询不出来结果,就不去执行下面的 delete 语句了。但是由于 mysql 的类型转换,因为这里存储的是 int 类型,所以 4xxxx 跟 4 是一样的。$_SGLOBAL['db']->query('delete from '.tname('spacetags').' where itemid='.$itemid.' and tagid in ('.simplode($deletetagidarr).') and status=\''.$status.'\'')参考漏洞:Supesite 前台注入 #3 (Delete)
19.二次注入
涉及到的是入库和出库在入库时经过全局转义,入库后转义符就会消失,那么就是, 把这个查询出来,那么出库的就是, 如果再带入到了查询,那么就成功的引入了单引号导致了注入,很多时候数据库中存储的长度是有限制的。
参考漏洞:phpyun v3.2 (20141226) 两处注入。参考漏洞:qibocms 地方门户系统 二次注入#5参考漏洞:74cms (20140709) 二枚二次注入参考链接:Hdwiki 最新版二次注入一枚
20.查询当中 key 可控把 $_POST 带入到了查询函数,然后 foreach key ,foreach 出来的 key 做了查询中的 column。防止方法一般是把数据库中的 column 查询出来,然后 in_array 判断一下 $_POST 出来的 key 是否在数据库中的 column 中。参考漏洞:云人才系统 SQL 注入,绕过 WAF参考漏洞:Cmseasy SQL 注射漏洞之三21.striplashes在全局 addslashes 后,在后面的文件中又 stripslashes 去掉了转义符,然后可以闭合单引号$_SESSION['flow_consignee'] = stripslashes_deep($consignee);参考漏洞:ecshop 全版本注入分析22.截取字符
会限制用户输入的长度,只截取一部分,只允许输入 32 个字符,没有在截取字符的后面加其他字符提交一个,被转义后成,绕后截取 32 个字符就是double query 的话,吃掉一个单引号,然后下一个连着的可控变量可以注入参考漏洞:Hdwiki (20141205) 存在 7 处 SQL 注入漏洞(含之前处理不当安全的漏洞)
23.注册 GLOBALS 变量把 GET POST COOKIE 循环出来,然后注册一个变量,这里不允许创建 GLOBALS 变量,如果设置了 REQUEST 的 GLOBALS,就直接退出低版本 request order 是 GPC ,在 php5.3 以后 request order 默认成了 GP ,也就是 request 成了 get 和 post ,不包含 cookie,所以 $_REQUEST 里面就不包含 COOKIE 提交来的,而这里也把 COOKIE 循环出来,注册变量,所以这里在 COOKIE 里面提交 GLOBALS 就不会被检测出来,而且也成功注册了 GLOBALS 变量,所以再结合后面的一些些代码就造成了代码执行。参考漏洞:Discuz! 某两个版本前台产品命令执行24.PDO 注入
查看 prepare() 硬编码的 string 是否可控PDO 无法安全处理 order by 需求####敏感逻辑1.认证与会话重置、找回密码人机验证绕过session 固定密码存储、加密算法是否合理,注意种子生成逻辑sso / oauth / openid 使用合规注意 Cookie 中包含的可读数据
2.交易
条件竞争服务器端数据校验逻辑
3.投票、统计
未使用 REMOTE_ADDR 获取 ip 地址PHP黑魔法1.弱类型in_array/intval/md5/strcmp
2.正则匹配
preg_replacethinkphp url rcepreg_matchphp
领取专属 10元无门槛券
私享最新 技术干货