📄 pp_ftp.c
字号:
if (numPercents >= MAX_PERCENT_SIGNS) { /* Alert on string format attack in parameter */ ftp_eo_event_log(Session, FTP_EO_PARAMETER_STR_FORMAT, NULL, NULL); return FTPP_ALERTED; } } break; case e_int: /* check that this_param is all digits up to next space */ { do { if (!isdigit((int)(*this_param))) { /* Alert on non-digit */ return FTPP_INVALID_PARAM; } this_param++; } while ((this_param < end) && (*this_param != ' ') ); } break; case e_number: /* check that this_param is all digits up to next space * and value is between 1 & 255 */ { int iValue = 0; do { if (!isdigit((int)(*this_param))) { /* Alert on non-digit */ return FTPP_INVALID_PARAM; } iValue = iValue * 10 + (*this_param - '0'); this_param++; } while ((this_param < end) && (*this_param != ' ') ); if ((iValue > 255) || (iValue == 0)) return FTPP_INVALID_PARAM; } break; case e_char: /* check that this_param is one of chars specified */ { int bitNum = (*this_param & 0x1f); if (!isalpha((int)(*this_param))) { /* Alert on non-char */ return FTPP_INVALID_PARAM; } else { if (!(ThisFmt->format.chars_allowed & (1 << (bitNum-1))) ) { /* Alert on unexpected char */ return FTPP_INVALID_PARAM; } } this_param++; /* should be a space */ } break; case e_date: /* check that this_param conforms to date specified */ { const char *tmp_ch = this_param; iRet = validate_date_format(ThisFmt->format.date_fmt, &tmp_ch); if (iRet != FTPP_SUCCESS) { /* Alert invalid date */ return FTPP_INVALID_PARAM; } if (!isspace((int)(*tmp_ch))) { /* Alert invalid date -- didn't make it to end of parameter. Overflow attempt? */ return FTPP_INVALID_PARAM; } this_param = tmp_ch; } break; case e_host_port: /* check that this_param is #,#,#,#,#,# */ { snort_ip ip; u_int16_t port=0; int ret = getIP(&this_param, end, ' ', &ip, &port); switch (ret) { case FTPP_NON_DIGIT: /* Alert on non-digit */ return FTPP_INVALID_PARAM; break; case FTPP_INVALID_ARG: /* Alert on number > 255 */ return FTPP_INVALID_PARAM; break; case FTPP_MALFORMED_IP_PORT: /* Alert on malformed host-port */ return FTPP_INVALID_PARAM; break; } if ((Session->client_conf->bounce.on) && (Session->client_conf->bounce.alert)) {#ifdef SUP_IP6 if (!IP_EQUALITY(&ip, GET_SRC_IP(p)))#else if (ip != ntohl(p->ip4_header->source.s_addr))#endif { int alert = 1; char *ipPtr = (char *)&ip; FTP_BOUNCE_TO *BounceTo = ftp_bounce_lookup_find( Session->client_conf->bounce_lookup, ipPtr, 4, &iRet); if (BounceTo) { if (BounceTo->portlo) { if (BounceTo->porthi) { if ((port >= BounceTo->portlo) && (port <= BounceTo->porthi)) alert = 0; } else { if (port == BounceTo->portlo) alert = 0; } } } /* Alert on invalid IP address for PORT */ if (alert) { ftp_eo_event_log(Session, FTP_EO_BOUNCE, NULL, NULL); /* Return here -- because we will likely want to * inspect the data traffic over a bounced data * connection */ return FTPP_PORT_ATTACK; } } }#ifdef SUP_IP6 Session->clientIP = ip;#else Session->clientIP = htonl(ip);#endif Session->clientPort = port; Session->data_chan_state |= DATA_CHAN_PORT_CMD_ISSUED; if (Session->data_chan_state & DATA_CHAN_PASV_CMD_ISSUED) { /* * If there was a PORT command previously in * a series of pipelined requests, this * cancels it. */ Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED; } IP_CLEAR(Session->serverIP); Session->serverPort = 0; } break; } ThisFmt->next_param = this_param; return FTPP_SUCCESS;}/* * Function: check_ftp_param_validity( * Packet *p, * char *params_begin, * char *params_end, * FTP_PARAM_FMT *param_format, * FTP_SESSION *Session) * * Purpose: Recursively determines whether each of the parameters for * an FTP command are valid. * * Arguments: p => Pointer to the current packet * params_begin => Pointer to beginning of parameters * params_end => End of params buffer * param_format => Parameter format specifier for this command * Session => Pointer to the session info * * Returns: int => return code indicating error or success * */int check_ftp_param_validity(SFSnortPacket *p, const char *params_begin, const char *params_end, FTP_PARAM_FMT *param_format, FTP_SESSION *Session){ int iRet = FTPP_ALERT; FTP_PARAM_FMT *ThisFmt = param_format; FTP_PARAM_FMT *NextFmt; const char *this_param = params_begin; if (!param_format) return FTPP_INVALID_ARG; if (!params_begin) return FTPP_INVALID_ARG; if ((!ThisFmt->next_param_fmt) && (params_begin >= params_end)) return FTPP_SUCCESS; ThisFmt->next_param = params_begin; if (ThisFmt->optional_fmt) { /* Check against optional */ iRet = validate_param(p, this_param, params_end, ThisFmt->optional_fmt, Session); if (iRet == FTPP_SUCCESS) { const char *next_param; NextFmt = ThisFmt->optional_fmt; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; } } } if ((iRet != FTPP_SUCCESS) && (ThisFmt->choices)) { /* Check against choices -- one of many */ int i; int valid = 0; for (i=0;i<ThisFmt->numChoices && !valid;i++) { /* Try choice [i] */ iRet = validate_param(p, this_param, params_end, ThisFmt->choices[i], Session); if (iRet == FTPP_SUCCESS) { const char *next_param; NextFmt = ThisFmt->choices[i]; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; valid = 1; break; } } } } else if ((iRet != FTPP_SUCCESS) && (ThisFmt->next_param_fmt)) { /* Check against next param */ iRet = validate_param(p, this_param, params_end, ThisFmt->next_param_fmt, Session); if (iRet == FTPP_SUCCESS) { const char *next_param; NextFmt = ThisFmt->next_param_fmt; next_param = NextFmt->next_param+1; iRet = check_ftp_param_validity(p, next_param, params_end, NextFmt, Session); if (iRet == FTPP_SUCCESS) { this_param = NextFmt->next_param+1; } } } if (iRet == FTPP_SUCCESS) { ThisFmt->next_param = this_param; } return iRet;}/* * Function: initialize_ftp(FTP_SESSION *Session, Packet *p, int iMode) * * Purpose: Initializes the state machine for checking an FTP packet. * Does normalization checks. * * Arguments: Session => Pointer to session info * p => pointer to the current packet struct * iMode => Mode indicating server or client checks * * Returns: int => return code indicating error or success * */int initialize_ftp(FTP_SESSION *Session, SFSnortPacket *p, int iMode){ int iRet; const unsigned char *read_ptr = p->payload; FTP_CLIENT_REQ *req; /* Normalize this packet ala telnet */ iRet = normalize_telnet(Session->global_conf, NULL, p, iMode); if (iRet != FTPP_SUCCESS && iRet != FTPP_NORMALIZED) { if (iRet == FTPP_ALERT) { if (Session->global_conf->global_telnet.detect_anomalies) { ftp_eo_event_log(Session, FTP_EO_EVASIVE_TELNET_CMD, NULL, NULL); } } return iRet; } if (p->flags & FLAG_ALT_DECODE) { /* Normalized data will always be in decode buffer */ if ( ((Session->client_conf->telnet_cmds.alert) && (iMode == FTPP_SI_CLIENT_MODE)) || ((Session->server_conf->telnet_cmds.alert) && (iMode == FTPP_SI_SERVER_MODE)) ) { /* alert -- FTP channel with telnet commands */ ftp_eo_event_log(Session, FTP_EO_TELNET_CMD, NULL, NULL); return FTPP_ALERT; /* Nothing else to do since we alerted */ } read_ptr = _dpd.altBuffer; } if (iMode == FTPP_SI_CLIENT_MODE) req = &Session->client.request; else if (iMode == FTPP_SI_SERVER_MODE) req = (FTP_CLIENT_REQ *)&Session->server.response; else return FTPP_INVALID_ARG; /* Set the beginning of the pipeline to the start of the * (normalized) buffer */ req->pipeline_req = (const char *)read_ptr; return FTPP_SUCCESS;}/* * Function: do_stateful_checks(FTP_SESSION *Session, Packet *p, * FTP_CLIENT_REQ *req, int rsp_code) * * Purpose: Handle stateful checks and state updates for FTP response * packets. * * Arguments: Session => Pointer to session info * p => Pointer to the current packet struct * req => Pointer to current response from packet * (this function may be called multiple * times for pipelined requests). * rsp_code => Integer response value for server response * * Returns: int => return code indicating error or success * */int do_stateful_checks(FTP_SESSION *Session, SFSnortPacket *p, FTP_CLIENT_REQ *req, int rsp_code){ int iRet = FTPP_SUCCESS; if (Session->server_conf->data_chan) { if (rsp_code == 226) { /* Just ignore this code -- end of transfer... * If we saw all the other dat for this channel * Session->data_chan_state should be NO_STATE. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -