Weakness reference
CWE-123

Write-what-Where Condition

A write-what-where condition occurs when an attacker can control both where data is written in memory and what data is written there. This is one of the most…

01Summary

A write-what-where condition occurs when an attacker can control both *where* data is written in memory and *what* data is written there. This is one of the most severe memory corruption vulnerabilities because it can lead to arbitrary code execution, privilege escalation, or complete system compromise. Unlike buffer overflows that corrupt adjacent memory, write-what-where gives an attacker surgical precision to overwrite critical data structures.

02How It Happens

This weakness typically arises in low-level code (C/C++) where memory management is manual and input validation is insufficient. Common scenarios include:

- Unsafe pointer arithmetic:
Code uses user-controlled values to calculate memory addresses without bounds checking. - Unvalidated array indexing:
An attacker supplies an index that is never verified to be within valid bounds, allowing writes to arbitrary offsets. - Format string vulnerabilities:
Misuse of format functions (e.g., printf) where an attacker controls the format string and can write to arbitrary addresses. - Unsafe deserialization:
Untrusted data is deserialized into structures containing function pointers or other sensitive fields that are then overwritten.

The core issue is the absence of a security boundary between user input and the memory address being written to.

03Real-World Impact

An attacker exploiting a write-what-where condition can overwrite function pointers, virtual method tables, return addresses on the stack, or heap metadata to redirect execution flow. This can result in arbitrary code execution with the privileges of the affected process, complete bypass of security mechanisms, or denial of service. Even on systems with modern mitigations (ASLR, DEP), write-what-where remains a critical primitive for building reliable exploits.

04Vulnerable & Fixed Patterns

Vulnerable pattern
# Simulated low-level memory operation (Python ctypes)
import ctypes

class DataBuffer:
    def __init__(self):
        self.data = (ctypes.c_char * 256)()
        self.metadata = ctypes.c_int(0)

def unsafe_write(buffer, offset, value):
    # offset is user-controlled and never validated
    ptr = ctypes.addressof(buffer.data) + offset
    ctypes.cast(ptr, ctypes.POINTER(ctypes.c_int))[0] = value

user_offset = int(input("Enter offset: "))
user_value = int(input("Enter value: "))
buf = DataBuffer()
unsafe_write(buf, user_offset, user_value)  # Attacker can write anywhere

Why it's vulnerable:
The offset parameter is taken directly from user input without validation. An attacker can supply a negative or very large offset to write beyond the intended buffer, corrupting adjacent memory structures.

Fixed pattern
import ctypes

class DataBuffer:
    BUFFER_SIZE = 256
    
    def __init__(self):
        self.data = (ctypes.c_char * self.BUFFER_SIZE)()
        self.metadata = ctypes.c_int(0)

def safe_write(buffer, offset, value):
    # Validate offset is within bounds
    if offset < 0 or offset + ctypes.sizeof(ctypes.c_int) > buffer.BUFFER_SIZE:
        raise ValueError("Offset out of bounds")
    ptr = ctypes.addressof(buffer.data) + offset
    ctypes.cast(ptr, ctypes.POINTER(ctypes.c_int))[0] = value

user_offset = int(input("Enter offset: "))
user_value = int(input("Enter value: "))
buf = DataBuffer()
safe_write(buf, user_offset, user_value)  # Bounds-checked
Vulnerable pattern
<?php
// Simulated pointer-like operation using array offsets
class MemoryRegion {
    private $buffer = array_fill(0, 256, 0);
    private $metadata = 0;
    
    public function unsafeWrite($offset, $value) {
        // $offset is user-controlled and never validated
        $this->buffer[$offset] = $value;
    }
}

$region = new MemoryRegion();
$user_offset = $_GET['offset'];  // No validation
$user_value = $_GET['value'];
$region->unsafeWrite($user_offset, $user_value);
?>

Why it's vulnerable:
The $offset parameter is used directly as an array key without checking whether it falls within the intended buffer bounds. An attacker can supply a negative index or an index far beyond the buffer size to corrupt adjacent data.

Fixed pattern
<?php
class MemoryRegion {
    const BUFFER_SIZE = 256;
    private $buffer = array();
    private $metadata = 0;
    
    public function __construct() {
        $this->buffer = array_fill(0, self::BUFFER_SIZE, 0);
    }
    
    public function safeWrite($offset, $value) {
        // Validate offset is within bounds
        if (!is_int($offset) || $offset < 0 || $offset >= self::BUFFER_SIZE) {
            throw new Exception("Offset out of bounds");
        }
        $this->buffer[$offset] = $value;
    }
}

$region = new MemoryRegion();
$user_offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
$user_value = isset($_GET['value']) ? (int)$_GET['value'] : 0;
$region->safeWrite($user_offset, $user_value);
?>

05Prevention Checklist

Validate all memory offsets and indices
before use; ensure they fall within the bounds of the target buffer or data structure.
Use safe abstractions
(managed languages, standard library functions) instead of manual pointer arithmetic whenever possible.
Implement strict input validation
on any user-supplied value that influences a write operation, including size, offset, or address calculations.
Enable compiler and runtime protections
such as stack canaries, address space layout randomization (ASLR), and data execution prevention (DEP).
Perform code review
focusing on memory operations, pointer arithmetic, and deserialization of untrusted data.
Use static analysis tools
to detect unsafe pointer usage, out-of-bounds writes, and format string vulnerabilities.

06Signs You May Already Be Affected

Unexplained crashes, segmentation faults, or memory corruption errors in logs may indicate an attempted or successful write-what-where exploit. Unusual changes to critical data structures (e.g., unexpected function behavior, privilege escalation, or code execution) without corresponding legitimate modifications are also red flags. If you maintain C/C++ code that performs manual memory management, review recent changes to pointer arithmetic and array indexing logic.

07Related Recent Vulnerabilities