Example #1
0
    def remove_cipher_suite(self, cipher_suite):
        """
        Remove a cipher suite from the list.
        """

        try:
            self._cipher_suites_keys.remove(cipher_suite)
        except AttributeError as missing_key:
            g_exception_logger.exception(missing_key)
Example #2
0
def remove_monitor_interface(monitor_iface_name):
    """
    Remove the virtual monitor interface that should have been added at
    startup.
    """

    index = get_interface_index(monitor_iface_name)
    if index:
        try:
            with IW() as iw:
                iw.del_interface(index)
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
Example #3
0
    def _associate(self):

        """
        Send an Association request.
        """

        err_occurred = False

        # Prepare the RSN IEs
        information_elements = bytes()
        if self._rsn:
            information_elements = bytes(self._rsn)

        if self._ms_wpa_ie:
            information_elements += bytes(self._ms_wpa_ie)

        try:
            with IW() as iw: # pylint: disable-msg=C0103
                g_default_logger.info("Trying to associate ...")
                iw.associate(
                    self._iface_index,
                    self._bssid,
                    self._ssid,
                    self._frequency,
                    info_elements=information_elements
                )
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
            err_occurred = True

            # At this point, the association process probably failed
            while err_occurred:
                time.sleep(0.05)
                try:
                    with IW() as iw: # pylint: disable-msg=C0103
                        g_default_logger.info("Trying to associate ...")
                        iw.associate(
                            self._iface_index,
                            self._bssid,
                            self._ssid,
                            self._frequency,
                            info_elements=information_elements
                        )
                        err_occurred = False
                except NetlinkError as netlink_err_:
                    g_exception_logger.exception(netlink_err_)
                    err_occurred = True

        return err_occurred
Example #4
0
def get_interface_index(iface_name):
    """
    Return the interface index.
    """

    interface_index = None

    try:
        with IPRoute() as ip:
            data = ip.link_lookup(ifname=iface_name)
            if data:
                interface_index = data[0]
    except NetlinkError as netlink_err:
        g_exception_logger.exception(netlink_err)

    return interface_index
Example #5
0
def get_wireless_interface_mac_addr(interface_index):
    """
    Return the MAC address of a wireless interface.
    """

    mac_address = None

    try:
        with IW() as iw:
            data = iw.get_interface_by_ifindex(interface_index)
            if data:
                mac_address = data[0].get_attr("NL80211_ATTR_MAC")
    except NetlinkError as netlink_err:
        g_exception_logger.exception(netlink_err)

    return mac_address
Example #6
0
    def _authenticate(self):
        """
        Send an Authentication frame.
        """

        err_occurred = False

        try:
            with IW() as iw:  # pylint: disable-msg=C0103
                iw.authenticate(self._iface_index, self._bssid, self._ssid,
                                self._frequency)
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
            err_occurred = True

        return err_occurred
Example #7
0
    def _scan(self):

        """
        Perform a scan and retrieve information related to the target SSID.
        """

        err_occurred = False
        bss_status_attr = None
        found = False
        rsn_ie_data = None
        vendor_ie_data = None

        try:
            with IW() as iw: # pylint: disable-msg=C0103
                scan_results = iw.scan(
                    self._iface_index,
                    [self._ssid],
                    flush_cache=True
                )
                bss_attr = None
                for result in scan_results:
                    bss_attr = result.get_attr('NL80211_ATTR_BSS')
                    if bss_attr is not None:
                        attrs = bss_attr["attrs"]
                        bss_ie = [x[1] for x in attrs if x[0] == \
                            "NL80211_BSS_INFORMATION_ELEMENTS"]
                        if bss_ie:
                            # Get SSID
                            ssid = bss_ie[0].get("SSID", None)
                            if ssid.decode("ascii") == self._ssid:
                                # Get RSN IEs
                                rsn_ie_data = bss_ie[0].get("RSN", None)
                                vendor_ie_data = bss_ie[0].get("VENDOR", None)
                                found = True
                                break
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
            err_occurred = True

        if found:
            self._bssid = bss_attr.get_attr("NL80211_BSS_BSSID")
            self._frequency = bss_attr.get_attr("NL80211_BSS_FREQUENCY")
            from_presp = bss_attr.get_attr('NL80211_BSS_PRESP_DATA')
            self._ssid_info_learned_in_presp = True if from_presp else False
            bss_status_attr = bss_attr.get_attr("NL80211_BSS_STATUS")

        return err_occurred, bss_status_attr, rsn_ie_data, vendor_ie_data
Example #8
0
    def _deauthenticate(self):
        """
        Send a Deauthentication frame.
        """

        err_occurred = False

        try:
            with IW() as iw:  # pylint: disable-msg=C0103
                iw.deauthenticate(self._iface_index,
                                  self._bssid,
                                  reason_code=0x01)
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
            err_occurred = True

        return err_occurred
Example #9
0
    def _disassociate(self):
        """
        Send a Disassociation request.
        """

        err_occurred = False

        try:
            with IW() as iw:  # pylint: disable-msg=C0103
                iw.disassociate(self._iface_index,
                                self._bssid,
                                reason_code=0x08)
        except NetlinkError as netlink_err:
            g_exception_logger.exception(netlink_err)
            err_occurred = True

        return err_occurred
Example #10
0
def get_mac_addr(interface_name):
    """
    Returns the MAC address of a given network interface.
    """

    mac_addr = None

    try:
        with IPDB() as ipdb:
            with ipdb.interfaces[interface_name] as interface:
                mac_addr = interface["address"]

    except KeyError as key_err:
        g_exception_logger.exception(key_err)
    except Exception as exception:
        g_exception_logger.exception(exception)

    return mac_addr
Example #11
0
def set_interface_operstate(iface_index, linkmode, operstate):
    """
    Set interface operational state.
    https://www.kernel.org/doc/Documentation/networking/operstates.txt
    """

    done = True

    try:
        with RawIPRoute() as rawip:
            rawip.link('set',
                       index=iface_index,
                       IFLA_LINKMODE=linkmode,
                       IFLA_OPERSTATE=operstate)
    except NetlinkError as netlink_err:
        g_exception_logger.exception(netlink_err)
        done = False

    return done
Example #12
0
def network_interface_status(interface_name):
    """
    Returns True if the network interface "interface_name" is up, False
    otherwise.
    """

    interface_up = False

    try:
        with IPDB() as ipdb:
            with ipdb.interfaces[interface_name] as interface:
                interface_up = interface["operstate"]

    except KeyError as key_err:
        g_exception_logger.exception(key_err)
    except Exception as exception:
        g_exception_logger.exception(exception)

    return interface_up
Example #13
0
def get_interface_operstate(iface_name):
    """
    Set interface operational state.
    https://www.kernel.org/doc/Documentation/networking/operstates.txt
    """

    operstate = None

    try:
        with IPDB() as ipdb:
            if iface_name in ipdb.interfaces.keys():
                with ipdb.interfaces[iface_name] as interface:
                    operstate = interface["operstate"]
    except KeyError as key_err:
        g_exception_logger.exception(key_err)
    except Exception as exception:
        g_exception_logger.exception(exception)

    return operstate
Example #14
0
def setup_wireless_interfaces(wireless_iface_name):
    """
    Create a monitor interface ("ra0"), if it does not exist already.
    Bring the wireless interface up if necessary.
    """

    setup_complete = True

    # Get interface index
    iface_index = get_interface_index(wireless_iface_name)

    # Check if it is a provided interface
    if not is_wireless_interface(iface_index):
        setup_complete = False
        g_exception_logger.error("%s is not a wireless interface.",\
wireless_iface_name)
    else:
        if not get_interface_index(MONITOR_INTERFACE_NAME):
            # Create a monitor interface
            try:
                with IW() as iw:
                    iw.add_interface(MONITOR_INTERFACE_NAME, 6, iface_index)
            except NetlinkError as netlink_err:
                g_exception_logger.exception(netlink_err)
                return False

        # Set the monitor interface "administratively" up
        if not set_interface_admin_state(MONITOR_INTERFACE_NAME,
                                         admin_up=True):
            g_exception_logger.error("Could not set %s administratively up",\
MONITOR_INTERFACE_NAME)
            setup_complete = False

        # Set the interface "administratively" up
        if not set_interface_admin_state(wireless_iface_name, admin_up=True):
            g_exception_logger.error("Could not set %s administratively up",\
wireless_iface_name)
            setup_complete = False

    return setup_complete
Example #15
0
def set_interface_admin_state(iface_name, admin_up=True):
    """
    Set interface "iface_name" administrative state.
    """

    done = True

    try:
        with IPDB() as ipdb:
            with ipdb.interfaces[iface_name] as interface:
                if admin_up:
                    interface["flags"] |= IFF_UP
                else:
                    interface["flags"] = ~IFF_UP
    except KeyError as key_err:
        g_exception_logger.exception(key_err)
        done = False
    except Exception as exception:
        g_exception_logger.exception(exception)
        done = False

    return done
Example #16
0
    def start(self):
        """
        Start listening for incoming frames.
        """

        resume_scanning = True
        self._running = True

        try:
            self._socket = L2ListenSocket(iface=self._iface)
        except OSError as err:
            g_default_logger.error(
                "Cannot listen on the provided interface \
(%s).", self._iface)
            g_exception_logger.exception(err)

        while self._running:
            try:
                read, _, __ = select.select([self._socket], [], [], 0.05)
                if read:
                    frame = self._socket.recv()
                    if frame.src != self._local_mac_addr:
                        self._handle_received_frame(frame)

                if resume_scanning:
                    # Send an EAPOL-Start frame to try to start the authentication
                    # process.
                    eapol_start_frame = EAPOL(version=self._eapol_version,
                                              type=1)
                    self.send_frame(eapol_start_frame)
                    resume_scanning = False

            except socket.error as err_mess:
                g_exception_logger.exception(err_mess)
                self._running = False

            except KeyboardInterrupt as keyboard_interrupt:
                # This exception should be caught (ra.py)
                raise keyboard_interrupt
Example #17
0
def main(argv):
    """
    Handles command line options.
    """

    program_name = __prog__
    program_version = "v{}".format(__version__)
    program_build_date = str(__updated__)
    program_version_message = "{} {} ({})".format(program_name,
                                                  program_version,
                                                  program_build_date)
    program_shortdesc = "radius-audit - A tool to audit RADIUS authentication servers."
    program_license = """{}

USAGE

Attempt to discover the phase 1 EAP authentication methods:
ra -iface eth0 -identity anonymous --discover-phase-1

Test if the server supports TLS_RSA_WITH_AES_128_CBC_SHA using TLS 1.1:
ra -iface eth0 -identity anonymous -tls-versions tls11 -tls-ciphers 0x002f

Attempt to perform a complete SSL/TLS scan:
ra -iface eth0 -identity anonymous --tls-scan
""".format(program_shortdesc)

    scanner = None
    try:
        parser = argparse.ArgumentParser(
            prog=__prog__,
            description=program_license,
            formatter_class=argparse.RawDescriptionHelpFormatter,
        )
        parser.add_argument("-v",
                            "--verbose",
                            dest="verbose",
                            action="count",
                            help="set verbosity level [default: %(default)s]")
        parser.add_argument("-V",
                            "--version",
                            action="version",
                            version=program_version_message)
        parser.add_argument(
            "-iface",
            action="store",
            dest="interface",
            type=str,
            required=True,
            help="provide the network interface to use. Example: eth0")
        parser.add_argument("-ssid",
                            action="store",
                            dest="ssid",
                            type=str,
                            required=False,
                            help="provide the SSID. Example: test-ssid")
        parser.add_argument(
            "-identity",
            action="store",
            dest="identity",
            type=str,
            default="anonymous",
            required=False,
            help="provide the identity of the peer. Example: anonymous")
        parser.add_argument(
            "--discover-phase-1",
            action="store_true",
            required=False,
            help="attempt to discover authorized phase 1 EAP authentication \
methods.")
        parser.add_argument(
            "-phase-1-methods",
            action="store",
            type=str,
            required=False,
            help="test if the given EAP authentication methods are supported. \
Example: 13,21,25 (list of EAP types)")
        parser.add_argument(
            "-with-eap-method",
            action="store",
            type=str,
            required=False,
            help="specify an EAP authentication method based on TLS: \
\"tls\", \"ttls\", or \"peap\".")
        parser.add_argument(
            "-tls-versions",
            action="store",
            type=str,
            required=False,
            help="provide a list of specific SSL/TLS versions (sslv2, sslv3, \
tls10, tls11, tls12).")
        parser.add_argument(
            "-tls-ciphers",
            action="store",
            type=str,
            required=False,
            help="provide a list of SSL/TLS ciphersuites (hex format). \
Example: 0x002e,0x002f")
        parser.add_argument(
            "--tls-scan",
            action="store_true",
            required=False,
            help="attempt to discover available SSL/TLS versions, as well as \
supported ciphersuites. By default, attempts will be made using EAP-TLS. To \
specify another EAP method based on TLS, use the -with-eap-method parameter.")
        parser.add_argument(
            "-min-tls-version",
            action="store",
            type=str,
            required=False,
            help="start the scan from the given SSL/TLS version (sslv2, sslv3,\
 tls10, tls11, tls12).")
        parser.add_argument("--json-output",
                            action="store_true",
                            required=False,
                            help="print the results in JSON format.")

        if len(argv) < 2:
            parser.print_help()
            return -1

        args = parser.parse_args()
        verbose = args.verbose or 0
        g_default_logger.setLevel(max(3 - verbose, 0) * 10)
        g_traffic_logger.setLevel(max(3 - verbose, 0) * 10)

        # Check if provided network interface exists
        interface_index = get_interface_index(args.interface)
        if not interface_index:
            g_default_logger.error("Could not find interface %s",\
args.interface)
            return -1

        mac_addr = None
        ssid = None
        if args.ssid:
            if not is_wireless_interface(interface_index):
                g_default_logger.error(
                    "Provided network interface \
(%s) is not a wireless interface.", args.interface)
                return -1

            ssid = args.ssid
            mac_addr = get_wireless_interface_mac_addr(interface_index)
            if not mac_addr:
                g_default_logger.error(
                    "Provided network interface \
(%s) doe    s not exist.", args.interface)
                return -1

            if not setup_wireless_interfaces(args.interface):
                g_default_logger.error("Could not setup the interfaces.")
                return -1

        else:
            if is_wireless_interface(interface_index):
                g_default_logger.error(
                    "Provided network interface \
(%s) is not a wired interface.", args.interface)
                return -1

            # Check if provided network interface is up
            if not network_interface_status(args.interface):
                g_default_logger.error(
                    "Provided network interface (%s) is \
down.", args.interface)
                return -1

            mac_addr = get_mac_addr(args.interface)
            if not mac_addr:
                g_default_logger.error(
                    "Provided network interface \
(%s) does not exist.", args.interface)
                return -1

        # Set the interface operational state to "DORMANT"
        if not set_interface_operstate(interface_index, 1, "DORMANT"):
            g_default_logger.warn(
                "Could not set %s operational state to \
DORMANT.", args.interface)

        discover_phase_1 = False
        phase_1_methods = None
        with_eap_method = None
        tls_scan = False
        tls_versions = None
        tls_ciphers = None
        tls_min_version = None
        json_output = None
        if args.discover_phase_1:
            discover_phase_1 = True
        if args.phase_1_methods:
            phase_1_methods = []
            tmp = args.phase_1_methods.split(',')
            for val in tmp:
                if is_integer(val):
                    phase_1_methods.append(int(val))
        if args.with_eap_method:
            tmp = args.with_eap_method.strip().split(',')
            if not tmp[0] in TLS_BASED_METHODS_BY_NAME:
                print("{} is not a valid / supported \"TLS-based\" EAP \
authentication method. Please choose one of the following: \
\"tls\", \"ttls\", or \"peap\".".format(tmp[0]),
                      file=sys.stderr)
                return -1
            with_eap_method = TLS_BASED_METHODS_BY_NAME[tmp[0]]
        if args.tls_versions:
            tls_versions = []
            tmp = args.tls_versions.split(',')
            for val in tmp:
                tls_version = get_tls_version_value_from_name(val)
                if not tls_version:
                    print("{} is not a valid / supported SSL/TLS version. \
Please choose one of the following: sslv2, sslv3, tls10, tls11, tls12."                                                                       .\
format(val), file=sys.stderr)
                    return -1
                else:
                    tls_versions.append(tls_version)
        tls_ciphers = []
        if args.tls_ciphers:
            tmp = args.tls_ciphers.split(',')
            for val in tmp:
                if is_hex_value(val):
                    cs_val = int(val, 16)
                    if not cipher_suite_is_valid(cs_val):
                        print("{} is not a valid / supported cipher suite.".\
format(val), file=sys.stderr)
                        return -1
                    else:
                        tls_ciphers.append(cs_val)
        if args.tls_scan:
            tls_scan = True
        if args.min_tls_version:
            tls_version = get_tls_version_value_from_name(args.min_tls_version)
            if not tls_version:
                print("{} is not a valid / supported SSL/TLS version.\n\
Please choose one of the following: sslv2, sslv3, tls10, tls11, tls12."                                                                       .\
format(tls_version), file=sys.stderr)
                return -1
            # Keep the "name" of the version instead of its actual value
            tls_min_version = args.min_tls_version
        if args.json_output:
            json_output = True

        if discover_phase_1:
            with_eap_method = None
            tls_scan = False
            tls_versions = None
            tls_ciphers = None
            tls_min_version = None

        elif phase_1_methods:
            with_eap_method = None
            tls_scan = False
            tls_versions = None
            tls_ciphers = None
            tls_min_version = None

        else:
            # By default, the tool will attempt to setup TLS sessions using
            # EAP-TLS.
            tls_scan = True

        # Create and start the "scanner"
        scanner = Scanner(args.interface, mac_addr, args.identity, ssid,
                          phase_1_methods, with_eap_method, tls_versions,
                          tls_ciphers, tls_scan, tls_min_version, json_output)
        scanner.start()

    except KeyboardInterrupt as keyboard_exception:
        g_exception_logger.exception(keyboard_exception)
        if scanner:
            scanner.stop()
        if is_wireless_interface(interface_index):
            remove_monitor_interface(MONITOR_INTERFACE_NAME)
        return -1

    except Exception as exception:
        g_exception_logger.exception(exception)
        if scanner:
            scanner.stop()
        if is_wireless_interface(interface_index):
            remove_monitor_interface(MONITOR_INTERFACE_NAME)
        return -1

    if is_wireless_interface(interface_index):
        remove_monitor_interface(MONITOR_INTERFACE_NAME)

    return 0
Example #18
0
    def start(self):

        """
        Start listening for incoming frames.
        """

        # Open a socket that will be used to send frames
        self._socket = socket.socket(
            socket.AF_PACKET,
            socket.SOCK_DGRAM,
            socket.htons(ETH_P_ALL)
        )

        # Open a socket on the monitor interface
        self._monitor_socket = L2ListenSocket(iface=MONITOR_INTERFACE_NAME)

        i = 0
        self._running = True
        while self._running:
            try:
                read, _, __ = select.select([self._monitor_socket.fileno()], [], [], 0.05)
                if read:
                    data_ = self._monitor_socket.recv(4096)
                    frame = RadioTap(data_)

                    if Dot11 in frame and\
                        frame[Dot11].addr2 != self._local_mac_addr:
                        self._handle_received_frame(frame)

                # Every 2.5+ seconds, try to detect any association loss
                if not i % 50:
                    association_loss = self._detect_association_loss()
                    if association_loss:
                        g_default_logger.info("Not associated with %s \
anymore.", self._bssid)
                        self._clear_ssid_info()
                    i = 0

                # If we're not associated, trigger a new scan in order to
                # retrieve necessary information
                if not self._has_ssid_info():
                    self._prepare()
                else:
                    if self._association_status != \
                        WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED:
                        # Info retrieved in a Probe Response ?
                        # If so, scan in order to get (hopefully) up-to-date
                        # data in another Probe Response
                        if self._previously_associated and \
                            self._ssid_info_learned_in_presp:
                            self._prepare()
                    else:
                        if not self._authentication_status == \
                            WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING or \
                            not i % 20:
                            if not self._authenticate():
                                self._authentication_status = \
                                    WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING
                            else:
                                g_default_logger.warning("Could not \
authenticate")

                i = i + 1

            except socket.error as err_mess:
                g_exception_logger.exception(err_mess)
                self._running = False

            except KeyboardInterrupt as keyboard_interrupt:
                # This exception should be caught (ra.py)
                raise keyboard_interrupt