Unicode 的视觉欺骗

Unicode 的视觉欺骗

新闻来源:特洛伊之源| 在 Rust 代码中隐藏无形的漏洞 作者: 张汉东

https://trojansource.codes/ 给出了更详细的解释。比如这段代码

1
2
3
4
5
6
7
8
// 该文件包含双向Unicode文本,其解释或编译方式可能与下面的内容不同。要审查,请在一个能显示隐藏的Unicode字符的编辑器中打开该文件。
// 执行输出 
fn main() {
    let is_admin = false;
    /*‮ } ⁦if is_admin⁩ ⁦ begin admins only */
        println!("You are an admin.");
    /* end admins only ‮ { ⁦*/
}

上面这段代码在最新的 VSCode 会有非常明显的隐藏字符提示。

https://cdn.ftls.xyz/images/2021/12/20211206.png
明显的隐藏字符提示"

有时,Unicode 会视觉欺骗,不会有明显提示。比如say_hello和say_һello,看上去没有区别,实际并不相同。你可以通过浏览器带的搜索,看到这两个不能同时被搜索。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
fn main() {
    fn say_hello() {
        println!("Hello, World!\n");
    }
    fn say_һello() {
        println!("Goodbye, World!\n");
    }
    say_hello();
    say_һello();

    let str1 = String::from("say_hello");
    let str2 = String::from("say_һello");
    for i in str1.as_bytes() { print!("{} ", i); }
    println!("");
    for i in str2.as_bytes() { print!("{} ", i); }
}

执行结果

1
2
3
4
5
6
Hello, World!

Goodbye, World!

115 97 121 95 104 101 108 108 111
115 97 121 95 210 187 101 108 108 111

完整结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
> Executing task: ~/.cargo/bin/cargo run <

   Compiling mo v0.1.0 (D:\rustcode\mo)
warning: identifier pair considered confusable between `say_hello` and `say_һello`
 --> src\main.rs:5:8
  |
2 |     fn say_hello() {
  |        --------- this is where the previous identifier occurred
...
5 |     fn say_һello() {
  |        ^^^^^^^^^
  |
  = note: `#[warn(confusable_idents)]` on by default

warning: The usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables
 --> src\main.rs:5:8
  |
5 |     fn say_һello() {
  |        ^^^^^^^^^
  |
  = note: `#[warn(mixed_script_confusables)]` on by default
  = note: The usage includes 'һ' (U+04BB).
  = note: Please recheck to make sure their usages are indeed what you want.

warning: `mo` (bin "mo") generated 2 warnings
    Finished dev [unoptimized + debuginfo] target(s) in 1.38s
     Running `target\debug\mo.exe`
Hello, World!

Goodbye, World!

115 97 121 95 104 101 108 108 111
115 97 121 95 210 187 101 108 108 111
终端将被任务重用,按任意键关闭。