rack-libinjection 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +55 -0
- data/CHANGELOG.md +112 -0
- data/GET_STARTED.md +418 -0
- data/LICENSE-libinjection.txt +33 -0
- data/LICENSE.txt +21 -0
- data/README.md +68 -0
- data/SECURITY.md +65 -0
- data/ext/libinjection/extconf.rb +113 -0
- data/ext/libinjection/libinjection_ext.c +1132 -0
- data/ext/libinjection/vendor/libinjection/.vendored +5 -0
- data/ext/libinjection/vendor/libinjection/COPYING +33 -0
- data/ext/libinjection/vendor/libinjection/MIGRATION.md +393 -0
- data/ext/libinjection/vendor/libinjection/README.md +251 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection.h +70 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_error.h +26 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_html5.c +830 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_html5.h +56 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_sqli.c +2342 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_sqli.h +297 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_sqli_data.h +9651 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_xss.c +1203 -0
- data/ext/libinjection/vendor/libinjection/src/libinjection_xss.h +23 -0
- data/lib/libinjection/version.rb +6 -0
- data/lib/libinjection.rb +31 -0
- data/lib/rack/libinjection.rb +586 -0
- data/lib/rack-libinjection.rb +3 -0
- data/samples/README.md +67 -0
- data/samples/libinjection_detect_raw_hot_path.rb +161 -0
- data/samples/rack_all_surfaces_hot_path.rb +198 -0
- data/samples/rack_params_hot_path.rb +166 -0
- data/samples/rack_query_hot_path.rb +176 -0
- data/samples/results/.gitkeep +0 -0
- data/script/fuzz_smoke.rb +39 -0
- data/script/vendor_libs.rb +227 -0
- data/test/test_helper.rb +7 -0
- data/test/test_libinjection.rb +223 -0
- data/test/test_middleware.rb +404 -0
- metadata +148 -0
|
@@ -0,0 +1,1203 @@
|
|
|
1
|
+
|
|
2
|
+
#include "libinjection_xss.h"
|
|
3
|
+
#include "libinjection.h"
|
|
4
|
+
#include "libinjection_html5.h"
|
|
5
|
+
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
|
|
8
|
+
#define IS_HEX_ENTITY_PREFIX(src) (*(src + 2) == 'x' || *(src + 2) == 'X')
|
|
9
|
+
|
|
10
|
+
typedef enum attribute {
|
|
11
|
+
TYPE_NONE,
|
|
12
|
+
TYPE_BLACK, /* ban always */
|
|
13
|
+
TYPE_ATTR_URL, /* attribute value takes a URL-like object */
|
|
14
|
+
TYPE_STYLE,
|
|
15
|
+
TYPE_ATTR_INDIRECT /* attribute *name* is given in *value* */
|
|
16
|
+
} attribute_t;
|
|
17
|
+
|
|
18
|
+
static attribute_t is_black_attr(const char *s, size_t len);
|
|
19
|
+
static int is_black_tag(const char *s, size_t len);
|
|
20
|
+
static int is_black_url(const char *s, size_t len);
|
|
21
|
+
static int cstrcasecmp_with_null(const char *a, const char *b, size_t n);
|
|
22
|
+
static int html_decode_char_at(const char *src, size_t len, size_t *consumed);
|
|
23
|
+
static int htmlencode_startswith(const char *a /* prefix */,
|
|
24
|
+
const char *b /* src */, size_t n);
|
|
25
|
+
|
|
26
|
+
typedef struct stringtype {
|
|
27
|
+
const char *name;
|
|
28
|
+
attribute_t atype;
|
|
29
|
+
} stringtype_t;
|
|
30
|
+
|
|
31
|
+
static const int gsHexDecodeMap[256] = {
|
|
32
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
33
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
34
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
35
|
+
256, 256, 256, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 256,
|
|
36
|
+
256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 256, 256, 256,
|
|
37
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
38
|
+
256, 256, 256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 256,
|
|
39
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
40
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
41
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
42
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
43
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
44
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
45
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
46
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
47
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
48
|
+
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
|
49
|
+
256};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @brief Decode HTML character entities in numeric form.
|
|
53
|
+
*
|
|
54
|
+
* This function decodes HTML character entities in numeric form, both decimal
|
|
55
|
+
* (e.g., A) and hexadecimal (e.g., A). It processes the input string
|
|
56
|
+
* and returns the corresponding character code, updating the number of
|
|
57
|
+
* characters consumed during decoding.
|
|
58
|
+
*
|
|
59
|
+
* Note that this function does not handle named entities (e.g., &).
|
|
60
|
+
*
|
|
61
|
+
* Note: The function assumes that the input string is well-formed and does not
|
|
62
|
+
* perform extensive validation. This means it allows sequences without ';', eg
|
|
63
|
+
* 'A' and decodes to 'A'.
|
|
64
|
+
*
|
|
65
|
+
* @param src The input string containing the HTML character entity.
|
|
66
|
+
* @param len The length of the input string.
|
|
67
|
+
* @param consumed Pointer to a size_t variable where the number of characters
|
|
68
|
+
* consumed will be stored.
|
|
69
|
+
* @return The decoded character code, or -1 on error.
|
|
70
|
+
*/
|
|
71
|
+
static int html_decode_char_at(const char *src, size_t len, size_t *consumed) {
|
|
72
|
+
int val = 0;
|
|
73
|
+
size_t i;
|
|
74
|
+
int ch;
|
|
75
|
+
|
|
76
|
+
if (len == 0 || src == NULL) {
|
|
77
|
+
*consumed = 0;
|
|
78
|
+
return -1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
*consumed = 1;
|
|
82
|
+
/*
|
|
83
|
+
* check if it starts with '&' and
|
|
84
|
+
* len >=3 or src[2] == 'x'/'X' and len >=4
|
|
85
|
+
* if not, return the character itself
|
|
86
|
+
*/
|
|
87
|
+
if (*src != '&' || len < 3 || (IS_HEX_ENTITY_PREFIX(src) && len < 4)) {
|
|
88
|
+
return (unsigned char)(*src);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* check if the second character is '#'
|
|
93
|
+
* if not, return '&' (we don't handle named entities here)
|
|
94
|
+
*/
|
|
95
|
+
if (*(src + 1) != '#') {
|
|
96
|
+
/* normally this would be for named entities
|
|
97
|
+
* but for this case we don't actually care
|
|
98
|
+
*/
|
|
99
|
+
return '&';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// if there's a hex prefix
|
|
103
|
+
if (IS_HEX_ENTITY_PREFIX(src)) {
|
|
104
|
+
ch = (unsigned char)(*(src + 3));
|
|
105
|
+
ch = gsHexDecodeMap[ch];
|
|
106
|
+
if (ch == 256) {
|
|
107
|
+
/* degenerate case '&#[?]' */
|
|
108
|
+
return '&';
|
|
109
|
+
}
|
|
110
|
+
val = ch;
|
|
111
|
+
i = 4;
|
|
112
|
+
while (i < len) {
|
|
113
|
+
ch = (unsigned char)src[i];
|
|
114
|
+
if (ch == ';') {
|
|
115
|
+
*consumed = i + 1;
|
|
116
|
+
return val;
|
|
117
|
+
}
|
|
118
|
+
ch = gsHexDecodeMap[ch];
|
|
119
|
+
if (ch == 256) {
|
|
120
|
+
*consumed = i;
|
|
121
|
+
return val;
|
|
122
|
+
}
|
|
123
|
+
val = (val * 16) + ch;
|
|
124
|
+
if (val > 0x1000FF) {
|
|
125
|
+
return '&';
|
|
126
|
+
}
|
|
127
|
+
++i;
|
|
128
|
+
}
|
|
129
|
+
*consumed = i;
|
|
130
|
+
return val;
|
|
131
|
+
} else {
|
|
132
|
+
i = 2;
|
|
133
|
+
ch = (unsigned char)src[i];
|
|
134
|
+
if (ch < '0' || ch > '9') {
|
|
135
|
+
return '&';
|
|
136
|
+
}
|
|
137
|
+
val = ch - '0';
|
|
138
|
+
i += 1;
|
|
139
|
+
while (i < len) {
|
|
140
|
+
ch = (unsigned char)src[i];
|
|
141
|
+
if (ch == ';') {
|
|
142
|
+
*consumed = i + 1;
|
|
143
|
+
return val;
|
|
144
|
+
}
|
|
145
|
+
if (ch < '0' || ch > '9') {
|
|
146
|
+
*consumed = i;
|
|
147
|
+
return val;
|
|
148
|
+
}
|
|
149
|
+
val = (val * 10) + (ch - '0');
|
|
150
|
+
if (val > 0x1000FF) {
|
|
151
|
+
return '&';
|
|
152
|
+
}
|
|
153
|
+
++i;
|
|
154
|
+
}
|
|
155
|
+
*consumed = i;
|
|
156
|
+
return val;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
* These were extracted from multiple browser sources:
|
|
162
|
+
* - WebKit:
|
|
163
|
+
* https://github.com/WebKit/WebKit/blob/main/Source/WebCore/dom/EventNames.json
|
|
164
|
+
* - Chromium/Blink:
|
|
165
|
+
* https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/dom/global_event_handlers.idl
|
|
166
|
+
* - Firefox/Gecko:
|
|
167
|
+
* https://github.com/mozilla-firefox/firefox/blob/main/dom/events/EventNameList.h
|
|
168
|
+
* - W3C/WHATWG specifications where applicable
|
|
169
|
+
*
|
|
170
|
+
* view-source:
|
|
171
|
+
* data:
|
|
172
|
+
* javascript:
|
|
173
|
+
* events:
|
|
174
|
+
*/
|
|
175
|
+
static stringtype_t BLACKATTREVENT[] = {
|
|
176
|
+
{"ABORT", TYPE_BLACK},
|
|
177
|
+
{"ACCESSKEYNOTFOUND",
|
|
178
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
179
|
+
*/
|
|
180
|
+
{"ACTIVATE", TYPE_BLACK},
|
|
181
|
+
{"ACTIVE", TYPE_BLACK},
|
|
182
|
+
{"ADDSOURCEBUFFER", TYPE_BLACK},
|
|
183
|
+
{"ADDSTREAM", TYPE_BLACK},
|
|
184
|
+
{"ADDTRACK", TYPE_BLACK},
|
|
185
|
+
{"AFTERPAINT",
|
|
186
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
187
|
+
*/
|
|
188
|
+
{"AFTERPRINT", TYPE_BLACK},
|
|
189
|
+
{"AFTERSCRIPTEXECUTE",
|
|
190
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
191
|
+
*/
|
|
192
|
+
{"ANIMATIONCANCEL", TYPE_BLACK},
|
|
193
|
+
{"ANIMATIONEND", TYPE_BLACK},
|
|
194
|
+
{"ANIMATIONITERATION", TYPE_BLACK},
|
|
195
|
+
{"ANIMATIONSTART", TYPE_BLACK},
|
|
196
|
+
{"AUDIOEND", TYPE_BLACK},
|
|
197
|
+
{"AUDIOCOMPLETE",
|
|
198
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
199
|
+
*/
|
|
200
|
+
{"AUDIOPROCESS", TYPE_BLACK},
|
|
201
|
+
{"AUDIOSTART", TYPE_BLACK},
|
|
202
|
+
{"AUTOCOMPLETE", TYPE_BLACK},
|
|
203
|
+
{"AUTOCOMPLETEERROR", TYPE_BLACK},
|
|
204
|
+
{"AUXCLICK", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl,
|
|
205
|
+
WebKit: EventNames.json */
|
|
206
|
+
{"BACKGROUNDFETCHABORT", TYPE_BLACK},
|
|
207
|
+
{"BACKGROUNDFETCHCLICK", TYPE_BLACK},
|
|
208
|
+
{"BACKGROUNDFETCHFAIL", TYPE_BLACK},
|
|
209
|
+
{"BACKGROUNDFETCHSUCCESS", TYPE_BLACK},
|
|
210
|
+
{"BEFOREACTIVATE", TYPE_BLACK},
|
|
211
|
+
{"BEFORECOPY", TYPE_BLACK},
|
|
212
|
+
{"BEFORECUT", TYPE_BLACK},
|
|
213
|
+
{"BEFOREINPUT", TYPE_BLACK},
|
|
214
|
+
{"BEFORELOAD", TYPE_BLACK},
|
|
215
|
+
{"BEFOREMATCH",
|
|
216
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, WebKit:
|
|
217
|
+
EventNames.json, Firefox: EventNameList.h */
|
|
218
|
+
{"BEFOREPASTE", TYPE_BLACK},
|
|
219
|
+
{"BEFOREPRINT", TYPE_BLACK},
|
|
220
|
+
{"BEFORESCRIPTEXECUTE",
|
|
221
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
222
|
+
*/
|
|
223
|
+
{"BEFORETOGGLE", TYPE_BLACK},
|
|
224
|
+
{"BEFOREUNLOAD", TYPE_BLACK},
|
|
225
|
+
{"BEGINEVENT", TYPE_BLACK},
|
|
226
|
+
{"BLOCKED", TYPE_BLACK},
|
|
227
|
+
{"BLUR", TYPE_BLACK},
|
|
228
|
+
{"BOUNDARY", TYPE_BLACK},
|
|
229
|
+
{"BUFFEREDAMOUNTLOW", TYPE_BLACK},
|
|
230
|
+
{"BUFFEREDCHANGE", TYPE_BLACK},
|
|
231
|
+
{"CACHED", TYPE_BLACK},
|
|
232
|
+
{"CANCEL", TYPE_BLACK},
|
|
233
|
+
{"CANPLAY", TYPE_BLACK},
|
|
234
|
+
{"CANPLAYTHROUGH", TYPE_BLACK},
|
|
235
|
+
{"CHANGE", TYPE_BLACK},
|
|
236
|
+
{"CHARGINGCHANGE", TYPE_BLACK},
|
|
237
|
+
{"CHARGINGTIMECHANGE", TYPE_BLACK},
|
|
238
|
+
{"CHECKING", TYPE_BLACK},
|
|
239
|
+
{"CLICK", TYPE_BLACK},
|
|
240
|
+
{"CLOSE", TYPE_BLACK},
|
|
241
|
+
{"CLOSING", TYPE_BLACK},
|
|
242
|
+
{"COMPLETE", TYPE_BLACK},
|
|
243
|
+
{"COMPOSITIONEND", TYPE_BLACK},
|
|
244
|
+
{"COMPOSITIONSTART", TYPE_BLACK},
|
|
245
|
+
{"COMPOSITIONCHANGE",
|
|
246
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
247
|
+
*/
|
|
248
|
+
{"COMPOSITIONUPDATE", TYPE_BLACK},
|
|
249
|
+
{"COMMAND", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, WebKit:
|
|
250
|
+
EventNames.json, Firefox: EventNameList.h */
|
|
251
|
+
{"CONFIGURATIONCHANGE", TYPE_BLACK},
|
|
252
|
+
{"CONNECT", TYPE_BLACK},
|
|
253
|
+
{"CONNECTING", TYPE_BLACK},
|
|
254
|
+
{"CONNECTIONSTATECHANGE", TYPE_BLACK},
|
|
255
|
+
{"CONTENTVISIBILITYAUTOSTATECHANGE", TYPE_BLACK},
|
|
256
|
+
{"CONTEXTLOST",
|
|
257
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, WebKit:
|
|
258
|
+
EventNames.json, Firefox: EventNameList.h */
|
|
259
|
+
{"CONTEXTMENU", TYPE_BLACK},
|
|
260
|
+
{"CONTEXTRESTORED",
|
|
261
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, WebKit:
|
|
262
|
+
EventNames.json, Firefox: EventNameList.h */
|
|
263
|
+
{"CONTROLLERCHANGE", TYPE_BLACK},
|
|
264
|
+
{"COOKIECHANGE", TYPE_BLACK},
|
|
265
|
+
{"COORDINATORSTATECHANGE", TYPE_BLACK},
|
|
266
|
+
{"COPY", TYPE_BLACK},
|
|
267
|
+
{"COUPONCODECHANGED", TYPE_BLACK},
|
|
268
|
+
{"CUECHANGE", TYPE_BLACK},
|
|
269
|
+
{"CURRENTENTRYCHANGE", TYPE_BLACK},
|
|
270
|
+
{"CUT", TYPE_BLACK},
|
|
271
|
+
{"DATAAVAILABLE", TYPE_BLACK},
|
|
272
|
+
{"DATACHANNEL", TYPE_BLACK},
|
|
273
|
+
{"DBLCLICK", TYPE_BLACK},
|
|
274
|
+
{"DEQUEUE", TYPE_BLACK},
|
|
275
|
+
{"DEVICECHANGE", TYPE_BLACK},
|
|
276
|
+
{"DEVICELIGHT",
|
|
277
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
278
|
+
*/
|
|
279
|
+
{"DEVICEMOTION", TYPE_BLACK},
|
|
280
|
+
{"DEVICEORIENTATION", TYPE_BLACK},
|
|
281
|
+
{"DEVICEORIENTATIONABSOLUTE",
|
|
282
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
283
|
+
*/
|
|
284
|
+
{"DISCHARGINGTIMECHANGE", TYPE_BLACK},
|
|
285
|
+
{"DISCONNECT", TYPE_BLACK},
|
|
286
|
+
{"DISPOSE", TYPE_BLACK},
|
|
287
|
+
{"DOMACTIVATE", TYPE_BLACK},
|
|
288
|
+
{"DOMCHARACTERDATAMODIFIED", TYPE_BLACK},
|
|
289
|
+
{"DOMCONTENTLOADED", TYPE_BLACK},
|
|
290
|
+
{"DOMNODEINSERTED", TYPE_BLACK},
|
|
291
|
+
{"DOMNODEINSERTEDINTODOCUMENT", TYPE_BLACK},
|
|
292
|
+
{"DOMNODEREMOVED", TYPE_BLACK},
|
|
293
|
+
{"DOMNODEREMOVEDFROMDOCUMENT", TYPE_BLACK},
|
|
294
|
+
{"DOMSUBTREEMODIFIED", TYPE_BLACK},
|
|
295
|
+
{"DOWNLOADING", TYPE_BLACK},
|
|
296
|
+
{"DRAG", TYPE_BLACK},
|
|
297
|
+
{"DRAGEND", TYPE_BLACK},
|
|
298
|
+
{"DRAGENTER", TYPE_BLACK},
|
|
299
|
+
{"DRAGLEAVE", TYPE_BLACK},
|
|
300
|
+
{"DRAGEXIT", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl,
|
|
301
|
+
Firefox: EventNameList.h */
|
|
302
|
+
{"DRAGOVER", TYPE_BLACK},
|
|
303
|
+
{"DRAGSTART", TYPE_BLACK},
|
|
304
|
+
{"DROP", TYPE_BLACK},
|
|
305
|
+
{"DURATIONCHANGE", TYPE_BLACK},
|
|
306
|
+
{"EMPTIED", TYPE_BLACK},
|
|
307
|
+
{"ENCRYPTED", TYPE_BLACK},
|
|
308
|
+
{"EDGEUICANCELED",
|
|
309
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
310
|
+
*/
|
|
311
|
+
{"EDGEUICOMPLETED",
|
|
312
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
313
|
+
*/
|
|
314
|
+
{"EDGEUISTARTED",
|
|
315
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
316
|
+
*/
|
|
317
|
+
{"EDITORBEFOREINPUT",
|
|
318
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
319
|
+
*/
|
|
320
|
+
{"EDITORINPUT",
|
|
321
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
322
|
+
*/
|
|
323
|
+
{"END", TYPE_BLACK},
|
|
324
|
+
{"ENDED", TYPE_BLACK},
|
|
325
|
+
{"ENDEVENT", TYPE_BLACK},
|
|
326
|
+
{"ENDSTREAMING", TYPE_BLACK},
|
|
327
|
+
{"ENTER", TYPE_BLACK},
|
|
328
|
+
{"ENTERPICTUREINPICTURE", TYPE_BLACK},
|
|
329
|
+
{"ERROR", TYPE_BLACK},
|
|
330
|
+
{"EXIT", TYPE_BLACK},
|
|
331
|
+
{"FENCEDTREECLICK",
|
|
332
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl */
|
|
333
|
+
{"FETCH", TYPE_BLACK},
|
|
334
|
+
{"FINISH", TYPE_BLACK},
|
|
335
|
+
{"FOCUS", TYPE_BLACK},
|
|
336
|
+
{"FOCUSIN", TYPE_BLACK},
|
|
337
|
+
{"FOCUSOUT", TYPE_BLACK},
|
|
338
|
+
{"FORMCHANGE",
|
|
339
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
340
|
+
*/
|
|
341
|
+
{"FORMCHECKBOXSTATECHANGE",
|
|
342
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
343
|
+
*/
|
|
344
|
+
{"FORMDATA", TYPE_BLACK},
|
|
345
|
+
{"FORMINVALID",
|
|
346
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
347
|
+
*/
|
|
348
|
+
{"FORMRADIOSTATECHANGE",
|
|
349
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
350
|
+
*/
|
|
351
|
+
{"FORMRESET",
|
|
352
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
353
|
+
*/
|
|
354
|
+
{"FORMSELECT",
|
|
355
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
356
|
+
*/
|
|
357
|
+
{"FORMSUBMIT",
|
|
358
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
359
|
+
*/
|
|
360
|
+
{"FULLSCREENCHANGE", TYPE_BLACK},
|
|
361
|
+
{"FULLSCREENERROR", TYPE_BLACK},
|
|
362
|
+
{"GAMEPADAXISMOVE",
|
|
363
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
364
|
+
*/
|
|
365
|
+
{"GAMEPADBUTTONDOWN",
|
|
366
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
367
|
+
*/
|
|
368
|
+
{"GAMEPADBUTTONUP",
|
|
369
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
370
|
+
*/
|
|
371
|
+
{"GAMEPADCONNECTED", TYPE_BLACK},
|
|
372
|
+
{"GAMEPADDISCONNECTED", TYPE_BLACK},
|
|
373
|
+
{"GATHERINGSTATECHANGE", TYPE_BLACK},
|
|
374
|
+
{"GESTURECHANGE", TYPE_BLACK},
|
|
375
|
+
{"GESTUREEND", TYPE_BLACK},
|
|
376
|
+
{"GESTURESCROLLEND", TYPE_BLACK},
|
|
377
|
+
{"GESTURESCROLLSTART", TYPE_BLACK},
|
|
378
|
+
{"GESTURESCROLLUPDATE", TYPE_BLACK},
|
|
379
|
+
{"GESTURESTART", TYPE_BLACK},
|
|
380
|
+
{"GESTURETAP", TYPE_BLACK},
|
|
381
|
+
{"GESTURETAPDOWN", TYPE_BLACK},
|
|
382
|
+
{"GOTPOINTERCAPTURE", TYPE_BLACK},
|
|
383
|
+
{"HASHCHANGE", TYPE_BLACK},
|
|
384
|
+
{"ICECANDIDATE", TYPE_BLACK},
|
|
385
|
+
{"ICECANDIDATEERROR", TYPE_BLACK},
|
|
386
|
+
{"ICECONNECTIONSTATECHANGE", TYPE_BLACK},
|
|
387
|
+
{"ICEGATHERINGSTATECHANGE", TYPE_BLACK},
|
|
388
|
+
{"IMAGEABORT",
|
|
389
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
390
|
+
*/
|
|
391
|
+
{"INACTIVE", TYPE_BLACK},
|
|
392
|
+
{"INPUT", TYPE_BLACK},
|
|
393
|
+
{"INPUTSOURCESCHANGE", TYPE_BLACK},
|
|
394
|
+
{"INSTALL", TYPE_BLACK},
|
|
395
|
+
{"INVALID", TYPE_BLACK},
|
|
396
|
+
{"INVOKE", TYPE_BLACK},
|
|
397
|
+
{"KEYDOWN", TYPE_BLACK},
|
|
398
|
+
{"KEYPRESS", TYPE_BLACK},
|
|
399
|
+
{"KEYSTATUSESCHANGE", TYPE_BLACK},
|
|
400
|
+
{"KEYUP", TYPE_BLACK},
|
|
401
|
+
{"LANGUAGECHANGE", TYPE_BLACK},
|
|
402
|
+
{"LEAVEPICTUREINPICTURE", TYPE_BLACK},
|
|
403
|
+
{"LEGACYATTRMODIFIED",
|
|
404
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
405
|
+
*/
|
|
406
|
+
{"LEGACYCHARACTERDATAMODIFIED",
|
|
407
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
408
|
+
*/
|
|
409
|
+
{"LEGACYDOMACTIVATE",
|
|
410
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
411
|
+
*/
|
|
412
|
+
{"LEGACYDOMFOCUSIN",
|
|
413
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
414
|
+
*/
|
|
415
|
+
{"LEGACYDOMFOCUSOUT",
|
|
416
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
417
|
+
*/
|
|
418
|
+
{"LEGACYMOUSELINEORPAGESCROLL",
|
|
419
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
420
|
+
*/
|
|
421
|
+
{"LEGACYMOUSEPIXELSCROLL",
|
|
422
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
423
|
+
*/
|
|
424
|
+
{"LEGACYNODEINSERTED",
|
|
425
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
426
|
+
*/
|
|
427
|
+
{"LEGACYNODEINSERTEDINTODOCUMENT",
|
|
428
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
429
|
+
*/
|
|
430
|
+
{"LEGACYNODEREMOVED",
|
|
431
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
432
|
+
*/
|
|
433
|
+
{"LEGACYNODEREMOVEDFROMDOCUMENT",
|
|
434
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
435
|
+
*/
|
|
436
|
+
{"LEGACYSUBTREEMODIFIED",
|
|
437
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
438
|
+
*/
|
|
439
|
+
{"LEGACYTEXTINPUT",
|
|
440
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
441
|
+
*/
|
|
442
|
+
{"LEVELCHANGE", TYPE_BLACK},
|
|
443
|
+
{"LOAD", TYPE_BLACK},
|
|
444
|
+
{"LOADEDDATA", TYPE_BLACK},
|
|
445
|
+
{"LOADEDMETADATA", TYPE_BLACK},
|
|
446
|
+
{"LOADEND", TYPE_BLACK},
|
|
447
|
+
{"LOADING", TYPE_BLACK},
|
|
448
|
+
{"LOADINGDONE", TYPE_BLACK},
|
|
449
|
+
{"LOADINGERROR", TYPE_BLACK},
|
|
450
|
+
{"LOADSTART", TYPE_BLACK},
|
|
451
|
+
{"LOSTPOINTERCAPTURE", TYPE_BLACK},
|
|
452
|
+
{"MAGNIFYGESTURE",
|
|
453
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
454
|
+
*/
|
|
455
|
+
{"MAGNIFYGESTURESTART",
|
|
456
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
457
|
+
*/
|
|
458
|
+
{"MAGNIFYGESTUREUPDATE",
|
|
459
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
460
|
+
*/
|
|
461
|
+
{"MARK", TYPE_BLACK},
|
|
462
|
+
{"MEDIARECORDERDATAAVAILABLE",
|
|
463
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
464
|
+
*/
|
|
465
|
+
{"MEDIARECORDERSTOP",
|
|
466
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
467
|
+
*/
|
|
468
|
+
{"MEDIARECORDERWARNING",
|
|
469
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
470
|
+
*/
|
|
471
|
+
{"MERCHANTVALIDATION", TYPE_BLACK},
|
|
472
|
+
{"MESSAGE", TYPE_BLACK},
|
|
473
|
+
{"MESSAGEERROR", TYPE_BLACK},
|
|
474
|
+
{"MOUSEDOUBLECLICK",
|
|
475
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
476
|
+
*/
|
|
477
|
+
{"MOUSEDOWN", TYPE_BLACK},
|
|
478
|
+
{"MOUSEENTER", TYPE_BLACK},
|
|
479
|
+
{"MOUSEEXPLOREBYTOUCH",
|
|
480
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
481
|
+
*/
|
|
482
|
+
{"MOUSEHITTEST",
|
|
483
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
484
|
+
*/
|
|
485
|
+
{"MOUSELEAVE", TYPE_BLACK},
|
|
486
|
+
{"MOUSELONGTAP",
|
|
487
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
488
|
+
*/
|
|
489
|
+
{"MOUSEMOVE", TYPE_BLACK},
|
|
490
|
+
{"MOUSEOUT", TYPE_BLACK},
|
|
491
|
+
{"MOUSEOVER", TYPE_BLACK},
|
|
492
|
+
{"MOUSEUP", TYPE_BLACK},
|
|
493
|
+
{"MOUSEWHEEL", TYPE_BLACK},
|
|
494
|
+
{"MOZFULLSCREENCHANGE",
|
|
495
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
496
|
+
*/
|
|
497
|
+
{"MOZFULLSCREENERROR",
|
|
498
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
499
|
+
*/
|
|
500
|
+
{"MOZPOINTERLOCKCHANGE",
|
|
501
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
502
|
+
*/
|
|
503
|
+
{"MOZPOINTERLOCKERROR",
|
|
504
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
505
|
+
*/
|
|
506
|
+
{"MOZVISUALRESIZE",
|
|
507
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
508
|
+
*/
|
|
509
|
+
{"MOZVISUALSCROLL",
|
|
510
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
511
|
+
*/
|
|
512
|
+
{"MUTE", TYPE_BLACK},
|
|
513
|
+
{"NAVIGATE", TYPE_BLACK},
|
|
514
|
+
{"NAVIGATEERROR", TYPE_BLACK},
|
|
515
|
+
{"NAVIGATESUCCESS", TYPE_BLACK},
|
|
516
|
+
{"NEGOTIATIONNEEDED", TYPE_BLACK},
|
|
517
|
+
{"NEXTTRACK", TYPE_BLACK},
|
|
518
|
+
{"NOMATCH", TYPE_BLACK},
|
|
519
|
+
{"NOTIFICATIONCLICK", TYPE_BLACK},
|
|
520
|
+
{"NOTIFICATIONCLOSE", TYPE_BLACK},
|
|
521
|
+
{"NOUPDATE", TYPE_BLACK},
|
|
522
|
+
{"OBSOLETE", TYPE_BLACK},
|
|
523
|
+
{"OFFLINE", TYPE_BLACK},
|
|
524
|
+
{"ONLINE", TYPE_BLACK},
|
|
525
|
+
{"OPEN", TYPE_BLACK},
|
|
526
|
+
{"ORIENTATIONCHANGE", TYPE_BLACK},
|
|
527
|
+
{"OVERFLOWCHANGED", TYPE_BLACK},
|
|
528
|
+
{"OVERSCROLL", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl */
|
|
529
|
+
{"PAGEHIDE", TYPE_BLACK},
|
|
530
|
+
{"PAGEREVEAL", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
531
|
+
{"PAGESHOW", TYPE_BLACK},
|
|
532
|
+
{"PAGESWAP", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
533
|
+
{"PASTE", TYPE_BLACK},
|
|
534
|
+
{"PAUSE", TYPE_BLACK},
|
|
535
|
+
{"PAYERDETAILCHANGE", TYPE_BLACK},
|
|
536
|
+
{"PAYMENTAUTHORIZED", TYPE_BLACK},
|
|
537
|
+
{"PAYMENTMETHODCHANGE", TYPE_BLACK},
|
|
538
|
+
{"PAYMENTMETHODSELECTED", TYPE_BLACK},
|
|
539
|
+
{"PLAY", TYPE_BLACK},
|
|
540
|
+
{"PLAYING", TYPE_BLACK},
|
|
541
|
+
{"POINTERAUXCLICK",
|
|
542
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
543
|
+
*/
|
|
544
|
+
{"POINTERCANCEL", TYPE_BLACK},
|
|
545
|
+
{"POINTERCLICK",
|
|
546
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
547
|
+
*/
|
|
548
|
+
{"POINTERDOWN", TYPE_BLACK},
|
|
549
|
+
{"POINTERENTER", TYPE_BLACK},
|
|
550
|
+
{"POINTERGOTCAPTURE",
|
|
551
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
552
|
+
*/
|
|
553
|
+
{"POINTERLEAVE", TYPE_BLACK},
|
|
554
|
+
{"POINTERLOCKCHANGE", TYPE_BLACK},
|
|
555
|
+
{"POINTERLOCKERROR", TYPE_BLACK},
|
|
556
|
+
{"POINTERLOSTCAPTURE",
|
|
557
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
558
|
+
*/
|
|
559
|
+
{"POINTERMOVE", TYPE_BLACK},
|
|
560
|
+
{"POINTEROUT", TYPE_BLACK},
|
|
561
|
+
{"POINTEROVER", TYPE_BLACK},
|
|
562
|
+
{"POINTERRAWUPDATE",
|
|
563
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, Firefox:
|
|
564
|
+
EventNameList.h */
|
|
565
|
+
{"POINTERUP", TYPE_BLACK},
|
|
566
|
+
{"POPSTATE", TYPE_BLACK},
|
|
567
|
+
{"PRESSTAPGESTURE",
|
|
568
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
569
|
+
*/
|
|
570
|
+
{"PREVIOUSTRACK", TYPE_BLACK},
|
|
571
|
+
{"PROPERTYCHANGE", TYPE_BLACK},
|
|
572
|
+
{"PROCESSORERROR", TYPE_BLACK},
|
|
573
|
+
{"PROGRESS", TYPE_BLACK},
|
|
574
|
+
{"PUSH", TYPE_BLACK},
|
|
575
|
+
{"PUSHNOTIFICATION", TYPE_BLACK},
|
|
576
|
+
{"PUSHSUBSCRIPTIONCHANGE", TYPE_BLACK},
|
|
577
|
+
{"QUALITYCHANGE", TYPE_BLACK},
|
|
578
|
+
{"RATECHANGE", TYPE_BLACK},
|
|
579
|
+
{"READYSTATECHANGE", TYPE_BLACK},
|
|
580
|
+
{"REDRAW", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
581
|
+
{"REJECTIONHANDLED", TYPE_BLACK},
|
|
582
|
+
{"RELEASE", TYPE_BLACK},
|
|
583
|
+
{"REMOVE", TYPE_BLACK},
|
|
584
|
+
{"REMOVESOURCEBUFFER", TYPE_BLACK},
|
|
585
|
+
{"REMOVESTREAM", TYPE_BLACK},
|
|
586
|
+
{"REMOVETRACK", TYPE_BLACK},
|
|
587
|
+
{"REPEAT", TYPE_BLACK}, /* WebKit: EventNames.json - SVG animation */
|
|
588
|
+
{"REPEATEVENT", TYPE_BLACK}, /* WebKit: EventNames.json, Firefox:
|
|
589
|
+
EventNameList.h - SVG animation */
|
|
590
|
+
{"RESET", TYPE_BLACK},
|
|
591
|
+
{"RESIZE", TYPE_BLACK},
|
|
592
|
+
{"RESOURCETIMINGBUFFERFULL", TYPE_BLACK},
|
|
593
|
+
{"RESULT", TYPE_BLACK},
|
|
594
|
+
{"RESUME", TYPE_BLACK},
|
|
595
|
+
{"ROTATEGESTURE",
|
|
596
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
597
|
+
*/
|
|
598
|
+
{"ROTATEGESTURESTART",
|
|
599
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
600
|
+
*/
|
|
601
|
+
{"ROTATEGESTUREUPDATE",
|
|
602
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
603
|
+
*/
|
|
604
|
+
{"RTCTRANSFORM", TYPE_BLACK},
|
|
605
|
+
{"SCROLL", TYPE_BLACK},
|
|
606
|
+
{"SCROLLEDAREACHANGED",
|
|
607
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
608
|
+
*/
|
|
609
|
+
{"SCROLLEND",
|
|
610
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl, WebKit:
|
|
611
|
+
EventNames.json, Firefox: EventNameList.h */
|
|
612
|
+
{"SCROLLPORTOVERFLOW",
|
|
613
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
614
|
+
*/
|
|
615
|
+
{"SCROLLPORTUNDERFLOW",
|
|
616
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
617
|
+
*/
|
|
618
|
+
{"SCROLLSNAPCHANGE", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl
|
|
619
|
+
- CSS Scroll Snap */
|
|
620
|
+
{"SCROLLSNAPCHANGING",
|
|
621
|
+
TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl - CSS Scroll Snap
|
|
622
|
+
*/
|
|
623
|
+
{"SEARCH", TYPE_BLACK},
|
|
624
|
+
{"SECURITYPOLICYVIOLATION", TYPE_BLACK},
|
|
625
|
+
{"SEEKED", TYPE_BLACK},
|
|
626
|
+
{"SEEKING", TYPE_BLACK},
|
|
627
|
+
{"SELECT", TYPE_BLACK},
|
|
628
|
+
{"SELECTEDCANDIDATEPAIRCHANGE", TYPE_BLACK},
|
|
629
|
+
{"SELECTEND", TYPE_BLACK},
|
|
630
|
+
{"SELECTIONCHANGE", TYPE_BLACK},
|
|
631
|
+
{"SELECTSTART", TYPE_BLACK},
|
|
632
|
+
{"SHIPPINGADDRESSCHANGE", TYPE_BLACK},
|
|
633
|
+
{"SHIPPINGCONTACTSELECTED", TYPE_BLACK},
|
|
634
|
+
{"SHIPPINGMETHODSELECTED", TYPE_BLACK},
|
|
635
|
+
{"SHIPPINGOPTIONCHANGE", TYPE_BLACK},
|
|
636
|
+
{"SHOW", TYPE_BLACK},
|
|
637
|
+
{"SIGNALINGSTATECHANGE", TYPE_BLACK},
|
|
638
|
+
{"SLOTCHANGE", TYPE_BLACK},
|
|
639
|
+
{"SMILBEGINEVENT",
|
|
640
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - SVG/SMIL */
|
|
641
|
+
{"SMILENDEVENT",
|
|
642
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - SVG/SMIL */
|
|
643
|
+
{"SMILREPEATEVENT",
|
|
644
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - SVG/SMIL */
|
|
645
|
+
{"SORT", TYPE_BLACK}, /* Chromium: Blink GlobalEventHandlers.idl */
|
|
646
|
+
{"SOUNDEND", TYPE_BLACK},
|
|
647
|
+
{"SOUNDSTART", TYPE_BLACK},
|
|
648
|
+
{"SOURCECLOSE", TYPE_BLACK},
|
|
649
|
+
{"SOURCEENDED", TYPE_BLACK},
|
|
650
|
+
{"SOURCEOPEN", TYPE_BLACK},
|
|
651
|
+
{"SPEECHEND", TYPE_BLACK},
|
|
652
|
+
{"SPEECHSTART", TYPE_BLACK},
|
|
653
|
+
{"SQUEEZE", TYPE_BLACK},
|
|
654
|
+
{"SQUEEZEEND", TYPE_BLACK},
|
|
655
|
+
{"SQUEEZESTART", TYPE_BLACK},
|
|
656
|
+
{"STALLED", TYPE_BLACK},
|
|
657
|
+
{"START", TYPE_BLACK},
|
|
658
|
+
{"STARTED", TYPE_BLACK},
|
|
659
|
+
{"STARTSTREAMING", TYPE_BLACK},
|
|
660
|
+
{"STATECHANGE", TYPE_BLACK},
|
|
661
|
+
{"STOP", TYPE_BLACK},
|
|
662
|
+
{"STORAGE", TYPE_BLACK},
|
|
663
|
+
{"SUBMIT", TYPE_BLACK},
|
|
664
|
+
{"SVGLOAD",
|
|
665
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
666
|
+
*/
|
|
667
|
+
{"SVGSCROLL",
|
|
668
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
669
|
+
*/
|
|
670
|
+
{"SWIPEGESTURE",
|
|
671
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
672
|
+
*/
|
|
673
|
+
{"SWIPEGESTUREEND",
|
|
674
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
675
|
+
*/
|
|
676
|
+
{"SWIPEGESTUREMAYSTART",
|
|
677
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
678
|
+
*/
|
|
679
|
+
{"SWIPEGESTURESTART",
|
|
680
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
681
|
+
*/
|
|
682
|
+
{"SWIPEGESTUREUPDATE",
|
|
683
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
684
|
+
*/
|
|
685
|
+
{"SUCCESS", TYPE_BLACK},
|
|
686
|
+
{"SUSPEND", TYPE_BLACK},
|
|
687
|
+
{"TAPGESTURE",
|
|
688
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
689
|
+
*/
|
|
690
|
+
{"TEXTINPUT", TYPE_BLACK},
|
|
691
|
+
{"TIMEOUT", TYPE_BLACK},
|
|
692
|
+
{"TIMEUPDATE", TYPE_BLACK},
|
|
693
|
+
{"TOGGLE", TYPE_BLACK},
|
|
694
|
+
{"TONECHANGE", TYPE_BLACK},
|
|
695
|
+
{"TOUCHCANCEL", TYPE_BLACK},
|
|
696
|
+
{"TOUCHEND", TYPE_BLACK},
|
|
697
|
+
{"TOUCHFORCECHANGE", TYPE_BLACK},
|
|
698
|
+
{"TOUCHMOVE", TYPE_BLACK},
|
|
699
|
+
{"TOUCHSTART", TYPE_BLACK},
|
|
700
|
+
{"TRACK", TYPE_BLACK},
|
|
701
|
+
{"TRANSITIONCANCEL", TYPE_BLACK},
|
|
702
|
+
{"TRANSITIONEND", TYPE_BLACK},
|
|
703
|
+
{"TRANSITIONRUN", TYPE_BLACK},
|
|
704
|
+
{"TRANSITIONSTART", TYPE_BLACK},
|
|
705
|
+
{"UNCAPTUREDERROR", TYPE_BLACK},
|
|
706
|
+
{"UNHANDLEDREJECTION", TYPE_BLACK},
|
|
707
|
+
{"UNIDENTIFIEDEVENT",
|
|
708
|
+
TYPE_BLACK}, /* Firefox: mozilla-firefox/firefox/dom/events/EventNameList.h
|
|
709
|
+
*/
|
|
710
|
+
{"UNLOAD", TYPE_BLACK},
|
|
711
|
+
{"UNMUTE", TYPE_BLACK},
|
|
712
|
+
{"USERPROXIMITY",
|
|
713
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - deprecated
|
|
714
|
+
*/
|
|
715
|
+
{"UPDATE", TYPE_BLACK},
|
|
716
|
+
{"UPDATEEND", TYPE_BLACK},
|
|
717
|
+
{"UPDATEFOUND", TYPE_BLACK},
|
|
718
|
+
{"UPDATEREADY", TYPE_BLACK},
|
|
719
|
+
{"UPDATESTART", TYPE_BLACK},
|
|
720
|
+
{"UPGRADENEEDED", TYPE_BLACK},
|
|
721
|
+
{"VALIDATEMERCHANT", TYPE_BLACK},
|
|
722
|
+
{"VERSIONCHANGE", TYPE_BLACK},
|
|
723
|
+
{"VISIBILITYCHANGE", TYPE_BLACK},
|
|
724
|
+
{"VOICESCHANGED", TYPE_BLACK},
|
|
725
|
+
{"VOLUMECHANGE", TYPE_BLACK},
|
|
726
|
+
{"VRDISPLAYACTIVATE",
|
|
727
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - WebVR
|
|
728
|
+
deprecated */
|
|
729
|
+
{"VRDISPLAYCONNECT",
|
|
730
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - WebVR
|
|
731
|
+
deprecated */
|
|
732
|
+
{"VRDISPLAYDEACTIVATE",
|
|
733
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - WebVR
|
|
734
|
+
deprecated */
|
|
735
|
+
{"VRDISPLAYDISCONNECT",
|
|
736
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - WebVR
|
|
737
|
+
deprecated */
|
|
738
|
+
{"VRDISPLAYPRESENTCHANGE",
|
|
739
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - WebVR
|
|
740
|
+
deprecated */
|
|
741
|
+
{"WAITING", TYPE_BLACK},
|
|
742
|
+
{"WAITINGFORKEY", TYPE_BLACK},
|
|
743
|
+
{"WEBGLCONTEXTCREATIONERROR", TYPE_BLACK},
|
|
744
|
+
{"WEBGLCONTEXTLOST", TYPE_BLACK},
|
|
745
|
+
{"WEBGLCONTEXTRESTORED", TYPE_BLACK},
|
|
746
|
+
{"WEBKITANIMATIONEND", TYPE_BLACK},
|
|
747
|
+
{"WEBKITANIMATIONITERATION", TYPE_BLACK},
|
|
748
|
+
{"WEBKITANIMATIONSTART", TYPE_BLACK},
|
|
749
|
+
{"WEBKITASSOCIATEFORMCONTROLS", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
750
|
+
{"WEBKITAUTOFILLREQUEST", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
751
|
+
{"WEBKITBEFORETEXTINSERTED", TYPE_BLACK},
|
|
752
|
+
{"WEBKITBEGINFULLSCREEN", TYPE_BLACK},
|
|
753
|
+
{"WEBKITCURRENTPLAYBACKTARGETISWIRELESSCHANGED", TYPE_BLACK},
|
|
754
|
+
{"WEBKITENDFULLSCREEN", TYPE_BLACK},
|
|
755
|
+
{"WEBKITFULLSCREENCHANGE", TYPE_BLACK},
|
|
756
|
+
{"WEBKITFULLSCREENERROR", TYPE_BLACK},
|
|
757
|
+
{"WEBKITKEYADDED", TYPE_BLACK},
|
|
758
|
+
{"WEBKITKEYERROR", TYPE_BLACK},
|
|
759
|
+
{"WEBKITKEYMESSAGE", TYPE_BLACK},
|
|
760
|
+
{"WEBKITMEDIASESSIONMETADATACHANGED",
|
|
761
|
+
TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
762
|
+
{"WEBKITMOUSEFORCECHANGED", TYPE_BLACK},
|
|
763
|
+
{"WEBKITMOUSEFORCEDOWN", TYPE_BLACK},
|
|
764
|
+
{"WEBKITMOUSEFORCEUP", TYPE_BLACK},
|
|
765
|
+
{"WEBKITMOUSEFORCEWILLBEGIN", TYPE_BLACK},
|
|
766
|
+
{"WEBKITNEEDKEY", TYPE_BLACK},
|
|
767
|
+
{"WEBKITNETWORKINFOCHANGE", TYPE_BLACK},
|
|
768
|
+
{"WEBKITPLAYBACKTARGETAVAILABILITYCHANGED", TYPE_BLACK},
|
|
769
|
+
{"WEBKITPRESENTATIONMODECHANGED", TYPE_BLACK},
|
|
770
|
+
{"WEBKITREMOVESOURCEBUFFER", TYPE_BLACK},
|
|
771
|
+
{"WEBKITSHADOWROOTATTACHED", TYPE_BLACK}, /* WebKit: EventNames.json */
|
|
772
|
+
{"WEBKITSOURCECLOSE", TYPE_BLACK},
|
|
773
|
+
{"WEBKITSOURCEENDED", TYPE_BLACK},
|
|
774
|
+
{"WEBKITSOURCEOPEN", TYPE_BLACK},
|
|
775
|
+
{"WEBKITTRANSITIONEND", TYPE_BLACK},
|
|
776
|
+
{"WHEEL", TYPE_BLACK},
|
|
777
|
+
{"WRITE", TYPE_BLACK},
|
|
778
|
+
{"WRITEEND", TYPE_BLACK},
|
|
779
|
+
{"WRITESTART", TYPE_BLACK},
|
|
780
|
+
{"XULBROADCAST",
|
|
781
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
782
|
+
specific */
|
|
783
|
+
{"XULCOMMANDUPDATE",
|
|
784
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
785
|
+
specific */
|
|
786
|
+
{"XULPOPUPHIDDEN",
|
|
787
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
788
|
+
specific */
|
|
789
|
+
{"XULPOPUPHIDING",
|
|
790
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
791
|
+
specific */
|
|
792
|
+
{"XULPOPUPSHOWING",
|
|
793
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
794
|
+
specific */
|
|
795
|
+
{"XULPOPUPSHOWN",
|
|
796
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
797
|
+
specific */
|
|
798
|
+
{"XULSYSTEMSTATUSBARCLICK",
|
|
799
|
+
TYPE_BLACK}, /* Firefox: gecko-dev/dom/events/EventNameList.h - XUL
|
|
800
|
+
specific */
|
|
801
|
+
{"ZOOM", TYPE_BLACK},
|
|
802
|
+
{NULL, TYPE_NONE}};
|
|
803
|
+
|
|
804
|
+
/*
|
|
805
|
+
* view-source:
|
|
806
|
+
* data:
|
|
807
|
+
* javascript:
|
|
808
|
+
*/
|
|
809
|
+
static stringtype_t BLACKATTR[] = {
|
|
810
|
+
{"ACTION", TYPE_ATTR_URL}, /* form */
|
|
811
|
+
{"ATTRIBUTENAME",
|
|
812
|
+
TYPE_ATTR_INDIRECT}, /* SVG allow indirection of attribute names */
|
|
813
|
+
{"BY", TYPE_ATTR_URL}, /* SVG */
|
|
814
|
+
{"BACKGROUND", TYPE_ATTR_URL}, /* IE6, O11 */
|
|
815
|
+
{"DATAFORMATAS", TYPE_BLACK}, /* IE */
|
|
816
|
+
{"DATASRC", TYPE_BLACK}, /* IE */
|
|
817
|
+
{"DYNSRC", TYPE_ATTR_URL}, /* Obsolete img attribute */
|
|
818
|
+
{"FILTER", TYPE_STYLE}, /* Opera, SVG inline style */
|
|
819
|
+
{"FORMACTION", TYPE_ATTR_URL}, /* HTML 5 */
|
|
820
|
+
{"FOLDER", TYPE_ATTR_URL}, /* Only on A tags, IE-only */
|
|
821
|
+
{"FROM", TYPE_ATTR_URL}, /* SVG */
|
|
822
|
+
{"HANDLER", TYPE_ATTR_URL}, /* SVG Tiny, Opera */
|
|
823
|
+
{"HREF", TYPE_ATTR_URL},
|
|
824
|
+
{"LOWSRC", TYPE_ATTR_URL}, /* Obsolete img attribute */
|
|
825
|
+
{"POSTER", TYPE_ATTR_URL}, /* Opera 10,11 */
|
|
826
|
+
{"SRC", TYPE_ATTR_URL},
|
|
827
|
+
{"STYLE", TYPE_STYLE},
|
|
828
|
+
{"TO", TYPE_ATTR_URL}, /* SVG */
|
|
829
|
+
{"VALUES", TYPE_ATTR_URL}, /* SVG */
|
|
830
|
+
{"XLINK:HREF", TYPE_ATTR_URL},
|
|
831
|
+
{NULL, TYPE_NONE}};
|
|
832
|
+
|
|
833
|
+
/* xmlns */
|
|
834
|
+
/* `xml-stylesheet` > <eval>, <if expr=> */
|
|
835
|
+
|
|
836
|
+
/*
|
|
837
|
+
static const char* BLACKATTR[] = {
|
|
838
|
+
"ATTRIBUTENAME",
|
|
839
|
+
"BACKGROUND",
|
|
840
|
+
"DATAFORMATAS",
|
|
841
|
+
"HREF",
|
|
842
|
+
"SCROLL",
|
|
843
|
+
"SRC",
|
|
844
|
+
"STYLE",
|
|
845
|
+
"SRCDOC",
|
|
846
|
+
NULL
|
|
847
|
+
};
|
|
848
|
+
*/
|
|
849
|
+
|
|
850
|
+
static const char *BLACKTAG[] = {
|
|
851
|
+
"APPLET",
|
|
852
|
+
/* , "AUDIO" */
|
|
853
|
+
"BASE", "COMMENT", /* IE http://html5sec.org/#38 */
|
|
854
|
+
"EMBED",
|
|
855
|
+
/* , "FORM" */
|
|
856
|
+
"FRAME", "FRAMESET", "HANDLER", /* Opera SVG, effectively a script tag */
|
|
857
|
+
"IFRAME", "IMPORT", "ISINDEX", "LINK", "LISTENER",
|
|
858
|
+
/* , "MARQUEE" */
|
|
859
|
+
"META", "NOSCRIPT", "OBJECT", "SCRIPT", "STYLE",
|
|
860
|
+
/* , "VIDEO" */
|
|
861
|
+
"VMLFRAME", "XML", "XSS", NULL};
|
|
862
|
+
|
|
863
|
+
static int cstrcasecmp_with_null(const char *a, const char *b, size_t n) {
|
|
864
|
+
unsigned int ai = 0, bi = 0;
|
|
865
|
+
char ca;
|
|
866
|
+
char cb;
|
|
867
|
+
/* printf("Comparing to %s %.*s\n", a, (int)n, b); */
|
|
868
|
+
while (n-- > 0) {
|
|
869
|
+
cb = b[bi++];
|
|
870
|
+
if (cb == '\0') {
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
ca = a[ai++];
|
|
875
|
+
|
|
876
|
+
if (cb >= 'a' && cb <= 'z') {
|
|
877
|
+
cb -= 0x20;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/* printf("Comparing %c vs %c with %d left\n", ca, cb, (int)n); */
|
|
881
|
+
if (ca != cb) {
|
|
882
|
+
return 1;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
ca = a[ai++];
|
|
886
|
+
|
|
887
|
+
if (ca == '\0') {
|
|
888
|
+
/* printf(" MATCH \n"); */
|
|
889
|
+
return 0;
|
|
890
|
+
} else {
|
|
891
|
+
return 1;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/*
|
|
896
|
+
* Does an HTML encoded binary string (const char*, length) start with
|
|
897
|
+
* a all uppercase c-string (null terminated), case insensitive!
|
|
898
|
+
*
|
|
899
|
+
* also ignore any embedded nulls in the HTML string!
|
|
900
|
+
*
|
|
901
|
+
* @param a - the prefix to check for
|
|
902
|
+
* @param b - the string to check
|
|
903
|
+
* @param n - the length of the string to check
|
|
904
|
+
* @return 1 if the string starts with the prefix, 0 otherwise
|
|
905
|
+
*/
|
|
906
|
+
static int htmlencode_startswith(const char *a, const char *b, size_t n) {
|
|
907
|
+
size_t consumed;
|
|
908
|
+
int cb;
|
|
909
|
+
int first = 1;
|
|
910
|
+
/* printf("Comparing %s with %.*s\n", a,(int)n,b); */
|
|
911
|
+
while (n > 0) {
|
|
912
|
+
if (*a == 0) {
|
|
913
|
+
/* printf("Match EOL!\n"); */
|
|
914
|
+
return 1;
|
|
915
|
+
}
|
|
916
|
+
cb = html_decode_char_at(b, n, &consumed);
|
|
917
|
+
b += consumed;
|
|
918
|
+
n -= consumed;
|
|
919
|
+
|
|
920
|
+
if (first && cb <= 32) {
|
|
921
|
+
/* ignore all leading whitespace and control characters */
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
first = 0;
|
|
925
|
+
|
|
926
|
+
if (cb == 0) {
|
|
927
|
+
/* always ignore null characters in user input */
|
|
928
|
+
continue;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
if (cb == 10) {
|
|
932
|
+
/* always ignore vertical tab characters in user input */
|
|
933
|
+
/* who allows this?? */
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
if (cb >= 'a' && cb <= 'z') {
|
|
938
|
+
/* upcase */
|
|
939
|
+
cb -= 0x20;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
if (*a != (char)cb) {
|
|
943
|
+
/* printf(" %c != %c\n", *a, cb); */
|
|
944
|
+
/* mismatch */
|
|
945
|
+
return 0;
|
|
946
|
+
}
|
|
947
|
+
a++;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
return (*a == 0) ? 1 : 0;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
static int is_black_tag(const char *s, size_t len) {
|
|
954
|
+
const char **black;
|
|
955
|
+
|
|
956
|
+
if (len < 3) {
|
|
957
|
+
return 0;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
black = BLACKTAG;
|
|
961
|
+
while (*black != NULL) {
|
|
962
|
+
if (cstrcasecmp_with_null(*black, s, len) == 0) {
|
|
963
|
+
/* printf("Got black tag %s\n", *black); */
|
|
964
|
+
return 1;
|
|
965
|
+
}
|
|
966
|
+
black += 1;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
/* anything SVG related */
|
|
970
|
+
if ((s[0] == 's' || s[0] == 'S') && (s[1] == 'v' || s[1] == 'V') &&
|
|
971
|
+
(s[2] == 'g' || s[2] == 'G')) {
|
|
972
|
+
/* printf("Got SVG tag \n"); */
|
|
973
|
+
return 1;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/* Anything XSL(t) related */
|
|
977
|
+
if ((s[0] == 'x' || s[0] == 'X') && (s[1] == 's' || s[1] == 'S') &&
|
|
978
|
+
(s[2] == 'l' || s[2] == 'L')) {
|
|
979
|
+
/* printf("Got XSL tag\n"); */
|
|
980
|
+
return 1;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return 0;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
static attribute_t is_black_attr(const char *s, size_t len) {
|
|
987
|
+
stringtype_t *black;
|
|
988
|
+
|
|
989
|
+
if (len < 2) {
|
|
990
|
+
return TYPE_NONE;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
if (len >= 5) {
|
|
994
|
+
|
|
995
|
+
/* JavaScript on.* event handlers */
|
|
996
|
+
if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'n' || s[1] == 'N')) {
|
|
997
|
+
black = BLACKATTREVENT;
|
|
998
|
+
const char *s_without_on =
|
|
999
|
+
&s[2]; // start comparing from the third char
|
|
1000
|
+
size_t s_without_on_len = len - 2; // temporary length variable
|
|
1001
|
+
while (black->name != NULL) {
|
|
1002
|
+
size_t black_name_len = strlen(black->name);
|
|
1003
|
+
// determine the maximum length to compare
|
|
1004
|
+
size_t max_len = (s_without_on_len < black_name_len)
|
|
1005
|
+
? s_without_on_len
|
|
1006
|
+
: black_name_len;
|
|
1007
|
+
if (cstrcasecmp_with_null(black->name, s_without_on, max_len) ==
|
|
1008
|
+
0) {
|
|
1009
|
+
/* printf("Got banned attribute name %s\n", black->name); */
|
|
1010
|
+
return black->atype;
|
|
1011
|
+
}
|
|
1012
|
+
black += 1;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/* XMLNS can be used to create arbitrary tags */
|
|
1017
|
+
if (cstrcasecmp_with_null("XMLNS", s, 5) == 0 ||
|
|
1018
|
+
cstrcasecmp_with_null("XLINK", s, 5) == 0) {
|
|
1019
|
+
/* printf("Got XMLNS and XLINK tags\n"); */
|
|
1020
|
+
return TYPE_BLACK;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
black = BLACKATTR;
|
|
1025
|
+
while (black->name != NULL) {
|
|
1026
|
+
if (cstrcasecmp_with_null(black->name, s, len) == 0) {
|
|
1027
|
+
/* printf("Got banned attribute name %s\n", black->name); */
|
|
1028
|
+
return black->atype;
|
|
1029
|
+
}
|
|
1030
|
+
black += 1;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
return TYPE_NONE;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
static int is_black_url(const char *s, size_t len) {
|
|
1037
|
+
|
|
1038
|
+
static const char *data_url = "DATA";
|
|
1039
|
+
static const char *viewsource_url = "VIEW-SOURCE";
|
|
1040
|
+
|
|
1041
|
+
/* obsolete but interesting signal */
|
|
1042
|
+
static const char *vbscript_url = "VBSCRIPT";
|
|
1043
|
+
|
|
1044
|
+
/* covers JAVA, JAVASCRIPT, + colon */
|
|
1045
|
+
static const char *javascript_url = "JAVA";
|
|
1046
|
+
|
|
1047
|
+
/* skip whitespace */
|
|
1048
|
+
while (len > 0 && (*s <= 32 || *s >= 127)) {
|
|
1049
|
+
/*
|
|
1050
|
+
* HEY: this is a signed character.
|
|
1051
|
+
* We are intentionally skipping high-bit characters too
|
|
1052
|
+
* since they are not ASCII, and Opera sometimes uses UTF-8 whitespace.
|
|
1053
|
+
*
|
|
1054
|
+
* Also in EUC-JP some of the high bytes are just ignored.
|
|
1055
|
+
*/
|
|
1056
|
+
++s;
|
|
1057
|
+
--len;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
if (htmlencode_startswith(data_url, s, len)) {
|
|
1061
|
+
return 1;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (htmlencode_startswith(viewsource_url, s, len)) {
|
|
1065
|
+
return 1;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
if (htmlencode_startswith(javascript_url, s, len)) {
|
|
1069
|
+
return 1;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
if (htmlencode_startswith(vbscript_url, s, len)) {
|
|
1073
|
+
return 1;
|
|
1074
|
+
}
|
|
1075
|
+
return 0;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
injection_result_t libinjection_is_xss(const char *s, size_t len, int flags) {
|
|
1079
|
+
h5_state_t h5;
|
|
1080
|
+
attribute_t attr = TYPE_NONE;
|
|
1081
|
+
injection_result_t parser_result;
|
|
1082
|
+
|
|
1083
|
+
libinjection_h5_init(&h5, s, len, (enum html5_flags)flags);
|
|
1084
|
+
while ((parser_result = libinjection_h5_next(&h5)) ==
|
|
1085
|
+
LIBINJECTION_RESULT_TRUE) {
|
|
1086
|
+
if (h5.token_type != ATTR_VALUE) {
|
|
1087
|
+
attr = TYPE_NONE;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (h5.token_type == DOCTYPE) {
|
|
1091
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1092
|
+
} else if (h5.token_type == TAG_NAME_OPEN) {
|
|
1093
|
+
if (is_black_tag(h5.token_start, h5.token_len)) {
|
|
1094
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1095
|
+
}
|
|
1096
|
+
} else if (h5.token_type == ATTR_NAME) {
|
|
1097
|
+
attr = is_black_attr(h5.token_start, h5.token_len);
|
|
1098
|
+
} else if (h5.token_type == ATTR_VALUE) {
|
|
1099
|
+
/*
|
|
1100
|
+
* IE6,7,8 parsing works a bit differently so
|
|
1101
|
+
* a whole <script> or other black tag might be hiding
|
|
1102
|
+
* inside an attribute value under HTML 5 parsing
|
|
1103
|
+
* See http://html5sec.org/#102
|
|
1104
|
+
* to avoid doing a full reparse of the value, just
|
|
1105
|
+
* look for "<". This probably need adjusting to
|
|
1106
|
+
* handle escaped characters
|
|
1107
|
+
*/
|
|
1108
|
+
/*
|
|
1109
|
+
if (memchr(h5.token_start, '<', h5.token_len) != NULL) {
|
|
1110
|
+
return 1;
|
|
1111
|
+
}
|
|
1112
|
+
*/
|
|
1113
|
+
|
|
1114
|
+
switch (attr) {
|
|
1115
|
+
case TYPE_NONE:
|
|
1116
|
+
break;
|
|
1117
|
+
case TYPE_BLACK:
|
|
1118
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1119
|
+
case TYPE_ATTR_URL:
|
|
1120
|
+
if (is_black_url(h5.token_start, h5.token_len)) {
|
|
1121
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1122
|
+
}
|
|
1123
|
+
break;
|
|
1124
|
+
case TYPE_STYLE:
|
|
1125
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1126
|
+
case TYPE_ATTR_INDIRECT:
|
|
1127
|
+
/* an attribute name is specified in a _value_ */
|
|
1128
|
+
if (is_black_attr(h5.token_start, h5.token_len)) {
|
|
1129
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1130
|
+
}
|
|
1131
|
+
break;
|
|
1132
|
+
}
|
|
1133
|
+
attr = TYPE_NONE;
|
|
1134
|
+
} else if (h5.token_type == TAG_COMMENT) {
|
|
1135
|
+
/* IE uses a "`" as a tag ending char */
|
|
1136
|
+
if (memchr(h5.token_start, '`', h5.token_len) != NULL) {
|
|
1137
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/* IE conditional comment */
|
|
1141
|
+
if (h5.token_len > 3) {
|
|
1142
|
+
if (h5.token_start[0] == '[' &&
|
|
1143
|
+
(h5.token_start[1] == 'i' || h5.token_start[1] == 'I') &&
|
|
1144
|
+
(h5.token_start[2] == 'f' || h5.token_start[2] == 'F')) {
|
|
1145
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1146
|
+
}
|
|
1147
|
+
if ((h5.token_start[0] == 'x' || h5.token_start[0] == 'X') &&
|
|
1148
|
+
(h5.token_start[1] == 'm' || h5.token_start[1] == 'M') &&
|
|
1149
|
+
(h5.token_start[2] == 'l' || h5.token_start[2] == 'L')) {
|
|
1150
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
if (h5.token_len > 5) {
|
|
1155
|
+
/* IE <?import pseudo-tag */
|
|
1156
|
+
if (cstrcasecmp_with_null("IMPORT", h5.token_start, 6) == 0) {
|
|
1157
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/* XML Entity definition */
|
|
1161
|
+
if (cstrcasecmp_with_null("ENTITY", h5.token_start, 6) == 0) {
|
|
1162
|
+
return LIBINJECTION_RESULT_TRUE;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
return parser_result;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/*
|
|
1171
|
+
* wrapper
|
|
1172
|
+
*
|
|
1173
|
+
*
|
|
1174
|
+
* const char* s: input string, may contain nulls, does not need to be
|
|
1175
|
+
* null-terminated. size_t len: input string length.
|
|
1176
|
+
*
|
|
1177
|
+
*
|
|
1178
|
+
*/
|
|
1179
|
+
injection_result_t libinjection_xss(const char *s, size_t slen) {
|
|
1180
|
+
injection_result_t result;
|
|
1181
|
+
if ((result = libinjection_is_xss(s, slen, DATA_STATE)) !=
|
|
1182
|
+
LIBINJECTION_RESULT_FALSE) {
|
|
1183
|
+
return result;
|
|
1184
|
+
}
|
|
1185
|
+
if ((result = libinjection_is_xss(s, slen, VALUE_NO_QUOTE)) !=
|
|
1186
|
+
LIBINJECTION_RESULT_FALSE) {
|
|
1187
|
+
return result;
|
|
1188
|
+
}
|
|
1189
|
+
if ((result = libinjection_is_xss(s, slen, VALUE_SINGLE_QUOTE)) !=
|
|
1190
|
+
LIBINJECTION_RESULT_FALSE) {
|
|
1191
|
+
return result;
|
|
1192
|
+
}
|
|
1193
|
+
if ((result = libinjection_is_xss(s, slen, VALUE_DOUBLE_QUOTE)) !=
|
|
1194
|
+
LIBINJECTION_RESULT_FALSE) {
|
|
1195
|
+
return result;
|
|
1196
|
+
}
|
|
1197
|
+
if ((result = libinjection_is_xss(s, slen, VALUE_BACK_QUOTE)) !=
|
|
1198
|
+
LIBINJECTION_RESULT_FALSE) {
|
|
1199
|
+
return result;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
return LIBINJECTION_RESULT_FALSE;
|
|
1203
|
+
}
|