forked from Annihil/mod_defender
-
Notifications
You must be signed in to change notification settings - Fork 2
/
RuntimeScanner.hpp
185 lines (162 loc) · 5.37 KB
/
RuntimeScanner.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/* _ _ __ _
* _ __ ___ ___ __| | __| | ___ / _| ___ _ __ __| | ___ _ __
* | '_ ` _ \ / _ \ / _` | / _` |/ _ \ |_ / _ \ '_ \ / _` |/ _ \ '__|
* | | | | | | (_) | (_| | | (_| | __/ _| __/ | | | (_| | __/ |
* |_| |_| |_|\___/ \__,_|___\__,_|\___|_| \___|_| |_|\__,_|\___|_|
* |_____|
* Copyright (c) 2017 Annihil
* Released under the GPLv3
*/
#ifndef RUNTIMESCANNER_HPP
#define RUNTIMESCANNER_HPP
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include <functional>
#include <cstdarg>
#include "RuleParser.h"
#include "JsonValidator.hpp"
//#define DEBUG_RUNTIME_PROCESSRULE
#ifdef DEBUG_RUNTIME_PROCESSRULE
#define DEBUG_RUNTIME_PR(x) do { std::cerr << x; } while (0)
#else
#define DEBUG_RUNTIME_PR(x)
#endif
//#define DEBUG_RUNTIME_BASESTR_RULE_SET
#ifdef DEBUG_RUNTIME_BASESTR_RULE_SET
#define DEBUG_RUNTIME_BRS(x) do { std::cerr << x; } while (0)
#else
#define DEBUG_RUNTIME_BRS(x)
#endif
#define PASS -1
#define STOP 403
/* used for reading input blocks */
#define READ_BLOCKSIZE 2048
using namespace Util;
using std::pair;
using std::make_pair;
using std::vector;
using std::set;
using std::string;
using std::cerr;
using std::stringstream;
using std::endl;
using std::regex;
using std::sregex_iterator;
using std::regex_match;
using std::distance;
using std::unordered_map;
using std::transform;
using std::function;
const std::string empty = string();
enum METHOD {
METHOD_GET = 0,
METHOD_POST,
METHOD_PUT,
UNSUPPORTED_METHOD,
};
enum CONTENT_TYPE {
CONTENT_TYPE_UNSUPPORTED = 0,
CONTENT_TYPE_URL_ENC, // application/x-www-form-urlencoded
CONTENT_TYPE_MULTIPART, // multipart/form-data
CONTENT_TYPE_APP_JSON, // application/json
};
enum TRANSFER_ENCODING {
TRANSFER_ENCODING_UNSUPPORTED = 0,
TRANSFER_ENCODING_CHUNKED
};
enum LOG_LVL {
LOG_LVL_EMERG = 0,
LOG_LVL_ALERT,
LOG_LVL_CRIT,
LOG_LVL_ERR,
LOG_LVL_WARNING,
LOG_LVL_NOTICE,
LOG_LVL_INFO,
LOG_LVL_DEBUG
};
typedef struct {
string zone;
set<unsigned long> ruleId;
string varname;
string content;
} match_info_t;
class RuntimeScanner {
friend class JsonValidator;
private:
RuleParser& parser;
stringstream matchVars;
unsigned int rulesMatchedCount = 0;
string uri;
vector<pair<string, string>> headers;
vector<pair<string, string>> get;
string rawContentType;
public:
METHOD method = UNSUPPORTED_METHOD;
CONTENT_TYPE contentType = CONTENT_TYPE_UNSUPPORTED;
TRANSFER_ENCODING transferEncoding = TRANSFER_ENCODING_UNSUPPORTED;
bool transferEncodingProvided = false;
unsigned long contentLength = 0;
bool contentLengthProvided = false;
string body;
unsigned long bodyLimit = 0;
bool bodyLimitExceeded = false;
int pid = 0;
long connectionId = 0;
string threadId;
string clientIp;
string requestedHost;
string serverHostname;
string fullUri;
string protocol;
string softwareVersion;
LOG_LVL logLevel = LOG_LVL_EMERG;
void *errorLogFile;
void *learningLogFile;
void *learningJSONLogFile;
bool learning;
bool extensiveLearning;
bool libinjSQL;
bool libinjXSS;
unordered_map<string, unsigned long> matchScores;
unordered_map<string, match_info_t> matchInfos;
bool block = false;
bool drop = false;
bool allow = false;
bool log = false;
function<int(void *file, const void *buf, size_t *len)> writeLogFn;
RuntimeScanner(RuleParser &parser) : parser(parser) {}
void setUri(char *uri);
void addHeader(char* key, char* val);
void addGETParameter(char* key, char* val);
void streamToFile(const stringstream &ss, void *file);
int processHeaders();
int processBody();
void logg(int priority, void *file, const char *fmt, ...);
void applyRuleAction(const rule_action_t &rule_action);
void checkLibInjection(MATCH_ZONE zone, const string &name, const string &value);
void basestrRuleset(MATCH_ZONE zone, const string &name, const string &value,
const vector<http_rule_t> &rules);
bool processRuleBuffer(const string &str, const http_rule_t &rl, unsigned long &nbMatch);
void applyCheckRule(const http_rule_t &rule, unsigned long nbMatch, const string &name, const string &value,
MATCH_ZONE zone, bool targetName);
void applyRuleMatch(const http_rule_t &rule, unsigned long nbMatch, MATCH_ZONE zone, const string &name,
const string &value, bool targetName);
void writeLearningLog();
void writeExtensiveLog(const http_rule_t &rule, MATCH_ZONE zone, const string &name,
const string &value, bool targetName);
void writeJSONLearningLog();
bool parseFormDataBoundary(unsigned char **boundary, unsigned long *boundary_len);
void multipartParse(u_char *src, unsigned long len);
bool contentDispositionParser(unsigned char *str, unsigned char *line_end,
unsigned char **fvarn_start, unsigned char **fvarn_end,
unsigned char **ffilen_start, unsigned char **ffilen_end);
int processAction();
bool splitUrlEncodedRuleset(char *str, const vector<http_rule_t> &rules, MATCH_ZONE zone);
};
#endif /* RUNTIMESCANNER_HPP */