Source code for pysap.SAPIGS

# encoding: utf-8
# pysap - Python library for crafting SAP's network protocols packets
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# Author:
#   Martin Gallo (@martingalloar)
#   Code contributed by SecureAuth to the OWASP CBAS project

# External imports
from scapy.layers.inet import TCP
from scapy.packet import Packet, bind_layers
from scapy.fields import ByteField, StrFixedLenField
# Custom imports
from pysap.SAPNI import SAPNI
from pysap.utils.fields import StrFixedLenPaddedField
# Optional imports
    from requests import Request
except ImportError:
    Request = None

# IGS Request Interpreter
# Not used yet, but it list interpreters
igs_req_interpreter = {
    1: "ZIPPER",           # ZIP provide file(s)
    2: "IMGCONV",          # Image converter
    3: "RSPOCONNECTOR",    # Remote Spool Connector
    4: "XMLCHART",         # Chart generator through XML input
    5: "CHART",            # Chart generator through ABAP Table input
    6: "BWGIS",            # BW Geographic Information System
    7: "SAPGISXML",        # old SAP GIS through XML input
""" IGS Request Interpreter """

# IGS Request Administrator function
# Not used yet, but it list admin functions
igs_req_adm = {
    1: "ADM:REGPW",              # Register a PortWatcher
    2: "ADM:UNREGPW",            # Unregister a PortWatcher
    3: "ADM:REGIP",              # Register an Interpreter
    4: "ADM:UNREGIP",            # Unregister an Interpreter
    5: "ADM:FREEIP",             # Inform than Interpreter is free
    6: "ADM:ILLBEBACK",          # Call back function
    7: "ADM:ABORT",              # Abort Interpreter work
    8: "ADM:PING",               # Ping receive
    9: "ADM:PONG",               # Ping send
    10: "ADM:SHUTDOWNIGS",       # Shutdown IGS
    11: "ADM:SHUTDOWNPW",        # Shutdown PortWatcher
    12: "ADM:CHECKCONSUMER",     # Check Portwatcher status
    13: "ADM:FREECONSUMER",      # Inform than Portwatcher is free
    14: "ADM:GETLOGFILE",        # Display log file
    15: "ADM:GETCONFIGFILE",     # Display configfile
    16: "ADM:GETDUMP",           # Display dump file
    17: "ADM:DELETEDUMP",        # Delete dump file
    18: "ADM:INSTALL",           # Upload shape files for GIS
    19: "ADM:SWITCH",            # Switch trace log level
    20: "ADM:GETVERSION",        # Get IGS Version
    21: "ADM:STATUS",            # Display IGS Status
    22: "ADM:STATISTIC",         # old Display IGS Statistic
    23: "ADM:STATISTICNEW",      # Display IGS Statistic
    24: "ADM:GETSTATCHART",      # Get IGS Statistic chart
    25: "ADM:SIM",               # Simulation function
"""IGS Request Administrator function"""

[docs]class SAPIGSTable(Packet): """SAP IGS table description Mandatory for RFC call type. This describes table name/width/length where content will be stored. """ name = "SAP IGS Table description" fields_desc = [ StrFixedLenPaddedField("version_label", "VERS", length=4), StrFixedLenPaddedField("version", " 1.0", length=44), StrFixedLenPaddedField("table_name_label", "TBNM", length=4), StrFixedLenPaddedField("table_name", "", length=44), StrFixedLenPaddedField("table_line_label", "TBLN", length=4), StrFixedLenPaddedField("table_line", "", length=44), StrFixedLenPaddedField("table_width_label", "TBWD", length=4), StrFixedLenPaddedField("table_width", "", length=44), StrFixedLenPaddedField("table_column_label", "TBCL", length=4), StrFixedLenPaddedField("table_column", "", length=44), StrFixedLenPaddedField("column_name_label", "CLNM", length=4), StrFixedLenPaddedField("column_name", "", length=44), StrFixedLenPaddedField("column_width_label", "CLWD", length=4), StrFixedLenPaddedField("column_width", "", length=44), ]
[docs] @staticmethod def add_entry(t_name, t_line, t_width, t_column, c_name, c_width, **kwargs): """Add an entry into Table description This where custom content is stored Entry must be write from the end like : ' abcd' :param t_name: name of table :type t_name: ``string`` :param t_line: number of line :type t_line: ``int`` :param t_width: width of table :type t_width: ``int`` :param t_column: number of column :type t_column: ``int`` :param c_name: name of column :type c_name: ``string`` :param c_width: width of column :type c_width: ``int`` :return: SAP IGS Table :rtype: :class:`SAPIGSTable` """ NewEntry = SAPIGSTable(table_name=format(t_name, ">43"), table_line=format(t_line, ">43"), table_width=format(t_width, ">43"), table_column=format(t_column, ">43"), column_name=format(c_name, ">43"), column_width=format(c_width, ">43") ) return NewEntry
[docs]class SAPIGS(Packet): """SAP Internet Graphic Server call packet This packet is used for the Remote IGS Function Call protocol. """ name = "SAP IGS Call" fields_desc = [ StrFixedLenPaddedField("function", "", padd="\x00", length=32), StrFixedLenPaddedField("listener", "ListenerX", padd="\x00", length=32), StrFixedLenPaddedField("hostname", "pysap", padd="\x00", length=81), StrFixedLenPaddedField("id", "1234", padd="\x00", length=4), StrFixedLenPaddedField("padd1", "\x00" * 15, length=15), ByteField("todo1", 0x01), # TODO: need to work on it StrFixedLenPaddedField("padd2", "\x00" * 20, length=20), ByteField("todo2", 0x08), # TODO: need to work on it StrFixedLenPaddedField("padd3", "\x00" * 6, length=6), StrFixedLenField("eye_catch", "TransMagic", length=10), StrFixedLenPaddedField("padd4", "\x00" * 2, length=2), StrFixedLenField("codepage", "4103", length=4), StrFixedLenPaddedField("offset_content", "", padd="\x00", length=16), StrFixedLenPaddedField("packet_size", "", padd="\x00", length=16), ]
[docs] @staticmethod def http(host, port, interpreter, files=None, tls=False, method='POST'): """HTTP request for IGS This method build a http(s) request for IGS HTTP Multiplexer service instead of Remote IGS Function Call :param host: remote host to connect to :type host: ``string`` :param port: remote port to connect to :type port: ``int`` :param interpreter: interpreter of function to call :type interpreter: ``string`` :param files: list of files to send in case of multipart/form-data :type files: ``dict`` :param tls: using https or not :type tls: ``bool`` :param method: HTTP request method to use :type method: ``string`` :return: the HTTP request to send as raw :rtype: ``string`` :raise ImportError: if the requests library can't be imported """ if Request is None: raise ImportError("requests library not available") protocol = 'https' if tls else 'http' url = "%s://%s:%d/%s" % (protocol, host, port, interpreter) # forge url # using PreparedRequest to retrieve the raw http request req = Request(method, url, files=files).prepare() # update User-Agent header req.headers['User-Agent'] = 'pysap' # format the request than could be send with SAP NI req_format = ('{}\r\n{}\r\n\r\n{}'.format( req.method + ' ' + req.url + ' HTTP/1.1', '\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()), req.body) ) return req_format
# Bind SAP NI with the IGS ports bind_layers(TCP, SAPNI, dport=40000) bind_layers(TCP, SAPNI, dport=40080)