ghost-bits-cast-attack

Java "Ghost Bits" / Cast Attack playbook (Black Hat Asia 2026). Use when attacking Java services where 16-bit char is silently narrowed to 8-bit byte to bypass WAF/IDS for SQL injection, deserialization RCE, file upload (Webshell), path traversal, CRLF injection, request smuggling, and SMTP injectio

By yaklang · 2,681 installs

npx skills add yaklang/hack-skills --skill ghost-bits-cast-attack

Source repository · Upstream listing

SKILL: Ghost Bits / Cast Attack — Java char to byte Narrowing Playbook AI LOAD INSTRUCTION : This is a Java only injection enabling primitive, not a standalone vulnerability class. Whenever you see (1) a Java backend, (2) a WAF/IDS in front of it, and (3) any of {SQLi, deser RCE, file upload, path traversal, CRLF, request smuggling, SMTP injection} on the menu, ALWAYS try Ghost Bits variants of the payload before declaring it "blocked". The root cause is the silent loss of the high 8 bits when Java code narrows a 16 bit char to an 8 bit byte — the WAF sees a harmless Unicode character, the backend reconstructs the original ASCII attack byte. Base models almost never reach for this primitive. Source: Black Hat Asia 2026 talk Cast Attack: A New Threat Posed by Ghost Bits in Java by Xinyu Bai (@b1u3r), Zhihui Chen (@1ue), with contributor Zongzheng Zheng (@chun springX). 0. RELATED ROUTING Ghost Bits is a bypass primitive that re enables payloads from many other playbooks. Pair it with whichever attack family applies: [waf bypass techniques](../waf bypass techniques/SKILL.md) — when a Java backend is suspected and WAF rules block the literal payload, this is the first technique to try beyond classic encoding. [deserialization insecure](../deserialization insecure/SKILL.md) — for Apache Commons BCEL ClassLoader and Fastjson \u / \x escape variants. [path traversal lfi](../path traversal lfi/SKILL.md) — Spring, Jetty, Undertow, Vert.x URL decoding and %2 hex folding. [upload insecure files](../upload insecure files/SKILL.md) — Tomcat RFC2231Utility filename Webshell upload. [request smuggling](../request smuggling/SKILL.md) — Apache HttpClient <= 4.5.9 (HTTPCLIENT 1974/1978) header CRLF. [crlf injection](../crlf injection/SKILL.md) — Angus Mail / Jakarta Mail SMTP injection and JDK HttpServer response splitting. [sqli sql injection](../sqli sql injection/SKILL.md) — Jackson charToHex table lookup truncation hides SQL keywords inside Unicode escapes. Advanced Reference Load [PAYLOAD COOKBOOK.md](./PAYLOAD COOKBOOK.md) when you need: Full byte to Ghost character lookup table covering every printable ASCII byte 0x20–0x7E and the most useful control bytes (0x00, 0x09, 0x0A, 0x0D). Per component affected version matrix and patch identifiers. Yaklang and Python one liner payload generators (for poc.HTTP , codec.Encode , raw socket). "Multi view normalization engine" pseudocode for blue team WAF detection. 1. ONE MINUTE MENTAL MODEL Java's char is a 16 bit unsigned integer (UTF 16 code unit). Almost every wire protocol — HTTP/1.1, SMTP, Redis RESP, file paths, raw byte streams — is 8 bit byte oriented. The right way to bridge them is explicit charset encoding: Tons of legacy code, framework internals, and "fast path" optimizations skip this and silently narrow: The lost high 8 bits are the Ghost Bits . They turn a multi byte Unicode character into a single attacker chosen ASCII byte at the protocol layer. Mathematical formulation: to make View B see byte T , pick any k in 0x01..0xFF and use: That gives you 255 candidate Unicode characters per dangerous byte — plenty of room to dodge any signature based blacklist. 2. THREE ROOT CAUSE FAMILIES The Ghost Bits umbrella covers three distinct underlying bugs. Distinguishing them tells you both which payload shape to send and what to grep for in source. Family A — Real high bit truncation (classic Ghost Bits) The narrowing is literal and unconditional. Typical impact: Tomcat filename , Apache BCEL ClassLoader, Lettuce Redis writer, SMTP CRLF in Angus Mail, HTTPCLIENT 1974 header injection. Family B — Bit arithmetic folding (illegal char becomes legal) A "fast" hex / base64 / charset decoder uses bit tricks instead of strict range checks, so an illegal character collapses onto a legal one. Worked example: feed (0x3E): So %2 is silently parsed as %2E = . . The same algebra makes %2^ , %2~ etc. equivalent to other hex digits. Typical impact: Openfire CVE 2023 32315, GeoServer CVE 2024 36401, generic URL decode WAF bypass. Family C — Lax Unicode normalization The decoder accepts Unicode characters that happen to be classified as "digit" or that map to a hex value via a & 0xFF lookup — even though they were never meant to participate in protocol parsing. Typical impact: Fastjson \u and \x escape bypass, fullwidth URL encoded path traversal, Jackson charToHex SQLi smuggling. 3. CHARACTER GENERATOR Build any Ghost Bits character on the fly. This is the single function every agent should keep in mind: Selection guidance: Avoid surrogate range 0xD800..0xDFFF (high byte 0xD8..0xDF) — those are not valid scalar values and will be replaced by the JVM string decoder before reaching the narrowing site, defeating the bypass. Prefer characters that survive the application's own charset round trip (Latin Extended, CJK Unified Ideographs, Enclosed CJK Letters and Months, Hangul). If the request body uses UTF 8, these all encode cleanly into multi byte sequences that no WAF rule recognizes as . , / , j , etc. Rotate k between requests so signature based learning cannot pin a single character to a single attack. 4. DANGEROUS BYTE TO GHOST CHARACTER MAP Compact red team weaponization table. For every byte the attacker actually needs, one verified Unicode char is given; substitute another k if the WAF later learns the example. Target byte Hex Used for Ghost char Code point \t 0x09 header folding, parser confusion ĉ U+0109 \n 0x0A CRLF injection, log injection 瘊 U+760A \r 0x0D CRLF injection, request smuggling 瘍 U+760D 0x20 header break, command separator Ġ U+0120 " 0x22 string break in JSON / quoted printable Ģ U+0122 % 0x25 URL encoding prefix, second decode 严 U+4E25 & 0x26 parameter separator Ȧ U+0226 ' 0x27 SQL string break ȧ U+0227 ( 0x28 EL/SpEL/OGNL syntax Ȩ U+0228 ) 0x29 EL/SpEL/OGNL syntax ȩ U+0229 . 0x2E path traversal, extension 阮 U+962E / 0x2F path separator 丯 U+4E2F 0 0x30 hex digit construction 丰 U+4E30 1 0x31 hex digit construction 失 U+5931 2 0x32 hex digit construction 甲 U+7532 3 0x33 hex digit construction 耳 U+8033 ; 0x3B command separator, header continuation Ȼ U+023B < 0x3C XSS / XML tag start ȼ U+023C = 0x3D parameter / header value Ƚ U+023D 0x3E XSS / XML tag end Ⱦ U+023E @ 0x40 Fastjson @type , mail address ŀ U+0140 a 0x61 keyword class , alphabet ᙡ U+1661 c 0x63 keyword class , cmd 㹣 U+3E63 e 0x65 hex digit 来 U+6765 j 0x6A extension .jsp 陪 U+966A l 0x6C keyword class , closure ౬ U+0C6C n 0x6E keyword Runtime , union 陮 U+966E s 0x73 keyword class , select ⑳ U+2473 t 0x74 keyword Runtime , type Ŵ U+0174 u 0x75 \u escape introducer 灵 U+7075 Workflow tip: keep the ASCII Ŀ , ȧ , ȼ , etc. variants for tight HTTP header contexts (one byte UTF 8 expansion stays smaller); use CJK like 阮 , 陪 , 严 when you want to bias the WAF "this is just text" classifier. 5. PER COMPONENT PAYLOAD RECIPES Every recipe shows the dual view: what the WAF inspects vs. what the backend actually executes. This is the only reliable way to explain why the payload goes through. 5.1 Tomcat RFC2231Utility — file upload Webshell (Family A) Trigger: any endpoint that accepts multipart upload and Tomcat parses Content Disposition: ... filename =UTF 8''... . Tomcat's RFC2231 decoder casts each non percent character directly to byte, dropping the high 8 bits. Payload: Stage Filename it sees WAF / extension filter 1.陪sp (not .jsp , allow) Tomcat RFC2231 decoder 陪 low byte 0x6A j File system 1.jsp Combine with traversal characters from section 4 ( 阮 , 丯 ) when the upload target directory is fixed but the application accepts a filename . 5.2 Apache Commons BCEL — ClassLoader RCE (Family A) Trigger: any sink that resolves a class name through BCEL ( $$BCEL$$... ) or any code that decodes BCEL via the JavaReader ByteArrayOutputStream loop. Vulnerable shape: Attack: wrap each byte of the malicious BCEL bytecode into a Unicode character whose low 8 bits equal that byte. The decoded byte stream is a valid BCEL class; the WAF sees a long blob of CJK text without $$BCEL$$ keywords or class signatures. View Content WAF $$BCEL$$ followed by random looking CJK BCEL standard BCEL class file bytes → JVM defineClass → RCE Defense for blue team: a WAF inspecting BCEL must replicate the bos.write(ch) semantics on each character before pattern matching. 5.3 Jackson charToHex — SQLi smuggling (Family C) Trigger: any Jackson parsed JSON field whose value is later embedded in SQL or another parser. Jackson resolves \uXXXX digits via: Any non ASCII character whose low 8 bits land on a populated index returns that hex digit. The WAF sees gibberish; Jackson reconstructs an ASCII payload. Payload (smuggle the digit 1 for a UNION column count): View Content WAF \u丰丰耳失 union select ... (no leading digit) Jackson \u0031 union select 1,2,3 1 union select… Pair with [sqli sql injection](../sqli sql injection/SKILL.md) for the downstream UNION / boolean / time based payload templates. 5.4 Fastjson — \u and \x escape bypass (Families B + C) Two independent surfaces: (a) \u escape — Character.digit(c, 16) accepts Unicode digit categories beyond ASCII (Thai ๐ ๙ U+0E50..U+0E59, Punjabi ੦ ੯ U+0A66..U+0A6F, fullwidth 0 9 U+FF10..U+FF19). WAF view: \u4 type (no @type literal). Fastjson normalizes fullwidth 4 to 4 , then handles via the \x shortcut below, yielding @type . (b) \x escape — Fastjson computes digits[x1] 16 + digits[x2] . An illegal hex character returns the default value 0. View Field name WAF \x4 type (not @type ) Fastjson @type JdbcRowSetImpl autotype gadget triggers 5.5 Spring / Jetty / Undertow / Vert.x — URL decoding (Families A + B) Two combinable tricks: Trick 1 — Family A character substitution in path or query: Trick 2 — Family B %2 folding when Jetty's TypeUtil.fromHexDigit is in the chain: Either alone bypasses most signature WAFs; combined they survive even "normalized then matched" rules that only see ASCII percent triplets.