# SeaCms 代码审计

**URL:** <https://forum.90sec.com/t/topic/2191>\
**Category:** 账号审核\
**Created:** [2022 年10 月 10 日 02:44 UTC](https://forum.90sec.com/t/topic/2191 "2022-10-10T02:44:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![xuehuiziyu](https://forum.90sec.com/letter_avatar_proxy/v4/letter/x/f1d935/32.png) [@xuehuiziyu](https://forum.90sec.com/u/xuehuiziyu)\
发布日期： [2022 年10 月 10 日 02:44 UTC](https://forum.90sec.com/t/topic/2191/1 "2022-10-10T02:44:02Z")

</div>

PHP 代码审计学习计划是从 BuleCms-\>SeaCms-\>DedeCms-\>PhpCms 逐一进行审计，这里审计的是 [SeaCms v6.45](https://down.easck.com/code/29585.html#xzdz)

SeaCms 是多文件入口的 Cms，思路还是先通读 `index.php` 和 `admin/index.php` 和 `admin/login.php` 文件，借此了解 Cms 对参数的全局过滤和连接数据库的编码和其它的一些安全措施

SeaCms 用 `addslashes` 函数对参数进行处理

```php
function _RunMagicQuotes(&$svar)
{
	if(!get_magic_quotes_gpc())
	{
		if( is_array($svar) )
		{
			foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
		}
		else
		{
			$svar = addslashes($svar);
		}
	}
	return $svar;
}

```

且数据库编码并没有设置为 `GBK`，这种情况下可能产生的 SQL 注入我知道的有两种

- 把客户端IP存储进数据库，且客户端IP可以伪造
- SQL 语句参数没有引号包裹或者用 反引号 等包裹

在我通读完 `index.php` 和 `admin/index.php` 和 `admin/login.php` 文件后并没有找到漏洞，前台功能较少，后台我注意到有一个模板编辑功能，审计上一套 `BuleCms` 的时候，就是前台 SQL 注入配合由后台模板编辑产生的文件写入进行一个组合拳 getshell

SeaCms 也存在由后台模板编辑产生的文件写入漏洞，但是这个写入有文件后缀限制，只能是 `html/htm/js/css/txt`

```php
$dirTemplate="../templets";
elseif($action=='saveCus')
{
	if($filedir == '')
	{
		ShowMsg('未指定要编辑的文件或文件名不合法', '-1');
		exit();
	}
	if(substr(strtolower($filedir),0,11)!=$dirTemplate){
		ShowMsg("只允许编辑templets目录！","admin_template.php");
		exit;
	}
	$filetype=getfileextend($filedir);
	if ($filetype!="html" && $filetype!="htm" && $filetype!="js" && $filetype!="css" && $filetype!="txt")
	{
		ShowMsg("操作被禁止！","admin_template.php");
		exit;
	}
	$folder=substr($filedir,0,strrpos($filedir,'/'));
	if(!is_dir($folder)){
		ShowMsg("目录不存在！","admin_template.php");
		exit;
	}
	$content = stripslashes($content);
	$content = m_eregi_replace("##textarea","<textarea",$content);
	$content = m_eregi_replace("##/textarea","</textarea",$content);
	$content = m_eregi_replace("##form","<form",$content);
	$content = m_eregi_replace("##/form","</form",$content);
	createTextFile($content,$filedir);
	ShowMsg("操作成功！","admin_template.php?action=custom");
	exit;
}

```

写入目录限制在 `../templets` 上，可以通过目录穿越绕过这一点，这时候是写入文件内容可控，文件名后缀只能是 `html/htm/js/css/txt` ，我在通读代码的时候注意到 `admin/login.php` 有一个文件包含操作

```php
include('templets/login.htm');

```

很好，这时候就可以通过写入一句话到 `login.htm` 文件中

 ![SeaCms01](https://forum.90sec.com/uploads/default/original/2X/1/1b325f490ffa15ac4de53027696c6db546c4f65d.png)

再访问 `admin/login.php` 即可 getshell

 ![SeaCms02](https://forum.90sec.com/uploads/default/original/2X/c/c32df24eae4cdb774128a3b3aca71d86cec0b24e.png)

后台的 getshell，这时候审审有没有逻辑漏洞/sql注入/未授权漏洞(XSS暂时不考虑)拿到后台权限，就可以打一套组合拳，登录处的处理逻辑没找到漏洞点，编辑模板也不存在未授权，只能找一找 sql 注入了

在我审计这套 Cms 的时候没有特别注意去寻找哪些 sql 语句的参数是没有被包裹或者被反引号包裹的，所以一直没有头绪，没有头绪就换其它思路，有未授权的上传接口，但是没有 `__wakeup` 函数无法 phar 反序列化，文件包含没有找到可控的点，这里陷入了僵局

还是太菜了，查阅网上有关 SeaCms 的审计文章，前台有个 sql 注入和 rce，sql注入产生在 `comment/api/index.php` 文件

```sql
$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";

```

`$ids` 可控，无引号包裹，这条语句是在 `Readrlist` 函数执行的，也正是因为在另一个函数里面，当时审计的有点疲惫了，没有跟进去，`$ids` 的传递也是很简单的

 ![SeaCms03](https://forum.90sec.com/uploads/default/original/2X/9/912458341060418f9dbaa7ade22bb988d6752a5c.png)

还有一个反引号包裹参数的后台 sql 注入

查阅文章提及到一个前台 rce，漏洞原因是 `eval` 执行的内容部分可控，在 `include/main.class.php` 文件，文件代码量很大，功能是用来解析模板标签的，漏洞核心代码如下

```php
function parseIf($content){
    $labelRule = buildregx("{if:(.*?)}(.*?){end if}","is");
    preg_match_all($labelRule,$content,$iar);
    $strIf=$iar[1][$m];
    @eval("if(".$strIf."){\$ifFlag=true;}else{\$ifFlag=false;}");
}

```

在 phpstorm 中跟踪哪里调用了 `parseIf` 函数，`search.php` 文件调用这个函数

```php
function echoSearchPage(){
    $content = str_replace("{searchpage:ordername}",$order,$content);
	$content=$mainClassObj->parseIf($content);
}

```

`$content` 值是 `cascade.html/search.html` 其中一个文件的内容，`templets/default/html/cascade.html` 文件存在 `{searchpage:ordername}` 标签，图片中的 `payload` 对应的 `$content` 变量值是 `templets/default/html/cascade.html` 文件里的内容，`$order` 通过传参传入

在 `$order` 变量传入要执行的代码

 ![SeaCms04](https://forum.90sec.com/uploads/default/original/2X/a/a5438f18cb89d7321c0bf1aee23f1ab6f41e0f24.png)
