Ghost Bits(幽灵比特)初学理解与总结
原理
什么是 Ghost Bits?
Ghost Bits(幽灵比特) 是 Java 语言特有的底层安全缺陷:
Java 的 char 是 16 位,byte 是 8 位。
当执行 (byte) ch 强制转换时,高 8 位会被直接丢弃且不报错,只保留低 8 位。
这部分被悄悄丢掉的高位,就叫 Ghost Bits。
char = 16 bit
byte = 8 bit
char:字符(存放看得见的文字)占16位,能存汉字、生僻字、特殊符号
byte:字节(计算机最小的存储单元)占8位,装不下汉字只能存英文、数字的底层编码
(byte)ch
就是把 16 位的 char 塞进 8 位的 byte 。一定会发生高 8 位丢失,只保留:低 8 位。
简单演示
一、
public class main {
public static void main(String[] args) {
char ch = '陪';
System.out.println(Integer.toHexString(ch));
}
}
966a

陪 = U+966A
Hex = 0x966A
二、
public class main {
public static void main(String[] args) {
char ch = '陪';
System.out.println(Integer.toHexString(ch));
byte b = (byte) ch;
System.out.println((char) b);
}
}
j

陪 → 0x966A
强转 byte 只保留低 8 位 → 0x6A
0x6A = ASCII j
也就是说,陪->j
汉字 → 悄悄变成危险字符
为什么危险?
因为安全检查看到的是char,而真正执行的是byte,于是检查的是A,执行的是B,WAF、业务过滤全部失效。
这叫Security Semantic Split(安全语义分裂),这才是真正危险的地方。
本地复现
文件上传绕过
场景:系统禁止
.jsp
.php
.exe
允许
.jpg
.png
.txt
开发写了:
if (filename.endsWith(".jsp")) {
reject();//拦截
}
他觉得很安全,但其实不安全
Demo 1:Ghost Bits 文件名绕过
public class GhostBitsDemo {
public static void main(String[] args) throws Exception {
String filename = "1.陪sp";
// 安全检查阶段
if (filename.endsWith(".jsp")) {
System.out.println("拦截:危险文件");
} else {
System.out.println("通过:看起来安全");
}
// 底层保存阶段(模拟)
byte[] bytes = new byte[filename.length()];
for (int i = 0; i < filename.length(); i++) {
bytes[i] = (byte) filename.charAt(i);//charAt是取出第i个
}
//将bytes数组[][][]...按照该 ISO-8859-1 翻译表 重新变回一个字符串!
String realFilename = new String(bytes, "ISO-8859-1");
System.out.println("真实落地文件名: " + realFilename);
}
}
通过:看起来安全
真实落地文件名: 1.jsp
为什么成功?
陪=0x966A
低8位 = 0x6A = j
1.陪sp -> 1.jsp
绕过了,成功上传木马
Demo 2:CRLF 注入(更高级)
瘍 → U+760D → 低 8 位 0x0D → \r
瘊 → U+760A → 低 8 位 0x0A →
所以
瘍瘊 → \r
这意味着可以注入协议换行
例如:
SMTP 注入
Header 注入
请求走私
XSS
public class CRLFDemo {
public static void main(String[] args) throws Exception { String payload = "user瘍瘊X-Test: hacked"; byte[] bytes = new byte[payload.length()]; for (int i = 0; i < payload.length(); i++) { bytes[i] = (byte) payload.charAt(i); } String result = new String(bytes, "ISO-8859-1"); System.out.println(result); }}
user
X-Test: hacked
Header 响应头被注入了

总结
高危代码
以下这些,只取字符的低 8 位,高位直接丢掉
汉字 → 强转 → 变成英文 / 符号
安全字符 → 悄悄 → 危险字符
(byte) ch
ch & 0xff
writeBytes()
OutputStream.write()
RandomAccessFile.writeBytes()
StringBufferInputStream
URLDecoder.decode()
修复
永远使用:
str.getBytes(StandardCharsets.UTF_8)
不要使用:
(byte)
writeBytes()
check(String)
use(byte)
必须:(同一语义、同一类型、同一编码)这才安全。
Ghost Bits 不是某个漏洞而是一整类漏洞模型,它能变成
- 文件上传绕过
- 路径穿越
- 任意文件读取
- 认证绕过
- SMTP 注入
- 请求走私
- XSS
- RCE 绕过
原PPT是在棉花糖公众号要的,链接是
https://mp.weixin.qq.com/s/Utx64ue7Phs44pCHrpJbrQ
由于个人水平有限,本篇对 Ghost Bits 漏洞的理解仍较为浅显,文中若有疏漏或错误之处,还望各位师傅多多指正,不胜感激!
温馨提示:本文内容仅用于合法授权的安全学习与研究交流,严禁用于未授权渗透测试、漏洞利用或任何违法行为。
涉及企业或平台的未公开漏洞信息,请遵循负责任披露原则,勿公开传播可直接复现的敏感细节。
如存在侵权、错误信息或不当内容,请联系站方处理,我们将及时核实并删除。邮箱:admin@baimaojianghu.com。
