返回介绍

8.2.2 字符串截断

发布于 2024-10-11 22:07:46 字数 3316 浏览 0 评论 0 收藏 0

如果你以前做过渗透测试,那字符串截断应该是我们比较熟悉的一个利用方式,特别是在零几年,在利用文件上传漏洞的时候,经常会用到抓包,然后修改 POST 文件上传数据包里面的文件,在文件名里面加一个%00,用来绕过文件扩展名的检查,又能把脚本文件写入到服务器中,下面我们就来了解下其中的原理吧。

8.2.2.1 %00 空字符截断

字符串截断被利用最多的是在文件操作上面,通常用来利用文件包含漏洞和文件上传漏洞,%00 即 NULL 是会被 GPC 和 addslashes() 函数过滤掉,所以要想用%00 截断需要 GPC 关闭以及不被 addslashes() 函数过滤,另外在 PHP5.3 之后的版本全面修复了文件名%00 截断的问题,这个版本以后也是不能用这种方式截断。为什么 PHP 在文件操作的时候用%00 会截断字符?PHP 基于 C 语言开发,%00 在 URL 解码后为\0,\0 在 C 语言中是字符串结束符,遇到\0 的时候以为到了字符串结尾,不再读取后面的字符串,自然而然的就理解成了截断。

做一个简单的测试,测试代码(1.php)

<?php

include ( $_GET['f'].'.php' );

在同目录下面新建文件 2.txt,内容为输出 phpinfo 信息代码,当我们请求/1.php?f=2.txt%00 时,实际上包含了 2.txt 这个文件,正常执行 phpinfo 代码。

8.2.2.2 iconv 函数字符编码转换截断

iconv() 函数用来做字符编码转换,比如从 UTF-8 转换到 GBK,字符集的编码转换总会存在一定的差异性,导致部分编码不能被成功转换,也就是出现常说的乱码。在使用 iconv() 函数转码的时候,当遇到不能处理的字符串则后续字符串会不被处理。

我们来做一个简单的测试,测试代码如下:

<?php

$a='1'.chr ( 130 ) .'2' ; 

echo $a ; 

echo '<br />' ; 

echo iconv ( "UTF-8" , "gbk" , $a );

我们执行这段代码的行结果如图 8-3 所示。

图 8-3

可以看到第一次输出$a 变量,1 和 2 都被正常输出,当使用 iconv() 函数转换编码后,从 chr(130)字符开始之后的字符串都没有输出,已经被成功截断。经过笔者 fuzz 测试,当我们文件名中有 chr(128)到 chr(255)之间都可以截断字符。

这种截断有很多利用常见,下面我们来看一个真实的案例,乌云平台漏洞【建站之星模糊测试实战之任意文件上传漏洞】,漏洞编号 WooYun-2014-48293,漏洞作者为 felixk3y,漏洞发生在/module/mod_tool.php 文件第 89 行起,img_create() 函数,代码如下:

public function img_create () {

  $file_info =& ParamHolder :: get ( 'img_name' , array (), PS_FILES ); 

  if ( $file_info['error'] > 0 ) {

    Notice :: set ( 'mod_marquee/msg' , __ ( 'Invalid post file data ! ' )); 

    Content :: redirect ( Html :: uriquery ( 'mod_tool' , 'upload_img' )); 

  }

  if (! preg_match ( '/\. ( '.PIC_ALLOW_EXT.' ) $/i' , $file_info["name"] )) {

    Notice :: set ( 'mod_marquee/msg' , __ ( 'File type error ! ' )); 

    Content :: redirect ( Html :: uriquery ( 'mod_marquee' , 'upload_img' )); 

  }

  if ( file_exists ( ROOT.'/upload/image/'.$file_info["name"] )) {

    $file_info["name"] = Toolkit :: randomStr ( 8 ) .strrchr ( $file_info["name"] , "." ); 

    }

    if (! $this->_savelinkimg ( $file_info )) {

       Notice :: set ( 'mod_marquee/msg' , __ ( 'Link image upload failed ! ' )); 

      Content :: redirect ( Html :: uriquery ( 'mod_marquee' , 'upload_img' )); 

    }

这是一个文件上传的代码,其中此漏洞的关键代码在:

if (! $this->_savelinkimg ( $file_info )) {

  Notice :: set ( 'mod_marquee/msg' , __ ( 'Link image upload failed ! ' )); 

  Content :: redirect ( Html :: uriquery ( 'mod_marquee' , 'upload_img' )); 

}

在这里调用_savelinkimg() 函数保存文件,跟进该函数,函数代码如下:

private function _savelinkimg ( $struct_file ) {

  $struct_file['name'] = iconv ( "UTF-8" , "gb2312" , $struct_file['name'] ); 

  echo $struct_file['name'] ; 

  move_uploaded_file ( $struct_file['tmp_name'] , ROOT.'/upload/image/'.$struct_ file['name'] ); 

  return ParamParser :: fire_virus ( ROOT.'/upload/image/'.$struct_file['name'] ); 

}

代码中:

$struct_file['name'] = iconv ( "UTF-8" , "gb2312" , $struct_file['name'] );

对文件名进行转码,之后:

move_uploaded_file ( $struct_file['tmp_name'] , ROOT.'/upload/image/'.$struct_file['name'] );

写入文件,这里就出现了我们上面说到的编码转换,最终导致可以上传任意文件。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文