Add content from: ReDisclosure: New technique for exploiting Full-Text Search ...

- Remove searchindex.js (auto-generated file)
This commit is contained in:
HackTricks News Bot 2025-09-25 18:49:46 +00:00
parent 74cc86ad2c
commit 1af4ae332d
2 changed files with 53 additions and 4 deletions

File diff suppressed because one or more lines are too long

View File

@ -198,6 +198,55 @@ mysql> select @@version;
mysql> select version();
```
## MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
This is not a classic SQL injection. When developers pass user input into `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, MySQL executes a rich set of Boolean search operators inside the quoted string. Many WAF/SAST rules only focus on quote breaking and miss this surface.
Key points:
- Operators are evaluated inside the quotes: `+` (must include), `-` (must not include), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). See MySQL docs.
- This allows presence/absence and prefix tests without breaking out of the string literal, e.g. `AGAINST('+admin*' IN BOOLEAN MODE)` to check for any term starting with `admin`.
- Useful to build oracles such as “does any row contain a term with prefix X?” and to enumerate hidden strings via prefix expansion.
Example query built by the backend:
```sql
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
```
If the application returns different responses depending on whether the result set is empty (e.g., redirect vs. error message), that behavior becomes a Boolean oracle that can be used to enumerate private data such as hidden/deleted titles.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: if the backend trims 12 trailing characters per word via a regex like `(\b.{1,2})(\s)|(\b.{1,2}$)`, submit `prefix*ZZ`. The cleaner trims the `ZZ` but leaves the `*`, so `prefix*` survives.
- Early-break stripping: if the code strips operators per word but stops processing when it finds any token with length ≥ min length, send two tokens: the first is a junk token that meets the length threshold, the second carries the operator payload. For example: `&&&&& +jack*ZZ` → after cleaning: `+&&&&& +jack*`.
Payload template (URL-encoded):
```
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
```
- `%26` is `&`, `%2B` is `+`. The trailing `xD` (or any two letters) is trimmed by the cleaner, preserving `{FUZZ}*`.
- Treat a redirect as “match” and an error page as “no match”. Dont auto-follow redirects to keep the oracle observable.
Enumeration workflow:
1) Start with `{FUZZ} = a…z,0…9` to find first-letter matches via `+a*`, `+b*`, …
2) For each positive prefix, branch: `a* → aa* / ab* / …`. Repeat to recover the whole string.
3) Distribute requests (proxies, multiple accounts) if the app enforces flood control.
Why titles often leak while contents dont:
- Some apps apply visibility checks only after a preliminary MATCH on titles/subjects. If control-flow depends on the “any results?” outcome before filtering, existence leaks occur.
Mitigations:
- If you dont need Boolean logic, use `IN NATURAL LANGUAGE MODE` or treat user input as a literal (escape/quote disables operators in other modes).
- If Boolean mode is required, strip or neutralize all Boolean operators (`+ - * " ( ) < > ~`) for every token (no early breaks) after tokenization.
- Apply visibility/authorization filters before MATCH, or unify responses (constant timing/status) when the result set is empty vs. non-empty.
- Review analogous features in other DBMS: PostgreSQL `to_tsquery`/`websearch_to_tsquery`, SQL Server/Oracle/Db2 `CONTAINS` also parse operators inside quoted arguments.
Notes:
- Prepared statements do not protect against semantic abuse of `REGEXP` or search operators. An input like `.*` remains a permissive regex even inside a quoted `REGEXP '.*'`. Use allow-lists or explicit guards.
## Other MYSQL injection guides
- [PayloadsAllTheThings MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
@ -206,9 +255,10 @@ mysql> select version();
- [PayloadsAllTheThings MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
- [MySQL Full-Text Search Boolean mode](https://dev.mysql.com/doc/refman/8.4/en/fulltext-boolean.html)
- [MySQL Full-Text Search Overview](https://dev.mysql.com/doc/refman/8.4/en/fulltext-search.html)
- [MySQL REGEXP documentation](https://dev.mysql.com/doc/refman/8.4/en/regexp.html)
- [ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)](https://exploit.az/posts/wor/)
{{#include ../../../banners/hacktricks-training.md}}