王國慶 发表于 2022-8-10 05:04:42

Bluecmsv1.6-代码审计

前言

之前一直说想学一下代码审计,但是由于懒还有代码审计确实比较难入门,真是一块难啃的骨头。但是没办法,现在有时间了学一下。我看网上大佬推荐的都是从bluecms1.6进行代码审计入门的,我们也来看看。
思路

思路其实就都差不多,大家也能搜到,就没什么好说的了,就以下几种嘛

[*]根据敏感关键字回溯参数传递过程。
[*]查找可控变量,正向追踪变量传递过程。
[*]寻找敏感功能点,通读功能点代码。
[*]直接通读全文代码。
反正明面话是说大家选一个自己最喜欢的思路就行,哈哈哈!但是我相信很多人还有一脸懵逼,我一个小白我哪知道选哪个。作为我也是小白刚入门,我说说我的思路,大家可以参考参考。

[*]基本拿到源码首先看一下目录结构,看出来是什么类型,什么框架
[*]看一下index.php,一般再开头都会有引用文件,然后进入引用的公共文件看看一些过滤函数呀,稍微优点印象进行,因为等会看正文的时候还是会回来再看看的。然后看看数据库的配置文件呀,有没有可能数据库就是gbk编码呢,这样是不是可以考虑以下有没有宽字节注入呢。
[*]其实没有捷径可以走,我是通过seay代码审计工具扫描之后,一个文件一个文件的进行审计的,这个虽然比较费时间,但是却能够很好的打下基本功。
好了bluecms都是网上各位大佬审计烂了,哈哈哈!我就不说明什么目录结构解释了,相信大家一搜都有。我直接开始审计吧,说实话我一开始是跟着网上的大佬文章进行审计的,但是大佬的文章一般只是审计一些经典案例的漏洞,并不是所有的漏洞呀,我们既然是新手,学习当然要抱着学到底的态度啦!虽然过程中可能有很多函数大家不知道是什么意思,我也不知道,毕竟我相信大多数人并没有做过php开发,但是没事,不懂我们搜呀,就这样一个一个的慢慢搜啃下来,我相信审计个几个经典cms之后大家就熟能生巧了。好了,废话不说了!开干!
工具


[*]Seay源代码审计系统
链接:https://github.com/f1tz/cnseay
漏洞审计

1.ad_js.php

SQL注入漏洞

$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);思路:我们可以看到这个sql语句拼接了一个$ad_id变量,我们往前看看这个变量是通过GET方式输入的,所以这个变量我们可控,并且中途并没有做什么过滤。所以这里存在数字型的SQL注入,直接sqlmap一把梭看看。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624093035843-1060564589.png
2.publish.php

文件上传漏洞

elseif($act == 'do_upload')
{
        include_once BLUE_ROOT . "include/upload.class.php";
        $image = new upload();
        if(isset($_FILES['upload_file']['error']) && $_FILES['upload_file']['error'] == 0)
        {
                $upload_pic = $image->img_upload($_FILES['upload_file']);
        }
        template_assign('add_pic', $upload_pic);
        $smarty->caching = false;
        $smarty->display('upload.htm');
}这个地方应该是有文件上传的,但是前端页面没有提交按钮,我醉了,不急我们后面分析还会有的,一般一个cms里面文件上传的功能写的都差不多,一错全错哈哈哈!直接一把梭。
任意文件删除

elseif($act == 'del_pic')
{
        $id = $_REQUEST['id'];
        $db->query("DELETE FROM ".table('post_pic').
                                " WHERE pic_path='$id'");
        if(file_exists(BLUE_ROOT.$id))
        {
                @unlink(BLUE_ROOT.$id);
        }
}这里id参数是用户输入的,可控并且没有任何过滤就调用unlink函数,这个函数是删除文件的,所以我们可以构造id参数删除任意文件。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624101733673-1796132658.png
这个payload能够删除跟publish.php同目录下的所有文件,但是我试了一下,我发现它能够删除D盘根目录下的文件,通过../../../能够删除上级目录下的文件,能够突破www目录。
3.user.php

任意文件包含漏洞

elseif ($act == 'pay'){
        include 'data/pay.cache.php';
        $price = $_POST['price'];
        $id = $_POST['id'];
        $name = $_POST['name'];
        if (empty($_POST['pay'])) {
                showmsg('对不起,您没有选择支付方式');
        }
        include 'include/payment/'.$_POST['pay']."/index.php";
}这里的pay参数是我们输入的,它只是检测了pay是否为空,不为空就代入include里面,这个操作造成了文件包含漏洞,我们可以通过../包含上级目录的文件,如果有文件上传漏洞的话,上传一个图片马进去,就造成连锁反应,直接连webshell了,后面好像还真有一个上传图片马的漏洞,大家等会往下看。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624103952249-979658912.png
直接穿越两级目录包含了首页的index.php文件。
存储型XSS漏洞

https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624104521159-908670029.png
我们发现编辑资料页面的参数除了sex强制转化为int,address进行了html实体编码,其他的基本没有做过滤,然后直接代入了sql语句中插入,我们可以插入XSS弹窗测试,但是最后测试发现只有email字段能够成功弹窗,查看数据库文件发现是其他字段的长度太小了,插入的语句被截断了。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624104905379-1349144729.png
任意文件删除

if (!empty($_POST['face_pic1'])){
      if (strpos($_POST['face_pic1'], 'http://') != false && strpos($_POST['face_pic1'], 'https://') != false){
         showmsg('只支持本站相对路径地址');
         }
      else{
         $face_pic = trim($_POST['face_pic1']);
      }
    }else{
                if(file_exists(BLUE_ROOT.$_POST['face_pic3'])){
                        @unlink(BLUE_ROOT.$_POST['face_pic3']);
                }
        }还是编辑资料这个地方,我发现这里也存在一个任意文件删除漏洞,首先检测face_pic1参数是不是为空,是为空去检测face_pic3参数是否存在,如果存在就调用unlink函数删除文件,而且这两个参数都是用户可控的。下面我们只要把face_pic1赋值空,把face_pic3赋值成删除的文件就行,抓包进行修改。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624105442567-2145405615.png
我们删除上级目录的123.txt,删除成功了,这个也是能够突破www目录的限制的,能直接删除D盘根目录文件。
文件上传漏洞

我发现编辑资料的地方存在一个文件上传,分析一下发现只能够上传图片马。文件上传它调用了img_upload函数过滤,跟踪进去看看首先限制了图片上传的类型是四种:image/jpeg,image/gif,image/png,image/pjpeg,当然了这个我们是可以伪装的,接着往下看他会获取文件的后缀也设置了一个白名单,必须是这四个:jpg,gif,png,pjpeg,这里我们可以用%00截断来上传文件,但是上传之后他好像会按时间经常赋值文件名和加上jpg后缀,所以就是一个图片马。%00截断是php5.3.29以下才生效,后面的版本修复了,我这个实验版本是5.2,当然好像还有其他上传方式,好像有phar利用,到时候去研究一下。
任意文件删除

https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624113052374-1814156915.png
这里应该是存在一个任意文件删除的,但是上面的sql语句会报错,因为bluecms的源码数据库里面没有company_image这个表。
任意文件删除

        //如果没有图片,则将信息缩略图设置为默认图片
        if (file_exists(BLUE_ROOT.$_POST['lit_pic'])) {
                @unlink(BLUE_ROOT.$_POST['lit_pic']);这段在user.php的614行,啊啊啊啊怎么这么多文件删除,这里lit_pic用户可控且没有做过滤,只要我们在上面一步步构造变量下来,然后到这里控制lit_pic为要删除的文件即可任意文件删除。
payload大概这样:
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624114532172-1383468764.png
注册处存在存储型XSS漏洞

elseif($act == 'do_reg'){
        $user_name                 =        !empty($_POST['user_name']) ? trim($_POST['user_name']) : '';
        $pwd                       =         !empty($_POST['pwd']) ? trim($_POST['pwd']) : '';
        $pwd1                            =         !empty($_POST['pwd1']) ? trim($_POST['pwd1']) : '';
        $email                   =         !empty($_POST['email']) ? trim($_POST['email']) : '';
        $safecode                =         !empty($_POST['safecode']) ? trim($_POST['safecode']) : '';
        $from = !empty($from) ? base64_decode($from) : 'user.php';

        if(strlen($user_name) < 4 || strlen($user_name) > 16){
                showmsg('用户名字符长度不符');
        }
        if(strlen($pwd) < 6){
                showmsg('密码不能少于6个字符');
        }
        if($pwd != $pwd1){
                showmsg('两次输入密码不一致');
        }
        if(strtolower($safecode) != strtolower($_SESSION['safecode'])){
                showmsg('验证码错误');
        }
        if($db->getone("SELECT * FROM ".table('user')." WHERE user_name='$user_name'")){
                showmsg('该用户名已存在');
        }
        if($db->getone("SELECT * FROM ".table('admin')." WHERE admin_name='$user_name'")){
                showmsg('该用户名已存在');
        }
        $sql = "INSERT INTO ".table('user')." (user_id, user_name, pwd, email, reg_time, last_login_time) VALUES ('', '$user_name', md5('$pwd'), '$email', '$timestamp', '$timestamp')";我们发现注册的代码输入的变量都没有经过过滤,但是对用户名有长度限制,密码一般不考虑,我们在邮箱字段输入xss语句,对邮箱的验证在前端,我们抓包直接改进行提交之后触发xss。
4. comment.php

SQL注入

配置文件中对POST,GET,COOKIES,REQUEST参数都做了gpc处理,唯独漏了SERVER,而且网站正好通过这个变量获取IP地址,直接搜全局搜索getip函数,看哪里使用了,这个函数在配置文件comment.fun.php中定义的函数
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624111956446-1108481253.png
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624112207312-1851369915.png
我们可以通过伪造ip注入sql语句,直接上sqlmap。
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624112736471-1193297114.png
5.guest_book.php

SQL注入漏洞

https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624134016157-694857220.png
同样的问题,online_ip实际就是获取在线ip,其实还是调用的getip函数,前面的配方。直接构造闭合注入。
payload:x-forwarded-for:127.0.0.1',database())-- -
到现在为止外部文件基本审完了,累死我了,当然可能会漏掉一些,或者利用难度大点的我还没达到那个水平。有大神看出来可以指点一下。下面开始审admin文件夹里面的文件吧。
5.admin/login.php

我们一般访问admin都是先访问登陆页面,我们看看登录页有什么漏洞吧,一般都会有万能密码的SQL注入,这里好像也有。
SQL注入漏洞

在login.php中我们看到没有对username和password做过滤,直接用check_admin函数来判断用户名密码,我们跟进去看看,函数里面也没有进行过滤而是直接代入SQL语句了,SQL语句如下:
$row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$name' and pwd = md5('$pwd')");可以看到用的单引号注入,我们只需要通过宽字节闭合掉单引号就能够万能密码登录了
payload:admin%df' or 1=1#
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624141603816-259638019.png
6.admin/ad_phone.php

存储型XSS漏洞

https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624142315584-722731915.png
我们可以看到什么的参数都没有过滤,只要时间参数通过-分隔开来成了一个数组去检测,所以按理说其他的content,title,color都是存在XSS的,但是我实际上只有前面两个触发了XSS,color字段被截断了,我发现是数据库的这个字段的长度只有10,所以没有触发成功。
7.ann.php

存储型XSS

elseif($act == 'do_add'){
        $title                = !empty($_POST['title']) ? trim($_POST['title']) : '';
        $color                = !empty($_POST['color']) ? trim($_PST['color']) : '';
        $cid                = $_POST['cid'];       
        $content        = !empty($_POST['content']) ? trim($_POST['content']) : '';
        if($title == '' || $content == '' || empty($cid)){
                showmsg('信息填写不完整');
        }
        if(!$db->query("INSERT INTO ".table('ann')." (ann_id, cid, author, title, color, content, add_time, click) VALUES ('', '$cid', '".$_SESSION['admin_name']."', '$title', '$color', '$content', '$timestamp', '1')")){
                showmsg('添加新信息出错', true);
        }else{
                showmsg('添加新信息成功', 'ann.php', true);
        }
}title和content字段都存在存储型XSS,color按理说也存在,但是数据库的该字段长度只有10,如果构造10以内的xss应该就能触发。
因为变量没过滤,所以这里还存在SQL注入漏洞,我这里举例延时注入,它的延时时间会×3倍,这个网站上基本有存储型XSS的地方都有这种SQL注入,payload都差不多,大家可以自行去试试,太多了太多了。
payload:
title=%3Cscript%3Ealert%281%29%3C%2Fscript%3E&color=&cid=1&content=1%df'+and+sleep(2)+or+1=1#&ann_id=3&act=do_editsqlmap语句:
sqlmap -r 1.txt --tamper unmagicquotes --current-db --batch -v 3 -p content --level 3https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624155751698-1226628082.png
admin/attachment.php

SQL注入漏洞,XSS漏洞

XSS就不说了大家都知道,SQL注入漏洞存在位置:
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624164011338-2055325526.png
测试payload:
att_name=%3Cscript%3Ealert%281%29%3C%2Fscript%3E&modelid=123&is_required=1&att_type=1&unit=1%df'+and+sleep(5)+or+1=1#&att_val=&show_order=0&act=doedit
admin/card.php

SQL注入跟XSS,一样的漏洞,原理也一样

admin/tpl_manage.php

任意文件包含

漏洞位置:
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624165405713-809489018.png
这里的tpl_name参数是用户可控的,直接用fopen函数打开了这个路径,我们只需要控制$file变量进行任意文件读取。
任意文件写入

漏洞位置:
https://img2022.cnblogs.com/blog/1553647/202206/1553647-20220624165543748-684840536.png
这里我们act变量赋值为do_edit,然后tpl_name就是我们写入的文件名,tpl_content就是我们写入的文件内容,这里的判断逻辑是如果tpl_name不存在,就会在/templates/default目录下面写入tpl_name文件,并把tpl_content的内容写入进去。
暂时就这样吧,漏洞太多了,基本都是重复的,一个功能写错了好多地方都用的一个函数,这次收获还不错。慢慢啃吧

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Bluecmsv1.6-代码审计