You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In SonicWall SMA100 firmware 10.2.1.15 the reverse-proxy module `mod_httprp.so` allocates an **0x80-byte** heap chunk and then concatenates several strings into it with `__sprintf_chk`:
`__sprintf_chk` is part of **_FORTIFY_SOURCE**. When it receives a **positive** `size` parameter it verifies that the resulting string fits inside the destination buffer. By passing **`-1` (0xFFFFFFFFFFFFFFFF)** the developers effectively **disabled the bounds check**, turning the fortified call back into a classic, unsafe `sprintf`.
65
+
66
+
Supplying an overly long **`Host:`** header therefore lets an attacker **overflow the 0x80-byte chunk and clobber the metadata of the following heap chunk** (tcache / fast-bin / small-bin depending on the allocator). A crash can be reproduced with:
67
+
68
+
```python
69
+
import requests, warnings
70
+
warnings.filterwarnings('ignore')
71
+
requests.get(
72
+
'https://TARGET/__api__/',
73
+
headers={'Host': 'A'*750},
74
+
verify=False
75
+
)
76
+
```
77
+
78
+
Practical exploitation would require **heap grooming** to place a controllable object right after the vulnerable chunk, but the root cause highlights two important takeaways:
79
+
80
+
1.**_FORTIFY_SOURCE is not a silver bullet** – misuse can nullify the protection.
81
+
2. Always pass the **correct buffer size** to the `_chk` family (or, even better, use `snprintf`).
A good demonstration of why **`sscanf` should never be trusted for parsing untrusted input** appeared in 2025 in SonicWall’s SMA100 SSL-VPN appliance.
107
+
The vulnerable routine inside `/usr/src/EasyAccess/bin/httpd` attempts to extract the version and endpoint from any URI that begins with `/__api__/`:
108
+
109
+
```c
110
+
char version[3];
111
+
char endpoint[0x800] = {0};
112
+
/* simplified proto-type */
113
+
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
114
+
```
115
+
116
+
1. The first conversion (`%2s`) safely stores **two** bytes into `version` (e.g. `"v1"`).
117
+
2. The second conversion (`%s`) **has no length specifier**, therefore `sscanf` will keep copying **until the first NUL byte**.
118
+
3. Because `endpoint` is located on the **stack** and is **0x800 bytes long**, providing a path longer than 0x800 bytes corrupts everything that sits after the buffer ‑ including the **stack canary** and the **saved return address**.
119
+
120
+
A single-line proof-of-concept is enough to trigger the crash **before authentication**:
121
+
122
+
```python
123
+
import requests, warnings
124
+
warnings.filterwarnings('ignore')
125
+
url = "https://TARGET/__api__/v1/" + "A"*3000
126
+
requests.get(url, verify=False)
127
+
```
128
+
129
+
Even though stack canaries abort the process, an attacker still gains a **Denial-of-Service** primitive (and, with additional information leaks, possibly code-execution). The lesson is simple:
130
+
131
+
* Always provide a **maximum field width** (e.g. `%511s`).
132
+
* Prefer safer alternatives such as `snprintf`/`strncpy_s`.
0 commit comments