[Plugins-writers] ike_detect - minor bug fix

From: Paul Johnston (paul@private)
Date: Thu May 06 2004 - 08:34:32 PDT

  • Next message: hallnk@private: "[Plugins-writers] Checking Windows Patches Using Registry"

    Hi,
    
    A tweak to make it report at 500/udp not 500/tcp, in one of the cases.
    
    Paul
    
    -- 
    Paul Johnston
    Internet Security Specialist
    Westpoint Limited
    Albion Wharf, 19 Albion Street,
    Manchester, M1 5LN
    England
    Tel: +44 (0)161 237 1028
    Fax: +44 (0)161 237 1031
    email: paul@private
    web: www.westpoint.ltd.uk
    
    
    
    283c283
    <     if (  (ord(r[16]) == 0x0B) && (ord(r[18]) == 0x05)  ) security_warning(port);
    ---
    >     if (  (ord(r[16]) == 0x0B) && (ord(r[18]) == 0x05)  ) security_warning(port, protocol:"udp");
    
    
    #
    # (C) Tenable Network Security
    #
    # script audited and subsequently patched thanks to submission by Bert Salaets
    
    if(description) {
     script_id(11935);
     script_version("$Revision: 1.4 $");
    
     name["english"] = "IPSEC IKE detection";
     script_name(english:name["english"]);
    
     desc["english"] =
    "The remote host seems to be enabled to do Internet Key
    Exchange (IKE).  This is typically indicative of a VPN server.
    VPN servers are used to connect remote hosts into internal
    resources.
    
    Solution: You should ensure that:
    1) The VPN is authorized for your Companies computing environment
    2) The VPN utilizes strong encryption
    3) The VPN utilizes strong authentication
    
    Risk factor : Low";
    
     script_description(english:desc["english"]);
    
     summary["english"] = "IPSEC IKE detect";
     script_summary(english:summary["english"]);
    
     script_category(ACT_GATHER_INFO);
    
     script_copyright(english:"This script is Copyright (C) 2003 Tenable Network Security");
     family["english"] = "General";
     script_family(english:family["english"]);
     exit(0);
    }
    
    #
    # The script code starts here
    #
    
    
    function calc_data() {
        T_PAY1 = T_NP + T_RES + T_PLEN + T_NUM + T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3
    + T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 +  T_AC6 + T_ALEN + T_AV6;
    
       for (MU=2; MU < TRANSFORM_MAX; MU++) {
    
        TPAY[MU] = T_NP + T_RES + T_PLEN + raw_string(MU) + T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3 + T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 + T_AC6 + T_ALEN + T_AV6;
    
    }
    
    TPAY[MU] = raw_string(0x00) + T_RES + T_PLEN + raw_string(MU) +  T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3 + T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 + T_AC6 + T_ALEN + T_AV6;
    
    
        tmp =  (MU * T_PAY_SZ) + strlen(IC) + strlen(RC) + strlen(NP) + strlen(MV) + strlen(ET) + strlen(IF) + strlen(MI) + 4;
    
        tmp = tmp + SA_HEADER_SZ + PROP_HEADER_SZ;               # sizeof SA_HEADER + PROP_HEADER
        myplen = tmp - 28;
        myp_plen = myplen - 12;
    
        len4 = tmp / 0xFFFFFF;
        len3 = tmp / 0xFFFF;
        len2 = tmp / 0xFF;
        len1 = tmp % 256;
        LEN=raw_string(len4,len3,len2,len1);
    
        len2 = myplen / 0xFF;
        len1 = myplen % 256;
        PLEN=raw_string(len2, len1);
    
        len2 = myp_plen / 0xFF;
        len1 = myp_plen % 256;
        P_PLEN=raw_string(len2, len1);
    
        SA_HEADER = SA_NP + RES + PLEN + DOI + SIT;
    
        PROP_HEADER = P_NP + P_RES + P_PLEN + P_NUM + PID + SPI_SZ + T_NUM_TOT;
    
        ISAKMP_HEADER = IC + RC + NP + MV + ET + IF + MI + LEN;
    
        blap = ISAKMP_HEADER + SA_HEADER + PROP_HEADER + T_PAY1;
        for (MU=2; MU <= TRANSFORM_MAX; MU++) {
            blap = blap + TPAY[MU];
        }
    
        return(blap);
    }
    
    
    
    
    
    srcaddr = this_host();
    dstaddr = get_host_ip();
    port = 500;
    srcport = rand() % 65535;
    
    if(!get_udp_port_state(port))exit(0);
    
    
    
    #------ISAKMP header-----#
    
    IC = raw_string (0xFF, 0x00, 0xFE, 0x01, 0xFD, 0x02, 0xFC, 0x03);    #8 byte Initiator cookie
    RC = raw_string (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);    #8 byte Responder cookie
    
    NP = raw_string (0x01);                                              #Next payload = 1 = Security Association
                                                                         # 2 = proposal / 3 = transform /  4 = Key exchange
                                                                         # 5 = ID /  6 = CERT / 7 = Cert request
                                                                         # 8 = HASH / 9 = SIGNATURE / 10 = NONCE
                                                                         # 11 = Notification / 12 = Delete
                                                                         # 13 = Vendor ID / 14-27 = RESERVED
                                                                         # 128-255 = PRIVATE USE
    
    
    MV = raw_string (0x10);                                              # 4bits = Major version
                                                                         # 4 low order bits = Minor version
    
    
    ET = raw_string (0x02);                                              # Exchange type = 4 = AGGRESSIVE
                                                                         # 0 = NONE / 1 = BASE / 2 = Identity protection
                                                                         # 3 = Authentication only  / 5 = Informational
                                                                         # 6-31 = FUTURE USE / 32-239 = DOI use
                                                                         # 240-255 = Private use
    
    IF = raw_string (0x00);
    MI = raw_string(0x00,0x00,0x00,0x00);                                # Message ID
    #LEN = raw_string (0x00,0x00,0x01,0x7b);                              # Length = total length of UDP data field
    
    
    #ISAKMP_HEADER = IC + RC + NP + MV + ET + IF + MI + LEN;
    ISAKMP_HEADER_SZ = 28;
    
    
    
    
    
    # ----- Security Association ---------#
    
    SA_NP = raw_string(0x00);                                            # Security Association next payload = key exchange
    RES = raw_string(0x00);                                              # reserved
    PLEN = raw_string(0x00,0x80);                                        # Security association payload length = LEN - 28
                                                                         # total len of all payloads (through last TP) + 12
    DOI = raw_string(0x00,0x00,0x00,0x01);                               # DOI = generic ISAKMP Security Association
    SIT = raw_string(0x00,0x00,0x00,0x01);                               # Situation
    
    SA_HEADER = SA_NP + RES + PLEN + DOI + SIT;
    SA_HEADER_SZ = 12;
    
    
    
    
    
    
    # ------Proposal --------------------#
    
    P_NP = raw_string(0x00);                                             # Proposal next payload = 0 (last proposal payload)
    P_RES = raw_string(0x00);                                            # reserved
    P_PLEN = raw_string(0x00,0x74);                                      # Proposal payload length = LEN - 40
                                                                         # payloads through last TP
    P_NUM = raw_string(0x01);                                            # proposal number
    PID = raw_string(0x01);                                              # protocol ID = 1 = proto_isakmp
    SPI_SZ = raw_string(0x00);                                           # SPI size
    T_NUM_TOT = raw_string(0x08);                                            # number of transforms
    
    PROP_HEADER = P_NP + P_RES + P_PLEN + P_NUM + PID + SPI_SZ + T_NUM_TOT;
    PROP_HEADER_SZ = 8;
    
    
    
    
    
    
    # -----Transform Payload ------------#
    T_NP = raw_string(0x03);                                             # transform next payload = 3 = more transforms
    T_RES = raw_string(0x00);                                            # reserved
    T_PLEN = raw_string(0x00,0x24);                                      # payload length --  36 bytes per transform
    T_NUM = raw_string(0x01);                                            # transform number
    T_ID = raw_string(0x01);                                             # transform ID
    T_RES2 = raw_string(0x00,0x00);                                      # reserved
    T_FLAGS = raw_string(0x80);                                          # data attribute following TV format
    T_AC = raw_string(0x01);                                             # Attribute type/class = 1 encryption alg basic
    T_AV = raw_string(0x00,0x05);                                        # Transform attribute value = 3des_CBC
    T_FLAGS2 = raw_string(0x80);
    T_AC2 = raw_string(0x02);                                            # attribute type/class = 2 = hash alg basic
    T_AV2 = raw_string(0x00,0x02);                                       # attribute value = 2 = SHA
    T_FLAGS3 = raw_string(0x80);
    T_AC3 = raw_string(0x03);                                            # attribute type/class = 4 = group description basic
    T_AV3 = raw_string(0x00,0x01);                                       # attribute value = 2 = alternate 1024 bit MODP group
    T_FLAGS4 = raw_string(0x80);
    T_AC4 = raw_string(0x04);                                            # attribute type/class = 3 = basic authentication
    T_AV4 = raw_string(0x00,0x02);                                       # attribute value = 65001 = for private use
    T_FLAGS5 = raw_string(0x80);
    T_AC5 = raw_string(0x0b);                                            # attribute type/class = 11 = basic life type
    T_AV5 = raw_string(0x00,0x01);                                       # attribute value = 1 = life duration in seconds
    T_FLAGS6 = raw_string(0x00);
    T_AC6 = raw_string(0x0c);                                            # attribute type/class = 12 = variable life duration
    T_ALEN = raw_string(0x00,0x04);                                      # attribute length = 4 bytes
    T_AV6 = raw_string(0x00,0x20,0xC4,0x9B);                             # attribute value
    
    T_PAY_SZ = 36;
    
    T_PAY1 = T_NP + T_RES + T_PLEN + T_NUM + T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3 +
    T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 + T_AC6 + T_ALEN + T_AV6;
    
    
    
    
    
    
    
    # -----Transform Payloads 2 and up -----------#
    # nothing changes except transform number .... and "Next payload" (on last payload)
    
    TRANSFORM_MAX = 8;
    
    for (TPAYRRAY=2; TPAYRRAY < TRANSFORM_MAX; TPAYRRAY++) {
    
        TPAY[TPAYRRAY] = T_NP + T_RES + T_PLEN + raw_string(TPAYRRAY) + T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3 + T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 + T_AC6 + T_ALEN + T_AV6;
    }
    
    TPAY[TPAYRRAY] = raw_string(0x00) + T_RES + T_PLEN + raw_string(TPAYRRAY) +  T_ID + T_RES2 + T_FLAGS + T_AC + T_AV + T_FLAGS2 + T_AC2 + T_AV2 + T_FLAGS3 + T_AC3 + T_AV3 + T_FLAGS4 + T_AC4 + T_AV4 + T_FLAGS5 + T_AC5 + T_AV5 + T_FLAGS6 + T_AC6 + T_ALEN + T_AV6;
    
    
    
    
    
    #--------end Proposal Payload ------------------------#
    
    #--------end Security Association Payload-------------#
    
    
    
    
    
    # added this blurb in order to handle racoon which doesn't like
    # Exchange type set to BASIC
    # --------------------------------------------
    
    blat = calc_data();
    soc = open_sock_udp(port);
    if (!soc) exit(0);
    send (socket:soc, data:blat);
    r = recv(socket:soc, length:48, timeout:2);
    rlen = strlen(r);
    
    if (rlen > 16) {
           if (  (ord(r[16]) == 0x01) && (ord(r[18]) == 0x02)  ) {security_warning(port); exit(0); }
           if (  (ord(r[16]) == 0x0B) && (ord(r[18]) == 0x05)  ) {security_warning(port); exit(0); }
           # still here?
           mywarning = string("The remote host answers on port 500 UDP\n");
           mywarning += string("If you know what the host is running, please send the\n");
           # maybe need an address like ike-fingerprint@private????
           mywarning += string("version as well as the following text to jwlampe@private : \n\n");
           for (i=0; i<rlen; i++) {
               mywarning = mywarning + (string(ord(r[i]), " "));
           }
           security_warning(port:port, data:mywarning);
           exit(0);
    }
    
    # end racoon check ---------------------------
    
    
    
    # now handle non-racoon IPSEC ;-)
    ET = raw_string(0x01);                 # change exchange type to BASIC
    MV = raw_string(0xFF);                 # set Major version = minor version = 15 (obviously bogus)
                                           # this *should* generate an error reply
    
    
    blat = calc_data();
    
    
    soc = open_sock_udp(port);
    if (!soc) exit(0);
    send (socket:soc, data:blat);
    r = recv(socket:soc, length:48, timeout:2);
    rlen = strlen(r);
    if (rlen > 16) {
        if (  (ord(r[16]) == 0x0B) && (ord(r[18]) == 0x05)  ) security_warning(port, protocol:"udp");
    } else {
        #nudge packet didn't work...We'll have to do a little more...
        # why this check, you might ask????
        # well, some implementations of IPSEC (Microsoft,...) will receive a packet from src port != 500 and dst port=500
        # and reply from src port == 501 dst port == 500
    
    
        blat = calc_data();
        oneoff = strlen(blat);
        filter = string("udp and src host ", get_host_ip(), " and dst host ", this_host(), " and dst port ", port);
        ip = forge_ip_packet(                ip_v : 4,
                                             ip_hl : 5,
                                             ip_tos : 0,
                                             ip_len : 20,
                                             ip_id : 0xABBA,
                                             ip_p : IPPROTO_UDP,
                                             ip_ttl : 255,
                                             ip_off : 0,
                                             ip_src : this_host(),
                                             ip_dst : get_host_ip());
    
    
        udpip = forge_udp_packet(                    ip : ip,
                                                     uh_sport : srcport,
                                                     uh_dport : 500,
                                                     uh_ulen : oneoff + 8,
                                                     data : blat);
    
        live = send_packet(udpip, pcap_active:TRUE, pcap_filter:filter);
        myrep = string("The remote host seems to be enabled to do Internet Key
    Exchange.  This is typically indicative of a VPN server.
    VPN servers are used to connect remote hosts into internal
    resources.  In addition, The remote host seems to be configured
    to force all communications across port 500 for both the source and
    destination port.  That is, we sent the machine a packet from a random
    port greater than 1024.  The machine sent the reply back to port 500.
    
    NOTE: This sort of behavior has been observed on Microsoft machines.
    
    Solution: You should ensure that:
    1) The VPN is authorized for your Companies computing environment
    2) The VPN utilizes strong encryption
    3) The VPN utilizes strong authentication
    
    Risk factor : Low");
        if (live) {
            if (  (ord(live[44]) == 0x0B) && (ord(live[46]) == 0x05)  ) security_warning(port:port, data:myrep, proto:"udp");
        }
    }
    
    exit(0);
    
    
    
    _______________________________________________
    Plugins-writers mailing list
    Plugins-writers@private
    http://mail.nessus.org/mailman/listinfo/plugins-writers
    



    This archive was generated by hypermail 2b30 : Thu May 06 2004 - 08:35:42 PDT