Пример #1
0
/**
 * nntpplugin_LTX_ycIrcScanScan
 *
 * scans a given payload to see if it conforms to our idea of what NNTP traffic
 * looks like.
 *
 *
 *
 * @param argc NOT USED
 * @param argv NOT USED
 * @param payload pointer to the payload data
 * @param payloadSize the size of the payload parameter
 * @param flow a pointer to the flow state structure
 * @param val a pointer to biflow state (used for forward vs reverse)
 *
 * @return 0 for no match NNTP_PORT_NUMBER (119) for a match
 *
 */
uint16_t
nntpplugin_LTX_ycNNTPScanScan (
    int argc,
    char *argv[],
    uint8_t * payload,
    unsigned int payloadSize,
    yfFlow_t * flow,
    yfFlowVal_t * val)
{

    int rc;
#   define NUM_CAPT_VECTS 60
    int vects[NUM_CAPT_VECTS];


    if (0 == pcreInitialized) {
        if (0 == ycNNTPScanInit()) {
            return 0;
        }
    }

    rc = pcre_exec(nntpCommandRegex, NULL, (char *)payload, payloadSize,
           0, 0, vects, NUM_CAPT_VECTS);

    if (rc <= 0) {
        rc = pcre_exec(nntpResponseRegex, NULL, (char *)payload,
               payloadSize, 0, 0, vects, NUM_CAPT_VECTS);
    }


    /** at some point in the future, this is the place to extract protocol
        information like message targets and join targets, etc.*/
#if YAF_ENABLE_HOOKS
    if (rc > 0) {
        yfHookScanPayload(flow, payload, payloadSize, nntpCommandRegex, 0,
                          173, NNTP_PORT);
        yfHookScanPayload(flow, payload, payloadSize, nntpResponseRegex, 0,
                          172, NNTP_PORT);
    }
#endif

    if (rc > 0) {
        return NNTP_PORT;
    }


    return 0;
}
Пример #2
0
gboolean decodeTLSv1(
    uint8_t *payload,
    unsigned int payloadSize,
    yfFlow_t *flow,
    uint16_t offsetptr,
    uint16_t firstpkt,
    uint8_t datalength,
    uint8_t type)
{

    uint32_t record_len;
    uint16_t header_len = offsetptr - 1;
    uint32_t cert_len, sub_cert_len;
    int cert_count = 0;
    uint16_t cipher_suite_len;
    uint8_t session_len;
    uint8_t compression_len;
    uint8_t next_msg;
    uint16_t ext_len = 0;
    uint16_t ext_ptr;
    uint16_t sub_ext_len;
    uint16_t sub_ext_type;

    /* Both Client and Server Hello's start off the same way */
    /* 3 for Length, 2 for Version, 32 for Random, 1 for session ID Len*/
    if (offsetptr + 39 > payloadSize) {
        return FALSE;
    }

    record_len = (ntohl(*(uint32_t *)(payload + offsetptr)) & 0xFFFFFF00) >> 8;

    offsetptr += 37; /* skip version  & random*/

    session_len = *(payload + offsetptr);

    offsetptr += session_len + 1;

    if (offsetptr + 2 > payloadSize){
        return FALSE;
    }

    if (type == 1) {
        /* Client Hello */

        cipher_suite_len = ntohs(*(uint16_t *)(payload + offsetptr));

        /* figure out number of ciphers by dividing by 2 */

        offsetptr += 2;

        if (cipher_suite_len > payloadSize) {
            return FALSE;
        }

        if (offsetptr + cipher_suite_len > payloadSize) {
            return FALSE;
        }
        /* cipher length */
        /* ciphers are here */
        offsetptr += cipher_suite_len;

        if (offsetptr + 1 > payloadSize) {
            return FALSE;
        }

        compression_len = *(payload + offsetptr);

        offsetptr += compression_len + 1;

#if YAF_ENABLE_HOOKS
        yfHookScanPayload(flow, payload, cipher_suite_len, NULL,
                          offsetptr+firstpkt, 91, TLS_PORT_NUMBER);
#endif

    } else if (type == 2) {
        /* Server Hello */
        if (offsetptr + 3 > payloadSize) {
            return FALSE;
        }
        /* cipher is here */
#if YAF_ENABLE_HOOKS
        yfHookScanPayload(flow, payload, 2, NULL, offsetptr+firstpkt, 89,
                          TLS_PORT_NUMBER);
#endif
        offsetptr += 2;
        /* compression method */
#if YAF_ENABLE_HOOKS
        yfHookScanPayload(flow, payload, 1, NULL, offsetptr+firstpkt, 90,
                          TLS_PORT_NUMBER);
#endif
        offsetptr++;

    }

    if ((offsetptr - header_len) < record_len) {
        int tot_ext = 0;
        /* extensions? */
        ext_len = ntohs(*(uint16_t *)(payload + offsetptr));
        ext_ptr = offsetptr + 2;
        offsetptr += ext_len + 2;
#if YAF_ENABLE_HOOKS
        /* only want Client Hello's server name */
        if (type == 1 && (offsetptr < payloadSize)) {
            while (ext_ptr < payloadSize && (tot_ext < ext_len)) {
                sub_ext_type = ntohs(*(uint16_t *)(payload + ext_ptr));
                ext_ptr += 2;
                sub_ext_len = ntohs(*(uint16_t *)(payload + ext_ptr));
                ext_ptr += 2;
                tot_ext += sizeof(uint16_t) + sizeof(uint16_t) + sub_ext_len;
                if (sub_ext_type != 0) {
                    ext_ptr += sub_ext_len;
                    continue;
                }
                if (sub_ext_len == 0) {
                    /* no server name listed */
                    break;
                }
                /* grab server name */
                /* jump past list length and type to get name length and name */
                ext_ptr += 3; /* 2 for length, 1 for type */
                sub_ext_len = ntohs(*(uint16_t *)(payload + ext_ptr));
                ext_ptr += 2;
                if ((ext_ptr + sub_ext_len) < payloadSize) {
                    yfHookScanPayload(flow, payload, sub_ext_len, NULL,
                                      ext_ptr+firstpkt, 95, TLS_PORT_NUMBER);
                }
                break;
            }
        }
#endif



    }

    while (payloadSize > offsetptr) {

        next_msg = *(payload + offsetptr);
        if (next_msg == 11) {
            /* certificate */
            if (offsetptr + 7 > payloadSize) {
                return TRUE; /* prob should be false */
            }

            offsetptr++;

            record_len = (ntohl(*(uint32_t *)(payload + offsetptr)) &
                          0xFFFFFF00) >> 8;
            offsetptr += 3;

            /* Total Cert Length */
            cert_len = (ntohl(*(uint32_t *)(payload + offsetptr)) &
                        0xFFFFFF00) >> 8;
            offsetptr += 3;

            while (payloadSize > (offsetptr + 4)) {
                sub_cert_len = (ntohl(*(uint32_t *)(payload + offsetptr)) &
                                0xFFFFFF00) >> 8;
                if ((sub_cert_len > cert_len) || (sub_cert_len < 2))  {
                    /* it's at least got to have a version number */
                    return TRUE; /* prob should be false */

                } else if (sub_cert_len > payloadSize) {
                    /* just not enough room */
                    return TRUE;
                }

                /* offset of certificate */
                if (cert_count < MAX_CERTS) {
#if YAF_ENABLE_HOOKS
                    if ((offsetptr + sub_cert_len + 3) < payloadSize) {
                        yfHookScanPayload(flow, payload, 1, NULL,
                                          offsetptr+firstpkt, 93,
                                          TLS_PORT_NUMBER);
                    }
#endif
                } else {
                    return TRUE;
                }

                cert_count++;
                offsetptr += 3 + sub_cert_len;
            }

        } else if (next_msg == 22) {
            /* 1 for type, 2 for version, 2 for length - we know it's long */
            offsetptr += 5;

        } else if (next_msg == 20 || next_msg == 21 || next_msg == 23) {

            offsetptr += 3; /* 1 for type, 2 for version */

            if ((offsetptr + 2) > payloadSize) {
                return TRUE; /* prob should be false */
            }

            record_len = ntohs(*(uint16_t *)(payload + offsetptr));

            if (record_len > payloadSize) {
                return TRUE;
            }

            offsetptr += record_len + 2;

        } else {

            return TRUE;

        }

    }
Пример #3
0
/**
 * proxyplugin_LTX_ycProxyScanScan
 *
 * the scanner for recognizing SSL/TLS packets through a proxy.
 *
 * @param argc number of string arguments in argv
 * @param argv string arguments for this plugin (first two are library
 *             name and function name)
 * @param payload the packet payload
 * @param payloadSize size of the packet payload
 * @param flow a pointer to the flow state structure
 * @param val a pointer to biflow state (used for forward vs reverse)
 *
 *
 * @return TLS_PORT_NUMBER
 *         otherwise 0
 */
uint16_t
proxyplugin_LTX_ycProxyScanScan (
    int argc,
    char *argv[],
    uint8_t * payload,
    unsigned int payloadSize,
    yfFlow_t * flow,
    yfFlowVal_t * val)
{
#define NUM_CAPT_VECTS 60
    int        vects[NUM_CAPT_VECTS];
    uint8_t    ssl_length;
    uint8_t    ssl_msgtype;
    uint16_t   tls_version;
    uint16_t   offsetptr = 0;
    uint16_t   firstpkt = 0;
    unsigned int payloadLength = payloadSize;
    int        rc, loop = 0;

    if (0 == pcreInitialized) {
        if (0 == yfProxyScanInit()) {
            return 0;
        }
    }

    /* if the applabel is 0, this is the fwd direction which should have
     * the HTTP CONNECT *
     * If not, we've probably already classified it as TLS and we're just
     * doing DPI */
    if (flow->appLabel == 0) {
        rc = pcre_exec(httpConnectRegex, NULL, (char *)payload, payloadSize,
                       0, 0, vects, NUM_CAPT_VECTS);
        if (rc <= 0) {
            rc = pcre_exec(httpConnectEstRegex, NULL, (char *)payload,
                           payloadSize, 0, 0, vects, NUM_CAPT_VECTS);
            if (rc <= 0) {
                return 0;
            }
        }
    } else if (flow->appLabel != TLS_PORT_NUMBER) {
        return 0;
    }


    /* every SSL/TLS header has to be at least 2 bytes long... */
    if ( payloadSize < 45 ) {
        return 0;
    }

    while (loop < val->pkt && loop < YAF_MAX_PKT_BOUNDARY) {
        if (val->paybounds[loop] == 0) {
            loop++;
        } else {
            firstpkt = val->paybounds[loop];
            break;
        }
    }

    /* http/1.0 connection established messaged is 39 bytes! */

    payload += firstpkt;
    payloadLength -= firstpkt;

    /*understanding how to determine between SSLv2 and SSLv3/TLS is "borrowed"
     *from OpenSSL payload byte 0 for v2 is the start of the length field, but
     *its MSb is always reserved to tell us how long the length field is, and
     *in some cases, the second MSb is reserved as well */

    /* when length is 2 bytes in size (MSb == 1), and the message type code is
     * 0x01 (client_hello) we know we're doing SSL v2 */
    if ((payload[0] & 0x80) && (0x01 == payload[2])) {

        ssl_length = ((payload[0] & 0x7F) << 8) | payload[1];

        if ( ssl_length < 2 ) {
            return 0;
        }

        ssl_msgtype = 1;
        offsetptr += 3;

        /* this is the version from the handshake message */
        tls_version = ntohs(*(uint16_t *)(payload + offsetptr));
        offsetptr += 2;
        if (tls_version == TLS_VERSION_1 || tls_version == SSL_VERSION_2 ||
            tls_version == SSL_VERSION_3)
        {
            if ( !decodeSSLv2(payload, payloadLength, flow, offsetptr,
                              firstpkt, ssl_length))
            {
                return 0;
            }
        } else {
            return 0;
        }

        /* SSLv2 (client_hello) */
#if YAF_ENABLE_HOOKS
        yfHookScanPayload(flow, payload, 1, NULL, 41, 88, TLS_PORT_NUMBER);
        yfHookScanPayload(flow, payload, 2, NULL, tls_version, 94,
                          TLS_PORT_NUMBER);
#endif
        return TLS_PORT_NUMBER;

    } else {

        if ((0x00 == (payload[0] & 0x80)) && (0x00 == (payload[0] & 0x40))
            && (0x01 == payload[3]))
        {
            /* this is ssl v2 but with a 3-byte header */
            /* the second MSb means the record is a data record */
            /* the fourth byte should be 1 for client hello */
            if ((payload[0] == 0x16) && (payload[1] == 0x03))
            {
                /* this is most likely tls, not sslv2 */
                goto tls;
            }

            ssl_length = ((payload[0] * 0x3F) << 8) | payload[1];

            if ( ssl_length < 3 ) {
                return 0;
            }
            offsetptr += 4;

            if ( (offsetptr + 2) < payloadLength ) {

                tls_version = ntohs(*(uint16_t *)(payload + offsetptr));
                offsetptr += 2;

                if (tls_version == TLS_VERSION_1 ||
                    tls_version == SSL_VERSION_2 ||
                    tls_version == SSL_VERSION_3)
                {
                    if (!decodeSSLv2(payload, payloadLength, flow, offsetptr,
                                     firstpkt, ssl_length))
                    {
                        return 0;
                    }
                } else {
                    return 0;
                }
            } else {
                return 0;
            }
#if YAF_ENABLE_HOOKS
            yfHookScanPayload(flow, payload, 1, NULL, 41, 88, TLS_PORT_NUMBER);
            yfHookScanPayload(flow, payload, 2, NULL, tls_version, 94,
                              TLS_PORT_NUMBER);
#endif
            return TLS_PORT_NUMBER;
        }
      tls:
        if ( payloadLength >= 10 ) {
            /* payload[0] is handshake request [0x16]
               payload[1] is ssl major version, sslv3 & tls is 3
               payload[5] is handshake command, 1=client_hello,2=server_hello
               payload[3,4] is length
               payload[9] is the version from the record */

            if ((payload[0] == 0x16) && (payload[1] == 0x03) &&
                ((payload[5] == 0x01) || (payload[5] == 0x02)) &&
                (((payload[3] == 0) && (payload[4] < 5)) ||
                 (payload[9] == payload[1])))
            {
                ssl_msgtype = payload[5];
                ssl_length = payload[4];
                tls_version = ntohs(*(uint16_t *)(payload + 1));
                /* 1 for content type, 2 for version, 2 for length,
                 * 1 for handshake type*/
                offsetptr += 6;
                /* now we should be at record length */
                if (!decodeTLSv1(payload, payloadLength, flow, offsetptr,
                                 firstpkt, ssl_length, ssl_msgtype))
                {
                    return 0;
                }

                /* SSLv3 / TLS */
#if YAF_ENABLE_HOOKS
                yfHookScanPayload(flow, payload, 1, NULL, 42, 88,
                                  TLS_PORT_NUMBER);
                yfHookScanPayload(flow, payload, 2, NULL, tls_version, 94,
                                  TLS_PORT_NUMBER);
#endif
                return TLS_PORT_NUMBER;
            }
        }
    }

    return 0;
}