躲开 cat 命令
9unk Lv5

命令运行机制

cat 命令是从一个位置读取内容,然后再把内容输入到另一个位置。一般 cat 命令会将读取的内容输出到 STDOUT,可以理解为输出到屏幕上。cat 还支持一些控制字符,例如 回车符\r,换行符\n 等等。

躲开 cat 命令

下面会用一个例子来证明,如何用 \r 对 cat 命令隐藏并执行 shell 脚本命令:

  1. 编写一个 python 脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cmd_h = "echo 'You forgot to check `cat -A`!' > oops" # hidden
cmd_v = "echo 'Hello world!'" # visible

with open("test.sh", "w") as f:
output = "#!/bin/sh\n"
output += cmd_h + ";" + cmd_v + " #\r" + cmd_v + " " * (len(cmd_h) + 3) + "\n"
f.write(output)

# 将双引号里面的值赋给变量 cmd_h
# 将双引号里面的值赋给变量 cmd_v
# 创建 test.sh 并写入下面的内容,如果有 test.sh 则覆盖重写内容
# 将双引号里面的值赋给变量 output
# 变量 output 追加内容
# 将内容写到 test.sh 中
  1. 滥用 cat 默认行为

cat 默认会执行 \r 控制字符,在 test.sh 中显示为蓝色的 ^M。

本质上,\r 会将光标移回该行的开头,其后打印的字符将会被覆盖(覆盖)先前打印的任何内容。这也是为什么我们在字符串的末尾添加空格。

因此当运行 cat test.sh 时:

1
2
3
[root@localhost command]# cat test.sh 
#!/bin/sh
echo 'Hello world!'

但是实际运行的字符串如下:

1
2
echo 'You forgot to check `cat -A`!' > oops
echo 'Hello world!'
  1. 不经意执行 test.sh
1
2
3
4
5
6
7
8
[root@localhost command]#  ls
test.sh
[root@localhost command]# sh ./test.sh
Hello world!
[root@localhost command]# ls
oops test.sh
[root@localhost command]# cat oops
You forgot to check `cat -A`!

解决方法

  1. 查看 test.sh 的大小和 cat 的内容是否匹配
  2. 使用 less、vim、vi 等命令打开文件
  3. 使用 cat -A 来查看文件,禁止执行控制字符
1
2
3
[root@localhost command]#  cat -A test.sh
#!/bin/sh$
echo 'You forgot to check `cat -A`!' > oops;echo 'Hello world!' #^Mecho 'Hello world!'

reference

Hiding from cats

  • 本文标题:躲开 cat 命令
  • 本文作者:9unk
  • 创建时间:2019-11-17 15:53:17
  • 本文链接:https://9unkk.github.io/2019/11/17/duo-kai-cat-ming-ling/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!