0x00 前言

本篇文章我第一次尝试进行代码审计,是不断总结前辈的思路与手法做出的总结,会介绍一个小白蜕变学习的过程。

0x01 环境准备

面对冗长的代码一个舒服趁手的审计工具就会对审计起到很大帮助,本篇文章将使用Seay源代码审计系统和rips对该cms进行审计,其中rips可以搭建在PHPStudy下,该工具网页访问即可,可以对简单的漏洞给出补丁修复,适合新手入门的学习。 rips汉化版0.55:https://pan.baidu.com/s/1hm6VA3vfSRglwF4zE2eqAA      p2ty

这里我利用PHPStudy搭建时出现该cms网页无法访问的情况,此时选择PHPStudy->其他选项菜单->软件设置->允许目录列表,将其勾选。并删除该编译失败的文件,重新访问install目录即可安装成功。注意要使用PHP5.x版本。

0x02 审计

首先将源码放置在PHPStudy中后,访问uploads/install安装Bluecms。在cmd命令窗口切换到主目录下输入命令tree查看目录结构,可以对整个cms有一个宏观的了解。

对于一名新手来说前期的学习可能更多依赖于工具的查找,那么打开Seay和rips进行自动审计。

这里列出部分Seay中审计出的信息,这里值得一说的是该工具也是基于既定规则进行的查找,因此也存在于误报的情况。所以相关漏洞需要自行检验,在了解一定PHP代码的前提下,可以通过该工具“定位函数”的功能去跳转到相关位置,从而审计。同时也可以结合rips对相关漏洞的定位进行一个快速的筛选。

1.SQL注入

在SQL注入代码的审计中,主要关注sql语句中变量拼接的地方,并向上查找该变量是否受用户控制(即是否可传参),当会收到用户控制后,去检查是否有函数对用户输入进行过滤,再根据其防范情况构造出绕过方法。SQL注入经常出现在登陆页面、获取HTTP头(user-agent/client-ip等)、订单处理等地方。

1)查看Seay中审计出的第一个漏洞点,跳转到该位置该工具会将位置高亮显示。

很明显再向上几行可以看到$ad_id是用户可控的参数,再看高亮的SQL语句经过了一层getone函数的过滤,那么双击选中getone,再右键选择定位函数,即可跳转到该函数定位的页面:mysql.class.php。

而该函数也并没有任何过滤,同时通过mysql_fetch_array函数将sql语句执行结果返回,最后echo以document.write输出。

那么构造利用的POC,常规注入即可,在源代码中看到内容回显。

2)再看第二个ann.php

很明显要求$ann_id不传入时,才会执行if语句,拼接$cid值,向上再看$ann_id和$cid的值用户都可控,但是一看到intval函数直接就pass了,该函数只有在if语句判断使用时才会出现安全漏洞。参看:http://huaidan.org/archives/3047.html

intval函数有个特性:”直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(\0)结束转换” 。

直接在用户输入处杜绝了数字型的注入 。

3)comment.php

追踪查看这两个疑似。

首先第一个如上图所示,追踪$id变量,看到存在intval函数的过滤。

在看第二个,依然也是$id的值,所以同上一样没有办法。

4)index.php

$result2 = $db->query("SELECT * FROM ".table('article')." WHERE cid=$row1[cat_id] and is_recommend = 1 and is_check = 1 ORDER BY id DESC LIMIT 7");

​可以看到定位到该语句,可以看到我们要关注的是$row1[]数组是从哪里获得的,选中$row1右键选择全文追踪,可以看到定位到前文有如下语句。

while($row1 = $db->fetch_array($result1))

​可以看到是通过$result1的值获得的,那么再对$result1进行全文追踪。

很明显这是一条被写死的语句,完全没有用户可控的参数,所以利用无效。

5)news.php,search.php

依然是可控的变量值经过intval函数进行了过滤,这里不再赘述。

6)user.php

一共有12个爆出疑似SQL注入,那么逐一查看。

第一个:intval函数过滤了$id值。

第二个:

$card_order = $db->getone("SELECT time FROM ".table('card_order')." WHERE user_id=".$_SESSION['user_id']);

​可以看到唯一拼接的是$_SESSION的user_id值,然而这也不可控

第三个:同第二个相同

第四个:存在拼接的post_id值,但向上溯源发现依然被intval函数过滤

$post_id = intval($_REQUEST[‘post_id’]);

剩下那些调用的也大多是post_id值和, $_SESSION的user_id值 ,所以全部无法利用。

如果到此一直跟着去一步步审计,那么起码应该掌握了溯源的方法,后续很多重复的部分就不再记述,会将不同的地方列出。

7)admin/area.php

第三个,跳转到关键代码,发现存在变量$old_parentid的拼接

$db->query(“UPDATE “.table(‘area’).” SET ishavechild = ‘0’ WHERE area_id = ‘$old_parentid'”);

溯源后看到$old_parentid = get_area_parentid($aid);

首先对get_area_parentid函数进行定位。

很明显看到有select语句的执行同时又经过了getone函数的过滤,这个函数我们前面已经说过,没有任何过滤,而唯一可控的值即为形参$area_id,那么返回去追踪实参的输入。

$aid = $_REQUEST[‘aid’] ? intval($_REQUEST[‘aid’]) : ”;

很遗憾又遇到了intval函数,全剧终。

8)admin/user.php(注入)

很明显看到只是做了GET传参的拼接,什么也没过滤,来到页面查看,存在我们之前注册的邮箱

进行union注入后没有回显,尝试布尔盲注

user_id=1 and length(database())=6

页面空白,而等于7时再次出现电子邮箱信息,即数据库长度为7。后面又利用ASCII和substr得到数据库第一位是b,那么后面就不做了,可以写脚本暴库了,而且什么都没有过滤那种。

9)include/common.fun.php

这里虽然没有过滤,向上溯源 , 发现这里是一个function。全局搜索调用这个function的地方。

很明显内容被写死,调用无望了。

10)admin/nav.php

很明显有一个可以后台注入的地方

11)guest_book.php

获取ip很有可能是通过$SESSION来获取的,全局搜索$online_ip,在comment.inc.php中找到

$online_ip = getip();

再追踪getip()函数

PHP: getenv – Manual getenv — 获取一个环境变量的值

那么知晓如此就可以通过X-Forwarded-For或者Client-ip进行注入了

这里要注意$SESSION中的数据貌似没有自动的url解码 +不能被解码为空格

2 文件包含漏洞结合文件上传

1)user.php

发现当进行支付操作时,会将pay的值通过post方式传递过去拼接,但是后面还拼接了/index.php,所以只要能够截断后面的部分就存在文件包含漏洞

购买 一张便民卡,然后选择支付。抓包

有两种方法可以截断:

绕过方法1:%00 截断

  条件:magic_quotes_gpc = Off PHP 版本<5.3.4

  测试:?filename=../../../../../../boot.ini%00
绕过方法2:路径长度截断

  条件:windows下目录路径最大长度为256字节,超出部分将丢弃;

       Linux下目录最大长度为4096字节,超出长度将丢弃

  测试:?filename=text.txt././././.  或?filename=test.txt.....

首先在根目录下建一个phpinfo的文件。

第一种利用方式,我没有成功,第二种方式可以成功

submit=%D4%DA%CF%DF%D6%A7%B8%B6&price=30&id=B1589353854E&name=%B1%E3%C3%F1%BF%A8&pay=../../../../../../../../../../phpinfo.php..............................................................................................................................................................

​但这里我实际测试的时候pay值的长度是199,即可截断成功

然后这里在测试抓包处又看到存在个人头像的上传,查看源代码

定位到img_upload函数,create_tempname函数是一个随机数命名

再次追踪get_type函数

再次追踪这个数组中的两变量

两个白名单,那么配合文件包含上传一个图片马即可

上传后找到路径,进行文件包含

任意文件删除漏洞

1)user.php

很明显要想达到任意文件删除的操作,需要对face_pic1的值为空,所以在上传头像时抓包

在下方选择任意文件即可删除。

而任意文件删除漏洞可以通过全文追踪unlink函数来筛选,以下代码同理

在看这段,应该也存在该漏洞,但是本地搭建的环境中我没有找到位置。

任意文件读取漏洞

1)admin/tpl_manage.php

可以看到tpl_name变量可控,且有fopen函数读取

抓包修改尝试读取根目录下的robotst.txt

再向下查看

构造?act=edit&tpl_name=../../robots.txt

2)uc_setting.php

全局搜索调用uc_write_config函数的地方,看给形参$file传入的实参值是否可控

elseif($succeed = uc_write_config($ucconfig."|".$uc_config['uc_api']."|".$uc_config['uc_ip'],BLUE_ROOT.'data/config.php'))

​然而可以看到后面的内容被写死,无望。