K-ANOY opened a new issue, #3942:
URL: https://github.com/apache/nuttx-apps/issues/3942
### Description / Steps to reproduce the issue
During the RFB 3.7+ security handshake the server sends a one-byte count of
security types,
followed by that many type bytes. `rfb_negotiate_security()` reads the count
straight off the
socket into a `uint8_t` and uses it as the length of a `recv` into the fixed
16-byte stack array
`types[16]`, with no upper-bound check (only the `== 0` case is
special-cased).
`system/vncviewer/rfb_protocol.c`, `rfb_negotiate_security()`:
```c
521 static int rfb_negotiate_security(int sockfd, const char *password)
522 {
523 uint8_t num_types;
524 uint8_t types[16]; /* 16-byte stack buffer */
...
532 ret = rfb_recv_exact(sockfd, &num_types, 1); /* server-supplied
1..255 */
...
538 if (num_types == 0) { ... return -ECONNREFUSED; } /* ONLY the ==0
case handled */
...
551 ret = rfb_recv_exact(sockfd, types, num_types); /* SINK: writes
num_types bytes */
```
`rfb_recv_exact()` writes exactly `len` bytes into the caller buffer:
```c
383 static int rfb_recv_exact(int sockfd, void *buf, size_t len)
...
388 while (len > 0)
390 n = recv(sockfd, p, len, 0);
406 p += n;
407 len -= n;
```
So line 551 can `recv` up to **255** bytes into `types[16]`, a 239-byte
stack overflow of
attacker-chosen content that smashes the saved-register / return-address
region of the frame.
There is no bound at all (not even a `DEBUGASSERT`) between the 1-byte read
of `num_types` and
its use as the copy length.
This runs **before authentication**: `vncviewer_main.c:191 rfb_connect()` →
`vncviewer_main.c:208 rfb_handshake()` → `rfb_protocol.c:772
rfb_negotiate_security()`. A
malicious VNC server (the server a viewer connects to) or an on-path
attacker injecting into the
TCP stream triggers it on the first handshake, with no credentials.
Steps:
1. Build and run the vncviewer app and connect to an attacker-controlled /
MITM'd VNC server.
2. In the RFB 3.7+ security handshake, have the server send a security-type
count of e.g. `0xff`
followed by that many bytes.
3. `rfb_negotiate_security()` writes those bytes past `types[16]`.
An AddressSanitizer build reports a stack-buffer-overflow WRITE past the
16-byte `types` array.
**Expected:** a count larger than the viewer's buffer is rejected or read in
capped chunks.
**Actual:** up to 255 attacker bytes are written past `types[16]` on the
stack, before auth.
**Suggested fix:** reject or clamp `num_types` to `sizeof(types)` before the
`recv` — the viewer
only needs to know whether `None` / `VNC Auth` is offered, so it can read in
capped chunks and
discard the remainder like `rfb_discard_exact` already does elsewhere.
### On which OS does this issue occur?
[OS: Linux]
### What is the version of your OS?
ubuntu 22
### NuttX Version
a09fb84a9b5f274add52cc0b6d803b77d44306c1
### Issue Architecture
[Arch: all]
### Issue Area
[Area: Networking]
### Host information
_No response_
### Verification
- [x] I have verified before submitting the report.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]