Independent defensive-security researcher based at Guangdong University of Technology (GDUT). First author of a peer-reviewed publication on adversarial machine learning in Computer Engineering and Applications (《计算机工程与应用》, 2025) — Peking University Core Journal & CSCD indexed. DOI: 10.3778/j.issn.1002-8331.2311-0227.

This site collects methodology notes that sit one level above any single writeup — how I turn vulnerability research into detection engineering output (Sigma rules, Suricata SIDs, SIEM hunt queries). The companion artefact repositories live at ctf-notes (23 vulhub CVE reproductions, full SOC artifact sets) and sigma-detection-rules (30 Sigma + 24 Suricata + 6 hunting queries across 3 SIEMs).

Scope. Every artifact published here originates from one of: (a) public CTF challenges distributed by event organizers, (b) vulhub Docker images of vendor-patched CVEs run on 127.0.0.1 in isolation, (c) virtual machines I own on hardware I own, or (d) academic research code I author. No production system, third-party service, or unauthorized network is involved at any stage.


Recent posts

  • Modern Mitigation Bypass Is Leak Chaining

    The last four levels of pwn.college’s Program Security module were the hardest to finish, and they share a single shape. None of them falls to one clever trick. Each one runs the full mitigation stack — stack canary, PIE, NX, RELRO, sometimes SUID privilege separation — and the only way through is to chain small leaks until every mitigation has been turned back into a known value.

  • Constrained Shellcode Is Interface Design

    The most useful lesson from the later pwn.college Program Security levels is that tiny shellcode is rarely a byte-golf problem alone.

  • Reverse Engineering Is Model Recovery

    The pwn.college Program Security reverse-engineering module is a clean progression from strings to models.

  • API Testing Is Contract Drift Hunting

    API bugs often come from contract drift. The frontend shows one contract; the backend accepts a wider one.

  • NoSQL Injection Is Query Shape Injection

    NoSQL injection is not just “SQL injection but without SQL.” The common failure is that user input changes the shape of the query.

  • Race Conditions Are State Transition Bugs

    Race conditions are often described as “send requests at the same time.” That is the delivery technique, not the bug.

  • GraphQL Security Is Schema and Transport Control

    GraphQL concentrates an application’s API surface behind one endpoint. That does not reduce the number of security boundaries. It hides them inside schema, resolver, and transport behavior.

  • Prototype Pollution Is Property Lookup Abuse

    Prototype pollution is often described as a write bug: get __proto__ into a parser, write to Object.prototype, win.

  • Targeted Scanning Is a Manual Testing Tool

    The useful version of automated scanning is not “scan everything and wait.” It is “I think this boundary matters, so test this boundary hard.”

  • JWT Security Is Verification Policy

    JWTs are easy to mistake for security because they look structured and cryptographic. The structure is not the security. The verification policy is.

  • File Upload Is a Four-Stage Boundary

    File upload vulnerabilities are not just extension bypasses. An upload feature has at least four security stages:

  • OAuth Security Is Binding

    OAuth bugs often happen when everyone completes their own step correctly, but nobody binds the steps together.

  • Host Is Routing Metadata

    The HTTP Host header is necessary routing metadata. Trouble starts when applications treat it as identity, local-origin proof, or a safe source for password reset links and script URLs.

  • Business Logic Bugs Are Broken Invariants

    Business logic bugs rarely look like classic injection. The payload may be a negative number, a missing parameter, a replayed confirmation URL, or an email address that two parsers disagree about.

  • Information Leaks Are Missing Exploit Parameters

    Information disclosure is easy to underestimate because the first response often looks passive: a version string, a debug page, a source backup, a header name, a Git diff.

  • Deserialization Restores Code Paths

    Unsafe deserialization is usually described as “turning bytes back into objects”. That is too gentle. In a real application, deserialization restores code paths: constructors, magic methods, getters, cleanup hooks, template rendering, and file operations.

  • Web Cache Poisoning Is a Key Boundary Bug

    Web cache poisoning is not mainly about whether a response is cached. It is about whether the cache key represents every input that can change that response.

  • A Return Address Is a Partially-Known Pointer - 30 pwn.college ROP Challenges, One Idea

    The pwn.college Return Oriented Programming module is 30 real challenges (plus an optional demo). I finished all 30. People treat a sequence like that as 30 separate puzzles. It isn’t. It is one idea, stretched until it breaks, then patched and stretched again.

  • WebSocket Security Starts at the Handshake

    WebSockets are not outside the web security model. They start as HTTP, carry cookies, and then become a long-lived message channel.

  • Authentication Bugs Are State Machine Bugs

    Authentication testing is easiest when you stop thinking about a single login form.

  • Authorization Is Not a Route Name

    Access control bugs are rarely subtle at the model level. They come from trusting the wrong thing.

  • Path Traversal Is a Canonicalization Bug

    Path traversal is often described as “put ../ in the filename.” That is the first lab, not the model.

  • SSTI Is Context First

    Server-side template injection is context first: raw text, expression, object, sandbox, and custom business-object contexts require different exploit paths.
  • Blind Command Injection Is a Channel Problem

    Command injection is easy to describe and easy to under-model.

  • Request Smuggling Is a Parser Disagreement Bug

    HTTP request smuggling looks like a bag of weird headers until you reduce it to one question:

  • CORS Is Not Authorization - A Three-Lab Map

    CORS is often described as a way to “allow another site to access an API.” That is true, but the dangerous part is easy to blur.

  • DOM Bugs Live in the Browser Runtime - A Seven-Lab Map

    DOM-based vulnerabilities are easy to miss in server-heavy reviews because the dangerous decision happens after the response is already in the browser.

  • CSRF Is a State-Transition Bug - A Twelve-Lab Map

    CSRF is usually introduced as “make the victim submit a form.” That is accurate, but too small.

  • XSS Is a Parser Boundary Problem - A Thirty-Lab Map

    Cross-site scripting is often taught as “inject <script>alert(1)</script>.” That is a useful first proof, but it is not the skill.

  • SSRF Is a Network Position Bug - A Seven-Lab Map

    Server-side request forgery is often described as “make the server request a URL.” That is accurate, but too small.

  • Entity Resolution Is a File and Network Boundary - An XXE Map

    The nine PortSwigger XXE labs are a good reminder that XML parsing is not harmless string handling.

  • CSRF Tokens Do Not Prove User Intent - A Clickjacking Methodology

    The five PortSwigger clickjacking labs are short, but they make one point that is easy to forget during web reviews:

  • Five Ways a Cache and an Origin Disagree — A Web Cache Deception Map

    Web cache deception (WCD) has one idea behind it: the cache and the origin disagree about what a URL means. The cache decides a response is a static asset and stores it in a shared, cookie-agnostic cache; the origin resolves the same URL to a dynamic, authenticated page. The victim’s private response — API key, CSRF token — ends up sitting at a URL the attacker can fetch.

  • 18 SQL Injection Labs Later — A Practical Map from Tautologies to OOB Exfiltration

    I worked through the first 18 SQL injection labs in PortSwigger Web Security Academy as a single track rather than as isolated puzzles. That framing is useful because the labs form a clean progression: direct predicate control, UNION shape discovery, metadata enumeration, blind extraction, error-based extraction, time-based extraction, OOB interaction, and finally a WAF bypass through XML entity encoding.

  • Four Ways LLM Apps Turn Data into Actions — Lessons from PortSwigger Web LLM Labs

    The first wave of LLM web security writeups often treated prompt injection as a strange new input-validation problem: users type weird words, the model does weird things. After working through PortSwigger’s Web LLM labs, I think that framing is too small.

  • When the Scanner Is the Vulnerability — Indirect Prompt Injection Against AI Security Agents

    My previous post mapped a black-box adversarial-ML attack chain onto MITRE ATLAS. That work attacks the model. This post is about the layer above it — the agent: an LLM wired to tools, credentials, and a network position, turned loose to act on content it did not write. The attack surface there is not the weights. It is the boundary between data and instructions, and that boundary is where indirect prompt injection lives.

  • 23 vulhub CVE Labs Later — Three Things I Would Redo From the Start

    The labs chapter currently contains 23 published CVEs, each reproduced in an isolated vulhub container and ending in a full SOC artefact set (Sigma rule, Suricata signature, IOC table, three-SIEM hunt queries). The oldest in the chapter is Shiro CVE-2016-4437, written in late 2024. The newest at time of writing is the ActiveMQ Jolokia chain (CVE-2026-34197). That spans roughly a year of evening-and-weekend work and ten calendar years of CVE coverage.

  • Testing the Four-Axis Detection Rubric Against CVE-2024-4956

    At the end of last week’s post I made a small public commitment. The post had introduced a four-axis rubric for predicting detection-rule effort (specificity / position / encoding / workflow uniqueness), and the closing paragraph picked the next CVE on my queue and scored it in advance: CVE-2024-4956 (Nexus Repository Jetty path traversal), preliminary scoring H/H/M/V-H, estimated rule shape single selection with URL-encoded variant. The post promised to come back at the end of the week with the actual result.

  • Three 2024 N-days, Three Signal Qualities — Why Jenkins is Easier to Detect Than GeoServer

    There is a counter-intuitive thing I learned writing detection rules for the 2024 CVE harvest. The CVEs that were worst for victims were not always the worst to detect. CVSS does not predict detection effort. Bug class does not predict it either. The one variable that does predict it — and I have never seen the variable named in any of the standard CVE triage frameworks — is what I will call detection signal quality: the byte-level distance between the attacker’s request and the closest legitimate request the application accepts.

  • How I Pick CVEs to Reproduce — Detection Engineering as Triage

    vulhub is the canonical catalogue of “vendor-patched CVEs that ship with a docker-compose.yml” — at the time of writing it covers somewhere north of 200 vulnerabilities across roughly 100 products. I have written full reproduction-plus-detection writeups for 23 of them, packaged as the labs chapter. The other ~180 I have not touched.

  • Anatomy of CVE-2024-36401 — Why the GeoServer JXPath Bug Needs a Three-Stage Detection

    Yesterday I opened SigmaHQ/sigma#6032, a small upstream contribution for CVE-2024-36401 — the unauthenticated RCE in GeoServer that ships through any OGC-compliant request path. The PR description has the shape every SigmaHQ PR has: a one-paragraph summary, a changelog line, a passing CI badge. It does not have space for the part that took me the longest to get right, which is why the rule looks the way it does and not three other ways it almost did. This post is that explanation.

  • Adversarial ML Attack Patterns Mapped to MITRE ATLAS — A Defender's Reference

    In 2025 I published a peer-reviewed paper on data-free black-box adversarial attacks against image classifiers. The paper is firmly in the offensive ML literature — it shows that with only API-level query access to a target model and no access to its training data, an attacker can train a GAN-based substitute model and use it to craft transfer adversarial examples that succeed against deployed services (Microsoft Azure included) at greater than 78% rate.

  • From CTF Heap Pwn to Falco Rules — Reading Memory Corruption as a Defender

    A common pushback I get when people see my GitHub: “You spend a lot of time on CTF pwn writeups. How is heap exploitation defensive work?” It’s a fair question, and the honest answer takes a while. This post is the long version.

  • From CVE Advisory to Sigma Rule in 30 Minutes — A Repeatable Workflow

    Most published CVEs sit in a strange middle ground: the advisory tells you the bug exists, the PoC tells you how to fire it, and the vendor patch tells you what is now blocked. But almost nothing tells you the only thing a defender actually cares about — what does this look like in my logs the morning a real attacker hits us. Writing that detection rule is its own discipline, and over the last year I have hardened a single workflow that turns any public N-day into a shippable Sigma rule and a Suricata signature in roughly half an hour.