mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-16 07:56:12 +03:00
202 lines
5.0 KiB
C
202 lines
5.0 KiB
C
/**
|
|
* Copyright 2012, 2013 Nick Galbreath
|
|
* nickg@client9.com
|
|
* BSD License -- see COPYING.txt for details
|
|
*
|
|
*
|
|
* HOW TO USE:
|
|
*
|
|
* #include "libinjection.h"
|
|
*
|
|
* // Normalize query or postvar value
|
|
* // If it comes in urlencoded, then it's up to you
|
|
* // to urldecode it. If it's in correct form already
|
|
* // then nothing to do!
|
|
*
|
|
* sfilter s;
|
|
* int sqli = libinjection_is_sqli(&s, user_string, new_len,
|
|
* NULL, NULL);
|
|
*
|
|
* // 0 = not sqli
|
|
* // 1 = is sqli
|
|
*
|
|
* // That's it! sfilter s has some data on how it matched or not
|
|
* // details to come!
|
|
*
|
|
*/
|
|
|
|
#ifndef _LIBINJECTION_H
|
|
#define _LIBINJECTION_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
* Version info.
|
|
* See python's normalized version
|
|
* http://www.python.org/dev/peps/pep-0386/#normalizedversion
|
|
*/
|
|
#define LIBINJECTION_VERSION "3.0.0-pre8"
|
|
|
|
#define ST_MAX_SIZE 32
|
|
#define MAX_TOKENS 5
|
|
|
|
#define CHAR_NULL '\0'
|
|
#define CHAR_SINGLE '\''
|
|
#define CHAR_DOUBLE '"'
|
|
|
|
#define COMMENTS_ANSI 0
|
|
#define COMMENTS_MYSQL 1
|
|
|
|
typedef struct {
|
|
#ifdef SWIG
|
|
%immutable;
|
|
#endif
|
|
char type;
|
|
char str_open;
|
|
char str_close;
|
|
char var_count;
|
|
char val[ST_MAX_SIZE];
|
|
} stoken_t;
|
|
|
|
typedef struct {
|
|
#ifdef SWIG
|
|
%immutable;
|
|
#endif
|
|
|
|
/* input */
|
|
const char *s;
|
|
size_t slen;
|
|
|
|
/* current tokenize state */
|
|
size_t pos;
|
|
int in_comment;
|
|
|
|
/* final sqli data */
|
|
stoken_t *current;
|
|
|
|
/* MAX TOKENS + 1 since use one extra token to determine
|
|
the type of the previous token */
|
|
stoken_t tokenvec[MAX_TOKENS + 1];
|
|
|
|
/* +1 for ending null */
|
|
char pat[MAX_TOKENS + 1];
|
|
char delim;
|
|
char comment_style;
|
|
|
|
int reason;
|
|
|
|
/* Number of ddw (dash-dash-white) comments
|
|
* These comments are in the form of
|
|
* '--[whitespace]' or '--[EOF]'
|
|
*
|
|
* All databases treat this as a comment.
|
|
*/
|
|
int stats_comment_ddw;
|
|
|
|
/* Number of ddx (dash-dash-[notwhite]) comments
|
|
*
|
|
* ANSI SQL treats these are comments, MySQL treats this as
|
|
* two unary operators '-' '-'
|
|
*
|
|
* If you are parsing result returns FALSE and
|
|
* stats_comment_dd > 0, you should reparse with
|
|
* COMMENT_MYSQL
|
|
*
|
|
*/
|
|
int stats_comment_ddx;
|
|
|
|
int stats_comment_c;
|
|
|
|
int stats_folds;
|
|
|
|
} sfilter;
|
|
|
|
/**
|
|
* Pointer to function, takes cstr input, returns 1 for true, 0 for false
|
|
*/
|
|
typedef int (*ptr_fingerprints_fn)(sfilter*, void* callbackarg);
|
|
|
|
/**
|
|
* Main API: tests for SQLi in three possible contexts, no quotes,
|
|
* single quote and double quote
|
|
*
|
|
* \param sql_state
|
|
* \param s
|
|
* \param slen
|
|
* \param fn a pointer to a function that determines if a fingerprint
|
|
* is a match or not. If NULL, then a hardwired list is
|
|
* used. Useful for loading fingerprints data from custom
|
|
* sources.
|
|
* \param callbackarg. For default case, use NULL
|
|
*
|
|
* \return 1 (true) if SQLi, 0 (false) if benign
|
|
*/
|
|
int libinjection_is_sqli(sfilter * sql_state,
|
|
const char *s, size_t slen,
|
|
ptr_fingerprints_fn fn, void* callbackarg);
|
|
|
|
/**
|
|
* This detects SQLi in a single context, mostly useful for custom
|
|
* logic and debugging.
|
|
*
|
|
* \param sql_state
|
|
* \param s
|
|
* \param slen
|
|
* \param delim must be char of
|
|
* CHAR_NULL (\0), raw context
|
|
* CHAR_SINGLE ('), single quote context
|
|
* CHAR_DOUBLE ("), double quote context
|
|
* Other values will likely be ignored.
|
|
*
|
|
* \return pointer to sfilter.pat as convience.
|
|
* do not free!
|
|
*
|
|
*/
|
|
const char* libinjection_sqli_fingerprint(sfilter * sql_state,
|
|
const char *s, size_t slen,
|
|
char delim,
|
|
char comment_style);
|
|
|
|
/* FOR H@CKERS ONLY
|
|
*
|
|
*/
|
|
|
|
void libinjection_sqli_init(sfilter* sql_state,
|
|
const char* s, size_t slen,
|
|
char delim, char comment_style);
|
|
|
|
int libinjection_sqli_tokenize(sfilter * sql_state, stoken_t *ouput);
|
|
|
|
/** The built-in default function to match fingerprints
|
|
* and do false negative/positive analysis. This calls the following
|
|
* two functions. With this, you other-ride one part or the other.
|
|
*
|
|
* return libinjection_sqli_blacklist(sql_state, callbackarg) &&
|
|
* libinject_sqli_not_whitelist(sql_state, callbackarg);
|
|
*
|
|
* \param sql_state should be filled out after libinjection_sqli_fingerprint is called
|
|
* \param callbackarg is unused but here to be used with API.
|
|
*/
|
|
int libinjection_sqli_check_fingerprint(sfilter *sql_state, void* callbackarg);
|
|
|
|
/* Given a pattern determine if it's a SQLi pattern.
|
|
*
|
|
* \return TRUE if sqli, false otherwise
|
|
*/
|
|
int libinjection_sqli_blacklist(sfilter* sql_state);
|
|
|
|
/* Given a positive match for a pattern (i.e. pattern is SQLi), this function
|
|
* does additional analysis to reduce false positives.
|
|
*
|
|
* \return TRUE if sqli, false otherwise
|
|
*/
|
|
int libinjection_sqli_not_whitelist(sfilter* sql_state);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _LIBINJECTION_H */
|