📄 snort_smtp.c
字号:
break; case STATE_UNKNOWN: DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "UNKNOWN STATE ~~~~~~~~~~~~~~~~~~~~~~~~~~\n");); /* If state is unknown try command state to see if we can * regain our bearings */ ptr = SMTP_HandleCommand(p, ptr, end); break; default: DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Bad SMTP state\n");); return; } }#ifdef DEBUG if (_smtp_normalizing) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Normalized payload\n%s\n", SMTP_PrintBuffer(p));); }#endif return;}/* very simplistic - just enough to say this is binary data - the rules will make a final * judgement. Should maybe add an option to the smtp configuration to enable the * continuing of command inspection like ftptelnet. */static int SMTP_IsTlsClientHello(const u_int8_t *ptr, const u_int8_t *end){ /* at least 3 bytes of data - see below */ if ((end - ptr) < 3) return 0; if ((ptr[0] == 0x16) && (ptr[1] == 0x03)) { /* TLS v1 or SSLv3 */ return 1; } else if ((ptr[2] == 0x01) || (ptr[3] == 0x01)) { /* SSLv2 */ return 1; } return 0;}/* this may at least tell us whether the server accepted the client hello by the presence * of binary data */static int SMTP_IsTlsServerHello(const u_int8_t *ptr, const u_int8_t *end){ /* at least 3 bytes of data - see below */ if ((end - ptr) < 3) return 0; if ((ptr[0] == 0x16) && (ptr[1] == 0x03)) { /* TLS v1 or SSLv3 */ return 1; } else if (ptr[2] == 0x04) { /* SSLv2 */ return 1; } return 0;}/* * Process server packet * * @param packet standard Packet structure * * @return do_flush * @retval 1 flush queued packets on client side * @retval 0 do not flush queued packets on client side */static int SMTP_ProcessServerPacket(SFSnortPacket *p){ int resp_found; const u_int8_t *ptr; const u_int8_t *end; const u_int8_t *eolm; const u_int8_t *eol; int do_flush = 0; int resp_line_len;#ifdef DEBUG const u_int8_t *dash;#endif ptr = p->payload; end = p->payload + p->payload_size; if (_smtp->state == STATE_TLS_SERVER_PEND) { if (SMTP_IsTlsServerHello(ptr, end)) { _smtp->state = STATE_TLS_DATA; } else { /* revert back to command state - assume server didn't accept STARTTLS */ _smtp->state = STATE_COMMAND; } } if (_smtp->state == STATE_TLS_DATA) { /* Ignore data */ if (_smtp_config.ignore_tls_data) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Ignoring Server TLS encrypted data\n");); p->normalized_payload_size = 0; p->flags |= FLAG_ALT_DECODE; } return 0; } while (ptr < end) { SMTP_GetEOL(ptr, end, &eol, &eolm); resp_line_len = eol - ptr; /* Check for response code */ _smtp_current_search = &_smtp_resp_search[0]; resp_found = _dpd.searchAPI->search_find(SEARCH_RESP, (const char *)ptr, resp_line_len, 1, SMTP_SearchStrFound); if (resp_found > 0) { switch (_smtp_search_info.id) { case RESP_220: /* This is either an initial server response or a STARTTLS response * flush the client side. if we've already seen STARTTLS, no need * to flush */ if (_smtp->state == STATE_CONNECT) _smtp->state = STATE_COMMAND; else if (_smtp->state != STATE_TLS_CLIENT_PEND) do_flush = 1; break; case RESP_354: do_flush = 1; break; default: break; }#ifdef DEBUG dash = ptr + _smtp_search_info.index + _smtp_search_info.length; /* only add response if not a dash after response code */ if ((dash == eolm) || ((dash < eolm) && (*dash != '-'))) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Server sent %s response\n", _smtp_resps[_smtp_search_info.id].name);); }#endif } else { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Server response not found - see if it's SSL data\n");); if ((_smtp->session_flags & SMTP_FLAG_CHECK_SSL) && (SMTP_IsSSL(ptr, end - ptr, p->flags))) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Server response is an SSL packet\n");); _smtp->state = STATE_TLS_DATA; /* Ignore data */ if (_smtp_config.ignore_tls_data) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Ignoring Server TLS encrypted data\n");); p->normalized_payload_size = 0; p->flags |= FLAG_ALT_DECODE; } return 0; } else if (_smtp->session_flags & SMTP_FLAG_CHECK_SSL) { _smtp->session_flags &= ~SMTP_FLAG_CHECK_SSL; } } if ((_smtp_config.max_response_line_len != 0) && (resp_line_len > _smtp_config.max_response_line_len)) { SMTP_GenerateAlert(SMTP_RESPONSE_OVERFLOW, "%s: %d chars", SMTP_RESPONSE_OVERFLOW_STR, resp_line_len); } ptr = eol; } return do_flush;}static int SMTP_IsSSL(const u_int8_t *ptr, int len, int pkt_flags){ u_int32_t ssl_flags = SSL_decode(ptr, len, pkt_flags); if ((ssl_flags != SSL_ARG_ERROR_FLAG) && !(ssl_flags & SMTP_SSL_ERROR_FLAGS)) { return 1; } return 0;}/* * Entry point to snort preprocessor for each packet * * @param packet standard Packet structure * * @return none */void SnortSMTP(SFSnortPacket *p){ int detected = 0; PROFILE_VARS; /* Ignore if no data */ if (p->payload_size == 0) {#ifdef DEBUG int pkt_dir; int flags = 0; if (p->stream_session_ptr != NULL) flags = _dpd.streamAPI->get_session_flags(p->stream_session_ptr); pkt_dir = SMTP_GetPacketDirection(p, flags); DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "SMTP %s packet\n", pkt_dir == SMTP_PKT_FROM_SERVER ? "server" : (pkt_dir == SMTP_PKT_FROM_CLIENT ? "client" : "unknown"));); DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "No payload to inspect\n"););#endif return; } SMTP_Setup(p); if (_smtp_pkt_direction == SMTP_PKT_FROM_SERVER) { int do_flush = 0; DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "SMTP server packet\n");); /* Process as a server packet */ do_flush = SMTP_ProcessServerPacket(p); if (do_flush) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Flushing stream\n");); _dpd.streamAPI->response_flush_stream(p); } } else {#ifdef DEBUG if (_smtp_pkt_direction == SMTP_PKT_FROM_CLIENT) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "SMTP client packet\n");); } else { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "SMTP packet NOT from client or server! " "Processing as a client packet\n");); }#endif /* This packet should be a tls client hello */ if (_smtp->state == STATE_TLS_CLIENT_PEND) { if (SMTP_IsTlsClientHello(p->payload, p->payload + p->payload_size)) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "TLS DATA STATE ~~~~~~~~~~~~~~~~~~~~~~~~~\n");); _smtp->state = STATE_TLS_SERVER_PEND; } else { /* reset state - server may have rejected STARTTLS command */ _smtp->state = STATE_COMMAND; } } if ((_smtp->state == STATE_TLS_DATA) || (_smtp->state == STATE_TLS_SERVER_PEND)) { /* if we're ignoring tls data, set a zero length alt buffer */ if (_smtp_config.ignore_tls_data) { p->normalized_payload_size = 0; p->flags |= FLAG_ALT_DECODE; } } else { if (p->flags & FLAG_STREAM_INSERT) { /* Packet will be rebuilt, so wait for it */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Client packet will be reassembled\n")); /* Turn off detection until we get the rebuilt packet. */ SMTP_DisableDetect(p); return; } else if (_smtp_reassembling && !(p->flags & FLAG_REBUILT_STREAM)) { /* If this isn't a reassembled packet and didn't get * inserted into reassembly buffer, there could be a * problem. If we miss syn or syn-ack that had window * scaling this packet might not have gotten inserted * into reassembly buffer because it fell outside of * window, because we aren't scaling it */ _smtp->session_flags |= SMTP_FLAG_GOT_NON_REBUILT; _smtp->state = STATE_UNKNOWN; } else if (_smtp_reassembling && (_smtp->session_flags & SMTP_FLAG_GOT_NON_REBUILT)) { /* This is a rebuilt packet. If we got previous packets * that were not rebuilt, state is going to be messed up * so set state to unknown. It's likely this was the * beginning of the conversation so reset state */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Got non-rebuilt packets before " "this rebuilt packet\n")); _smtp->state = STATE_UNKNOWN; _smtp->session_flags &= ~SMTP_FLAG_GOT_NON_REBUILT; }#ifdef DEBUG /* Interesting to see how often packets are rebuilt */ DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "Payload: %s\n%s\n", (p->flags & FLAG_REBUILT_STREAM) ? "reassembled" : "not reassembled", SMTP_PrintBuffer(p)););#endif SMTP_ProcessClientPacket(p); } } PREPROC_PROFILE_START(smtpDetectPerfStats); detected = _dpd.detect(p);#ifdef PERF_PROFILING smtpDetectCalled = 1;#endif PREPROC_PROFILE_END(smtpDetectPerfStats); /* Turn off detection since we've already done it. */ SMTP_DisableDetect(p); if (detected) { DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "SMTP vulnerability detected\n");); }}static void SMTP_DisableDetect(SFSnortPacket *p){ _dpd.disableAllDetect(p); _dpd.setPreprocBit(p, PP_SFPORTSCAN); _dpd.setPreprocBit(p, PP_PERFMONITOR); _dpd.setPreprocBit(p, PP_STREAM4); _dpd.setPreprocBit(p, PP_STREAM5);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -