github.com/TeaOSLab/EdgeNode@v1.3.8/internal/waf/injectionutils/libinjection/src/libinjection_sqli.h (about)

     1  /**
     2   * Copyright 2012-2016 Nick Galbreath
     3   * nickg@client9.com
     4   * BSD License -- see `COPYING.txt` for details
     5   *
     6   * https://libinjection.client9.com/
     7   *
     8   */
     9  
    10  #ifndef LIBINJECTION_SQLI_H
    11  #define LIBINJECTION_SQLI_H
    12  
    13  #ifdef __cplusplus
    14  extern "C" {
    15  #endif
    16  
    17  /*
    18   * Pull in size_t
    19   */
    20  #include <string.h>
    21  
    22  enum sqli_flags {
    23      FLAG_NONE            = 0
    24      , FLAG_QUOTE_NONE    = 1   /* 1 << 0 */
    25      , FLAG_QUOTE_SINGLE  = 2   /* 1 << 1 */
    26      , FLAG_QUOTE_DOUBLE  = 4   /* 1 << 2 */
    27  
    28      , FLAG_SQL_ANSI      = 8   /* 1 << 3 */
    29      , FLAG_SQL_MYSQL     = 16  /* 1 << 4 */
    30  };
    31  
    32  enum lookup_type {
    33      LOOKUP_WORD        = 1
    34      , LOOKUP_TYPE        = 2
    35      , LOOKUP_OPERATOR    = 3
    36      , LOOKUP_FINGERPRINT = 4
    37  };
    38  
    39  struct libinjection_sqli_token {
    40  #ifdef SWIG
    41  %immutable;
    42  #endif
    43      /*
    44       * position and length of token
    45       * in original string
    46       */
    47      size_t pos;
    48      size_t len;
    49  
    50      /*  count:
    51       *  in type 'v', used for number of opening '@'
    52       *  but maybe used in other contexts
    53       */
    54      int  count;
    55  
    56      char type;
    57      char str_open;
    58      char str_close;
    59      char val[32];
    60  };
    61  
    62  typedef struct libinjection_sqli_token stoken_t;
    63  
    64  /**
    65   * Pointer to function, takes c-string input,
    66   *  returns '\0' for no match, else a char
    67   */
    68  struct libinjection_sqli_state;
    69  typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*, int lookuptype, const char* word, size_t len);
    70  
    71  struct libinjection_sqli_state {
    72  #ifdef SWIG
    73  %immutable;
    74  #endif
    75  
    76      /*
    77       * input, does not need to be null terminated.
    78       * it is also not modified.
    79       */
    80      const char *s;
    81  
    82      /*
    83       * input length
    84       */
    85      size_t slen;
    86  
    87      /*
    88       * How to lookup a word or fingerprint
    89       */
    90      ptr_lookup_fn lookup;
    91      void*         userdata;
    92  
    93      /*
    94       *
    95       */
    96      int flags;
    97  
    98      /*
    99       * pos is the index in the string during tokenization
   100       */
   101      size_t pos;
   102  
   103  #ifndef SWIG
   104      /* for SWIG.. don't use this.. use functional API instead */
   105  
   106      /* MAX TOKENS + 1 since we use one extra token
   107       * to determine the type of the previous token
   108       */
   109      struct libinjection_sqli_token tokenvec[8];
   110  #endif
   111  
   112      /*
   113       * Pointer to token position in tokenvec, above
   114       */
   115      struct libinjection_sqli_token *current;
   116  
   117      /*
   118       * fingerprint pattern c-string
   119       * +1 for ending null
   120       * Minimum of 8 bytes to add gcc's -fstack-protector to work
   121       */
   122      char fingerprint[8];
   123  
   124      /*
   125       * Line number of code that said decided if the input was SQLi or
   126       * not.  Most of the time it's line that said "it's not a matching
   127       * fingerprint" but there is other logic that sometimes approves
   128       * an input. This is only useful for debugging.
   129       *
   130       */
   131      int reason;
   132  
   133      /* Number of ddw (dash-dash-white) comments
   134       * These comments are in the form of
   135       *   '--[whitespace]' or '--[EOF]'
   136       *
   137       * All databases treat this as a comment.
   138       */
   139       int stats_comment_ddw;
   140  
   141      /* Number of ddx (dash-dash-[notwhite]) comments
   142       *
   143       * ANSI SQL treats these are comments, MySQL treats this as
   144       * two unary operators '-' '-'
   145       *
   146       * If you are parsing result returns FALSE and
   147       * stats_comment_dd > 0, you should reparse with
   148       * COMMENT_MYSQL
   149       *
   150       */
   151      int stats_comment_ddx;
   152  
   153      /*
   154       * c-style comments found  /x .. x/
   155       */
   156      int stats_comment_c;
   157  
   158      /* '#' operators or MySQL EOL comments found
   159       *
   160       */
   161      int stats_comment_hash;
   162  
   163      /*
   164       * number of tokens folded away
   165       */
   166      int stats_folds;
   167  
   168      /*
   169       * total tokens processed
   170       */
   171      int stats_tokens;
   172  
   173  };
   174  
   175  typedef struct libinjection_sqli_state sfilter;
   176  
   177  struct libinjection_sqli_token* libinjection_sqli_get_token(
   178      struct libinjection_sqli_state* sql_state, int i);
   179  
   180  /*
   181   * Version info.
   182   *
   183   * This is moved into a function to allow SWIG and other auto-generated
   184   * binding to not be modified during minor release changes.  We change
   185   * change the version number in the c source file, and not regenerated
   186   * the binding
   187   *
   188   * See python's normalized version
   189   * http://www.python.org/dev/peps/pep-0386/#normalizedversion
   190   */
   191  const char* libinjection_version(void);
   192  
   193  /**
   194   *
   195   */
   196  void libinjection_sqli_init(struct libinjection_sqli_state *sf,
   197                              const char* s, size_t len,
   198                              int flags);
   199  
   200  /**
   201   * Main API: tests for SQLi in three possible contexts, no quotes,
   202   * single quote and double quote
   203   *
   204   * \param sql_state core data structure
   205   *
   206   * \return 1 (true) if SQLi, 0 (false) if benign
   207   */
   208  int libinjection_is_sqli(struct libinjection_sqli_state* sql_state);
   209  
   210  /*  FOR HACKERS ONLY
   211   *   provides deep hooks into the decision making process
   212   */
   213  void libinjection_sqli_callback(struct libinjection_sqli_state *sf,
   214                                  ptr_lookup_fn fn,
   215                                  void* userdata);
   216  
   217  
   218  /*
   219   * Resets state, but keeps initial string and callbacks
   220   */
   221  void libinjection_sqli_reset(struct libinjection_sqli_state *sf,
   222                               int flags);
   223  
   224  /**
   225   *
   226   */
   227  
   228  /**
   229   * This detects SQLi in a single context, mostly useful for custom
   230   * logic and debugging.
   231   *
   232   * \param sql_state  Main data structure
   233   * \param flags flags to adjust parsing
   234   *
   235   * \returns a pointer to sfilter.fingerprint as convenience
   236   *          do not free!
   237   *
   238   */
   239  const char* libinjection_sqli_fingerprint(struct libinjection_sqli_state *sql_state,
   240                                            int flags);
   241  
   242  /**
   243   * The default "word" to token-type or fingerprint function.  This
   244   * uses a ASCII case-insensitive binary tree.
   245   */
   246  char libinjection_sqli_lookup_word(struct libinjection_sqli_state *sql_state,
   247                                     int lookup_type,
   248                                     const char* str,
   249                                     size_t len);
   250  
   251  /* Streaming tokenization interface.
   252   *
   253   * sql_state->current is updated with the current token.
   254   *
   255   * \returns 1, has a token, keep going, or 0 no tokens
   256   *
   257   */
   258  int  libinjection_sqli_tokenize(struct libinjection_sqli_state *sf);
   259  
   260  /**
   261   * parses and folds input, up to 5 tokens
   262   *
   263   */
   264  int libinjection_sqli_fold(struct libinjection_sqli_state *sf);
   265  
   266  /** The built-in default function to match fingerprints
   267   *  and do false negative/positive analysis.  This calls the following
   268   *  two functions.  With this, you over-ride one part or the other.
   269   *
   270   *     return libinjection_sqli_blacklist(sql_state) &&
   271   *        libinjection_sqli_not_whitelist(sql_state);
   272   *
   273   * \param sql_state should be filled out after libinjection_sqli_fingerprint is called
   274   */
   275  int libinjection_sqli_check_fingerprint(struct libinjection_sqli_state * sql_state);
   276  
   277  /* Given a pattern determine if it's a SQLi pattern.
   278   *
   279   * \return TRUE if sqli, false otherwise
   280   */
   281  int libinjection_sqli_blacklist(struct libinjection_sqli_state* sql_state);
   282  
   283  /* Given a positive match for a pattern (i.e. pattern is SQLi), this function
   284   * does additional analysis to reduce false positives.
   285   *
   286   * \return TRUE if SQLi, false otherwise
   287   */
   288  int libinjection_sqli_not_whitelist(struct libinjection_sqli_state * sql_state);
   289  
   290  #ifdef __cplusplus
   291  }
   292  #endif
   293  
   294  #endif /* LIBINJECTION_SQLI_H */