⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hi_norm.c

📁 入侵检测SNORT.最近更新的基于网络检测的IDS.希望能给大家带来方便.
💻 C
📖 第 1 页 / 共 4 页
字号:
/**************************************************************************** * * Copyright (C) 2003-2008 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation.  You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ /****  @file       hi_norm.c**  **  @author     Daniel Roelker <droelker@sourcefire.com**  **  @brief      Contains normalization skeleton for server and client**              normalization routines.**  **  This file contains the core routines to normalize the different fields**  within the HTTP protocol.  We currently only support client URI**  normalization, but the hooks are here to easily add other routines.**  **  NOTES:**      - Initial development.  DJR*/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include "hi_client_norm.h"#include "hi_eo.h"#include "hi_eo_events.h"#include "hi_eo_log.h"#include "hi_ui_iis_unicode_map.h"#include "hi_return_codes.h"#include "hi_si.h"#include "hi_util.h"#include "hi_util_xmalloc.h"#define MAX_DIRS        2048#define NO_HEX_VAL      -1#define BASE36_VAL      -2#define HEX_VAL          1/****  This define checks for negative return codes, since we have multiple**  reasons to error.  This just cuts the return code checks, especially**  as we add more errors.*/#define GET_ERR         0x80000000#define END_OF_BUFFER   -1#define DOUBLE_ENCODING -2#define DIR_TRAV        -2#define NON_ASCII_CHAR  0xfftypedef struct s_URI_NORM_STATE{    u_char *abs_uri;    u_char *param;    /*    **  Directory tracking    */    u_char *dir_track[MAX_DIRS];    u_int   dir_count;}  URI_NORM_STATE;typedef int (*DECODE_FUNC)(HI_SESSION *, const u_char *,                          const u_char *, const u_char **, URI_NORM_STATE *);static int hex_lookup[256];static int valid_lookup[256];/***  NAME**    GetPtr::*//****  This routine is for getting bytes in the U decode.**  **  This checks the current bounds and checking for the double decoding.**  This routine differs from the other Get routines because it returns**  other values than just END_OF_BUFFER and the char.**  **  We also return DOUBLE_ENCODING if there is a % and double decoding**  is turned on.**  **  When using this function it is important to note that it increments**  the buffer before checking the bounds.  So, if you call this function**  in a loop and don't check for END_OF_BUFFER being returned, then **  you are going to overwrite the buffer.  If I put the check in, you**  would just be in an never-ending loop.  So just use this correctly.**  **  @param ServerConf  the server configuration**  @param start       the start of the URI**  @param end         the end of the URI**  @param ptr         the current pointer into the URI**  **  @return integer**  **  @retval END_OF_BUFFER    the end of the buffer has been reached.**  @retval DOUBLE_ENCODING  a percent was found and double decoding is on**  @retval <= 0xff          an ASCII char         */static int GetPtr(HI_SESSION *Session, const u_char *start,                   const u_char *end, const u_char **ptr, URI_NORM_STATE *norm_state){    HTTPINSPECT_CONF *ServerConf = Session->server_conf;    (*ptr)++;    if(!hi_util_in_bounds(start, end, *ptr))        return END_OF_BUFFER;    if(ServerConf->double_decoding.on && **ptr == '%')        return DOUBLE_ENCODING;    return (int)**ptr;}/***  NAME**    UDecode::*//****  Handles the single decode for %U encoding.**  **  This routine receives the ptr pointing to the u.  We check the bounds**  and continue with processing.  %u encoding works by specifying the**  exact codepoint to be used.  For example, %u002f would be /.  So this**  all seems fine.  BUT, the problem is that IIS maps multiple codepoints**  to ASCII characters.  So, %u2044 also maps to /.  So this is what we**  need to handle here.**  **  This routine only handles the single encoding.  For double decoding,**  %u is handled in DoubleDecode().  It's the same routine, with just**  the GetByte function different.**  **  We use a get_byte function to get the bytes, so we can use this**  routine for PercentDecode and for DoubleDecode.****  @param ServerConf  the server configuration**  @param start       the start of the URI**  @param end         the end of the URI**  @param ptr         the current pointer into the URI**  @param get_byte    the function pointer to get bytes.**  **  @return integer**  **  @retval END_OF_BUFFER    we are at the end of the buffer**  @retval DOUBLE_ENCODING  this U encoding is possible double encoded**  @retval NON_ASCII_CHAR   return this char for non-ascii or bad decodes**  @retval iChar            this is the char that we decoded.*/static int UDecode(HI_SESSION *Session, const u_char *start,                   const u_char *end, const u_char **ptr, DECODE_FUNC get_byte,                   URI_NORM_STATE *norm_state){    HTTPINSPECT_CONF *ServerConf = Session->server_conf;    int iByte;    int iNorm;    int iCtr;    iNorm = 0;    hi_stats.unicode++;    for(iCtr = 0; iCtr < 4; iCtr++)    {        iByte = get_byte(Session, start, end, ptr, norm_state);        if(iByte & GET_ERR)            return iByte;        if(valid_lookup[(u_char)iByte] < 0)        {            hi_stats.non_ascii++;            return NON_ASCII_CHAR;        }        iNorm <<= 4;        iNorm = (iNorm | (hex_lookup[(u_char)iByte]));    }    /*    **  If the decoded codepoint is greater than a single byte value,    **  then we return a NON_ASCII_CHAR.    */    if(iNorm > 0xff)    {        /*        **  We check here for IIS codepoints that map to ASCII chars.        */        if(ServerConf->iis_unicode.on && iNorm <= 0xffff)        {            iNorm = ServerConf->iis_unicode_map[iNorm];            if(iNorm == HI_UI_NON_ASCII_CODEPOINT)            {                   hi_stats.non_ascii++;                iNorm = NON_ASCII_CHAR;            }            if(hi_eo_generate_event(Session, ServerConf->iis_unicode.alert) &&               !norm_state->param)            {                hi_eo_client_event_log(Session, HI_EO_CLIENT_IIS_UNICODE,                                       NULL, NULL);            }        }        else        {            hi_stats.non_ascii++;            return NON_ASCII_CHAR;        }    }    /*    **  Check if we alert on this encoding    */    if(hi_eo_generate_event(Session, ServerConf->u_encoding.alert) &&       !norm_state->param)    {        hi_eo_client_event_log(Session, HI_EO_CLIENT_U_ENCODE, NULL, NULL);    }    return iNorm;}/***  NAME**    PercentDecode::*//****  This is the first level of decoding, and deals with ASCII, U, and**  double decoding.****  This function is the main decoding function.  It handles all the ASCII**  encoding and the U encoding, and tells us when there is a double**  encoding.**  **  We use the GetPtr() routine to get the bytes for us.  This routine**  checks for DOUBLE_ENCODING and tells us about it if it finds something,**  so we can reset the ptrs and run it through the double decoding**  routine.**  **  The philosophy behind this routine is that if we run out of buffer**  we return such, the only other thing we return besides the decodes**  char is a NON_ASCII_CHAR in the case that we try and decode something**  like %tt.  This is no good, so we return a place holder.**  **  @param ServerConf  the server configuration**  @param start       the start of the URI**  @param end         the end of the URI**  @param ptr         the current pointer into the URI**  **  @return integer**  **  @retval END_OF_BUFFER   We've hit the end of buffer while decoding.**  @retval NON_ASCII_CHAR  Invalid hex encoding, so we return a placeholder.**  @retval char            return the valid char**  **  @see GetPtr()*/static int PercentDecode(HI_SESSION *Session, const u_char *start,                          const u_char *end, const u_char **ptr, URI_NORM_STATE *norm_state){    HTTPINSPECT_CONF *ServerConf = Session->server_conf;    int    iByte;    const u_char *orig_ptr;    int    iNorm;    orig_ptr = *ptr;    iByte = GetPtr(Session, start, end, ptr, norm_state);    if(iByte & GET_ERR)    {        if(iByte == END_OF_BUFFER)            return END_OF_BUFFER;        if(iByte == DOUBLE_ENCODING)        {            *ptr = orig_ptr;            return (int)**ptr;        }    }    /*    **  Initialize the normalization byte    */    iNorm = 0;    /*    **  hex values    */    if(valid_lookup[(u_char)iByte] < 0)    {        /*        **  Check for %u encoding.        **        **  The u-encoding loop always returns something.        */        if(ServerConf->u_encoding.on && (toupper(iByte) == 'U'))        {            iNorm = UDecode(Session, start, end, ptr, GetPtr, norm_state);            /*            **  We have to handle the double meaning of END_OF_BUFFER            **  when using the GetPtr() function.            */            if(iNorm & GET_ERR)            {                if(iNorm == END_OF_BUFFER)                {                    /*                    **  We have reached the end of the buffer while                    **  processing a U encoding.                    */                    return END_OF_BUFFER;                }                if(iNorm == DOUBLE_ENCODING)                {                    *ptr = orig_ptr;                    return (int)**ptr;                }            }            return iNorm;        }        else if(!ServerConf->base36.on ||                valid_lookup[(u_char)iByte] != BASE36_VAL)        {            hi_stats.non_ascii++;            return NON_ASCII_CHAR;        }        /*        **  The logic above dictates that if we get to this point, we        **  have a valid base36 encoding, so let's log the event.        */        hi_stats.base36++;        if(hi_eo_generate_event(Session, ServerConf->base36.alert) &&           !norm_state->param)        {            hi_eo_client_event_log(Session, HI_EO_CLIENT_BASE36, NULL, NULL);        }    }    iNorm = (hex_lookup[(u_char)iByte]<<4);    iByte = GetPtr(Session, start, end, ptr, norm_state);    if(iByte & GET_ERR)    {        if(iByte == END_OF_BUFFER)            return END_OF_BUFFER;        if(iByte == DOUBLE_ENCODING)        {            *ptr = orig_ptr;            return (int)**ptr;        }    }    if(valid_lookup[(u_char)iByte] < 0)    {        if(!ServerConf->base36.on || valid_lookup[(u_char)iByte] != BASE36_VAL)        {            hi_stats.non_ascii++;            return NON_ASCII_CHAR;        }        /*        **  Once again, we know we have a valid base36 encoding, let's alert        **  if possible.        */        hi_stats.base36++;        if(hi_eo_generate_event(Session, ServerConf->base36.alert) &&           !norm_state->param)        {            hi_eo_client_event_log(Session, HI_EO_CLIENT_BASE36, NULL, NULL);        }    }    iNorm = (iNorm | (hex_lookup[(u_char)iByte])) & 0xff;    if(hi_eo_generate_event(Session,ServerConf->ascii.alert) &&       !norm_state->param)    {        hi_eo_client_event_log(Session, HI_EO_CLIENT_ASCII,                               NULL, NULL);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -