|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Copyright 2012-2016 Nick Galbreath
|
|
Packit Service |
384592 |
* nickg@client9.com
|
|
Packit Service |
384592 |
* BSD License -- see `COPYING.txt` for details
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* https://libinjection.client9.com/
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifndef LIBINJECTION_SQLI_H
|
|
Packit Service |
384592 |
#define LIBINJECTION_SQLI_H
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef __cplusplus
|
|
Packit Service |
384592 |
extern "C" {
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Pull in size_t
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
#include <string.h>
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
enum sqli_flags {
|
|
Packit Service |
384592 |
FLAG_NONE = 0
|
|
Packit Service |
384592 |
, FLAG_QUOTE_NONE = 1 /* 1 << 0 */
|
|
Packit Service |
384592 |
, FLAG_QUOTE_SINGLE = 2 /* 1 << 1 */
|
|
Packit Service |
384592 |
, FLAG_QUOTE_DOUBLE = 4 /* 1 << 2 */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
, FLAG_SQL_ANSI = 8 /* 1 << 3 */
|
|
Packit Service |
384592 |
, FLAG_SQL_MYSQL = 16 /* 1 << 4 */
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
enum lookup_type {
|
|
Packit Service |
384592 |
LOOKUP_WORD = 1
|
|
Packit Service |
384592 |
, LOOKUP_TYPE = 2
|
|
Packit Service |
384592 |
, LOOKUP_OPERATOR = 3
|
|
Packit Service |
384592 |
, LOOKUP_FINGERPRINT = 4
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
struct libinjection_sqli_token {
|
|
Packit Service |
384592 |
#ifdef SWIG
|
|
Packit Service |
384592 |
%immutable;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* position and length of token
|
|
Packit Service |
384592 |
* in original string
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
size_t pos;
|
|
Packit Service |
384592 |
size_t len;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* count:
|
|
Packit Service |
384592 |
* in type 'v', used for number of opening '@'
|
|
Packit Service |
384592 |
* but maybe used in other contexts
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int count;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char type;
|
|
Packit Service |
384592 |
char str_open;
|
|
Packit Service |
384592 |
char str_close;
|
|
Packit Service |
384592 |
char val[32];
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
typedef struct libinjection_sqli_token stoken_t;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Pointer to function, takes c-string input,
|
|
Packit Service |
384592 |
* returns '\0' for no match, else a char
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
struct libinjection_sqli_state;
|
|
Packit Service |
384592 |
typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*, int lookuptype, const char* word, size_t len);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
struct libinjection_sqli_state {
|
|
Packit Service |
384592 |
#ifdef SWIG
|
|
Packit Service |
384592 |
%immutable;
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* input, does not need to be null terminated.
|
|
Packit Service |
384592 |
* it is also not modified.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
const char *s;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* input length
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
size_t slen;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* How to lookup a word or fingerprint
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
ptr_lookup_fn lookup;
|
|
Packit Service |
384592 |
void* userdata;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int flags;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* pos is the index in the string during tokenization
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
size_t pos;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifndef SWIG
|
|
Packit Service |
384592 |
/* for SWIG.. don't use this.. use functional API instead */
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* MAX TOKENS + 1 since we use one extra token
|
|
Packit Service |
384592 |
* to determine the type of the previous token
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
struct libinjection_sqli_token tokenvec[8];
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Pointer to token position in tokenvec, above
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
struct libinjection_sqli_token *current;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* fingerprint pattern c-string
|
|
Packit Service |
384592 |
* +1 for ending null
|
|
Packit Service |
384592 |
* Minimum of 8 bytes to add gcc's -fstack-protector to work
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
char fingerprint[8];
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Line number of code that said decided if the input was SQLi or
|
|
Packit Service |
384592 |
* not. Most of the time it's line that said "it's not a matching
|
|
Packit Service |
384592 |
* fingerprint" but there is other logic that sometimes approves
|
|
Packit Service |
384592 |
* an input. This is only useful for debugging.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int reason;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Number of ddw (dash-dash-white) comments
|
|
Packit Service |
384592 |
* These comments are in the form of
|
|
Packit Service |
384592 |
* '--[whitespace]' or '--[EOF]'
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* All databases treat this as a comment.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_comment_ddw;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Number of ddx (dash-dash-[notwhite]) comments
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* ANSI SQL treats these are comments, MySQL treats this as
|
|
Packit Service |
384592 |
* two unary operators '-' '-'
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* If you are parsing result returns FALSE and
|
|
Packit Service |
384592 |
* stats_comment_dd > 0, you should reparse with
|
|
Packit Service |
384592 |
* COMMENT_MYSQL
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_comment_ddx;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* c-style comments found /x .. x/
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_comment_c;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* '#' operators or MySQL EOL comments found
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_comment_hash;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* number of tokens folded away
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_folds;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* total tokens processed
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int stats_tokens;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
typedef struct libinjection_sqli_state sfilter;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
struct libinjection_sqli_token* libinjection_sqli_get_token(
|
|
Packit Service |
384592 |
struct libinjection_sqli_state* sqlistate, int i);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Version info.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* This is moved into a function to allow SWIG and other auto-generated
|
|
Packit Service |
384592 |
* binding to not be modified during minor release changes. We change
|
|
Packit Service |
384592 |
* change the version number in the c source file, and not regenerated
|
|
Packit Service |
384592 |
* the binding
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* See python's normalized version
|
|
Packit Service |
384592 |
* http://www.python.org/dev/peps/pep-0386/#normalizedversion
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
const char* libinjection_version(void);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
void libinjection_sqli_init(struct libinjection_sqli_state* sql_state,
|
|
Packit Service |
384592 |
const char* s, size_t slen,
|
|
Packit Service |
384592 |
int flags);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* Main API: tests for SQLi in three possible contexts, no quotes,
|
|
Packit Service |
384592 |
* single quote and double quote
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \param sql_state core data structure
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \return 1 (true) if SQLi, 0 (false) if benign
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_is_sqli(struct libinjection_sqli_state* sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* FOR HACKERS ONLY
|
|
Packit Service |
384592 |
* provides deep hooks into the decision making process
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
void libinjection_sqli_callback(struct libinjection_sqli_state* sql_state,
|
|
Packit Service |
384592 |
ptr_lookup_fn fn,
|
|
Packit Service |
384592 |
void* userdata);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* Resets state, but keeps initial string and callbacks
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
void libinjection_sqli_reset(struct libinjection_sqli_state* sql_state,
|
|
Packit Service |
384592 |
int flags);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* This detects SQLi in a single context, mostly useful for custom
|
|
Packit Service |
384592 |
* logic and debugging.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \param sql_state Main data structure
|
|
Packit Service |
384592 |
* \param flags flags to adjust parsing
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \returns a pointer to sfilter.fingerprint as convenience
|
|
Packit Service |
384592 |
* do not free!
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
const char* libinjection_sqli_fingerprint(struct libinjection_sqli_state* sql_state,
|
|
Packit Service |
384592 |
int flags);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* The default "word" to token-type or fingerprint function. This
|
|
Packit Service |
384592 |
* uses a ASCII case-insensitive binary tree.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
char libinjection_sqli_lookup_word(struct libinjection_sqli_state* sql_state,
|
|
Packit Service |
384592 |
int lookup_type,
|
|
Packit Service |
384592 |
const char* s,
|
|
Packit Service |
384592 |
size_t slen);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Streaming tokenization interface.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* sql_state->current is updated with the current token.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \returns 1, has a token, keep going, or 0 no tokens
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_sqli_tokenize(struct libinjection_sqli_state * sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/**
|
|
Packit Service |
384592 |
* parses and folds input, up to 5 tokens
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_sqli_fold(struct libinjection_sqli_state * sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/** The built-in default function to match fingerprints
|
|
Packit Service |
384592 |
* and do false negative/positive analysis. This calls the following
|
|
Packit Service |
384592 |
* two functions. With this, you over-ride one part or the other.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* return libinjection_sqli_blacklist(sql_state) &&
|
|
Packit Service |
384592 |
* libinjection_sqli_not_whitelist(sql_state);
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \param sql_state should be filled out after libinjection_sqli_fingerprint is called
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_sqli_check_fingerprint(struct libinjection_sqli_state * sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Given a pattern determine if it's a SQLi pattern.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \return TRUE if sqli, false otherwise
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_sqli_blacklist(struct libinjection_sqli_state* sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Given a positive match for a pattern (i.e. pattern is SQLi), this function
|
|
Packit Service |
384592 |
* does additional analysis to reduce false positives.
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* \return TRUE if SQLi, false otherwise
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
int libinjection_sqli_not_whitelist(struct libinjection_sqli_state * sql_state);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#ifdef __cplusplus
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#endif /* LIBINJECTION_SQLI_H */
|