Unicorn Shop:Unicode Numeric 类型转换绕过
记录 Unicorn Shop 题目中利用 Unicode numeric value 绕过单字符价格限制的分析过程。
一、核心考点
- Python
unicodedata模块 - Unicode 字符与
unicodedata.numeric() - 字符串长度限制
- 类型转换与输入验证逻辑错误
- Unicode 绕过
二、题目核心逻辑
商品 ID 为 4 的价格是 1337,但题目限制 price: Only one char allowed!,也就是要求 len(price) == 1。
普通输入 1337 的长度为 4,显然无法直接通过限制。

三、关键突破点
通过报错或源码发现,后端使用了 unicodedata.numeric(price),并且要求输入只有一个字符。这个函数接受的范围远远超过普通的 0-9:Unicode 中存在不同语言的数字、罗马数字和数字形式等特殊字符。
本题中找到的埃塞俄比亚数字字符“万”,长度为 1,但 numeric value 为 10000,因此可以参与价格判断。
四、用 Python 自动寻找特殊字符
可以使用下面的辅助脚本,查找 Unicode 中数值不小于 1337 的字符:
import unicodedata
for i in range(0x10000):
char = chr(i)
value = unicodedata.numeric(char, None)
if value is not None and value >= 1337:
print(
"字符:", repr(char),
"数值:", value,
"Unicode:", hex(i)
)
五、为什么这是漏洞,而不是 Python 的 Bug?
unicodedata.numeric() 本身没有问题。问题在于,开发者的预期是“用户输入一个普通数字”,但实际代码允许任意具有 numeric value 的 Unicode 字符参与价格判断。
因此,这属于输入验证或类型转换逻辑错误,而不是 unicodedata.numeric() 存在漏洞。
一句话记忆
本题通过单字符限制阻止 1337,但后端使用 unicodedata.numeric() 将具有 Unicode numeric 属性的字符转换为数值,因此可以利用 numeric value 为 10000 的埃塞俄比亚数字字符,在 len=1 的情况下绕过价格限制。
小结
遇到数字输入限制时,除了检查长度和字符集,还要确认后端实际采用的类型转换函数,以及它对 Unicode 字符的处理范围。