EXERCISE 1 — Deserialization RCE vs JSON safety ================================================ WHY NATIVE SERIALIZATION (ObjectInputStream, pickle) IS AN RCE VULNERABILITY: SERIALIZATION is converting an object into bytes (to store or send). DESERIALIZATION is reconstructing the object from those bytes. Languages like Java and Python provide "native" serializers that are EXPRESSIVE — they can serialize almost any object, including complex class instances with methods and state. The danger: during deserialization, the reconstructed object may EXECUTE METHODS as part of its initialization or state restoration. So if an attacker crafts a serialized byte string that represents a malicious object, deserialization RUNS THAT ATTACKER'S CODE. EXAMPLE (conceptual): - A Java class has a method that opens a file or runs a command. - An attacker crafts a serialized object that, when instantiated, triggers that method's execution. - You deserialize the attacker's bytes with ObjectInputStream. - The object is instantiated (executing the method) — the attacker's code runs. - You have RCE with the privileges of the Java process. This is called a "gadget chain" — a chain of existing methods that, when invoked in sequence, execute arbitrary code. Common libraries (Apache Commons, Spring) contain gadgets that attackers can chain together. WHY IT'S AN RCE: Unlike SQL injection (where you inject a query string) or command injection (where you inject shell syntax), deserialization RCE is AUTOMATIC — no parsing, no string evaluation required. The act of deserialization itself triggers code. The barrier to exploitation is: "can the attacker control the serialized input?" ANSWER: yes, in many places — uploaded files, API requests, database blobs, cached objects. So: NEVER deserialize untrusted input. --- WHY JSON DESERIALIZATION IS SAFE (and why to validate): JSON is a DATA FORMAT, not an executable format. A JSON parser creates data structures (dictionaries, lists, strings, numbers) — it NEVER instantiates classes or calls methods. So a malicious JSON string can't execute code just by being parsed. EXAMPLE: {"command": "rm -rf /", "user": "attacker"} Parsing this JSON produces a dict with two string keys. The values are STRINGS, not code. If your application then INTERPRETS the "command" string and runs it, that's a problem — but the problem is YOUR CODE, not JSON's. JSON IS SAFE because: - It only produces data (dicts, lists, strings, numbers, bools). - The parser has no hooks to instantiate arbitrary classes. - There's no way to embed executable code in the JSON spec itself. BUT YOU MUST VALIDATE THE STRUCTURE AND VALUES: 1. Validate the schema — does it have the fields you expect, with the right types? Reject unexpected fields or types. 2. Validate the values — are the strings within safe bounds (length, charset)? Do they match expected patterns (email, URL, UUID)? Reject values that don't fit. 3. Validate the logic — does the data represent a valid state for your app? (e.g. a price shouldn't be negative, a user ID should exist in the DB.) EXAMPLE OF SAFE JSON HANDLING: - Parse JSON -> produces a dict. - Check: does it have "user_id" and "amount" (and only those)? - Check: is "user_id" an integer and "amount" a positive number? - Check: does user_id correspond to a real user in the DB? - If all checks pass, use the data. Otherwise, reject it. This is why JSON is safe for untrusted input — the worst case is you get malformed data, which you detect and reject. You never execute code. --- ONE-LINE TAKEAWAY: Native serializers execute methods during deserialization (RCE risk); JSON is safe because it only produces data, but you MUST validate the structure and values after parsing.