diff --git a/src/lib/ACLAnalyzer.py b/src/lib/ACLAnalyzer.py index a4d6c35fdcb1c9db5dfc64149c3cfa4cace3f0b8..ef6d8d63c13a86f02777aee67f29ad542c8b15c9 100644 --- a/src/lib/ACLAnalyzer.py +++ b/src/lib/ACLAnalyzer.py @@ -34,7 +34,8 @@ class ACLAnalyzer(): def analyze_class(self,route:ElementContext)->list[str]: - method_lists = list(filter(lambda x:x['name']!='__init__' and x['type']=='class_method' and x['parent']==route.get_base_element_name(),route.cfg.source_code_method_list)) + file_method_list = self.project_info.dependency_manager.get(route.location).method_list + method_lists = list(filter(lambda x:x['name']!='__init__' and x['type']=='class_method' and x['parent']==route.get_base_element_name(),file_method_list)) # Remove yang ada di no check list for ctx in route.context: if ctx.startswith("Exempt::"): @@ -46,12 +47,13 @@ class ACLAnalyzer(): class_acls = [] for f in method_lists: ctx = ElementContext(f"{f['parent']}.{f['name']}",'function',route.location,[f"Parent::{f['parent']}"]) - ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code_method_list,route.cfg.source_code_dependency_list,route.cfg.source_code)) + ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code)) result = self.analyze_function(ctx) class_acls.append([ctx.name,result]) return class_acls def analyze_function(self,route:ElementContext,is_route=True)->list[str]: + file_method_list = self.project_info.dependency_manager.get(route.location).method_list # Cek parent nya untuk menentukaan apakah ada dekorator # Inisialisasi principal_list var_list = [] @@ -104,7 +106,7 @@ class ACLAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -192,7 +194,7 @@ class ACLAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -233,7 +235,7 @@ class ACLAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -272,7 +274,7 @@ class ACLAnalyzer(): # Cek apakah fungsinya dipanggil if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -327,7 +329,7 @@ class ACLAnalyzer(): if parts[0]==var['name']: parts[0] = var['type'] fun_name = ".".join(parts) - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if parts[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -383,8 +385,9 @@ class ACLAnalyzer(): return principal_list def analyze_module(self,route:ElementContext)->list[list[str,list[str]]]: + file_method_list = self.project_info.dependency_manager.get(route.location).method_list # Cari info semua fungsi di module - method_lists = [m for m in route.cfg.source_code_method_list if not (m['type']=='class_method' and m['name']=='__init__')] + method_lists = [m for m in file_method_list if not (m['type']=='class_method' and m['name']=='__init__')] # Remove yang ada di no check list for ctx in route.context: if ctx.startswith("Exempt::"): @@ -398,18 +401,19 @@ class ACLAnalyzer(): if f['type']=='class_method': #TODO class method ctx = ElementContext(f"{f['parent']}.{f['name']}",'function',route.location,[]) - ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code_method_list,route.cfg.source_code_dependency_list,route.cfg.source_code)) + ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code)) result = self.analyze_function(ctx) route_acls.append([ctx.get_base_element_name(),result]) else: ctx = ElementContext(f['name'],'function',route.location,[]) - ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code_method_list,route.cfg.source_code_dependency_list,route.cfg.source_code)) + ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code)) result = self.analyze_function(ctx) route_acls.append([ctx.get_base_element_name(),result]) return route_acls def check_acl_list(self,route:ElementContext,name:str,ctx:list[str]=[])->list[str]|None: #TODO handle variabel dan kelas dan import + file_method_list = self.project_info.dependency_manager.get(route.location).method_list # Format name: fun atau self.fun acl_list = (role for role in self.acl_info.principal_list) for acl_class in self.project_info.acl_class: @@ -443,7 +447,7 @@ class ACLAnalyzer(): if acl_class.location==route.location: # Kelas/fungsi lokal # Kali aja ada di module ini - for function in route.cfg.source_code_method_list: + for function in file_method_list: if(acl_class.type=='class' and function['type']=='class_method' and function['parent']==acl_class.get_base_element_name()): full_name = name if len(name.split("."))==1 and ctx: @@ -471,7 +475,7 @@ class ACLAnalyzer(): else: # Beda file, cek di import ada gak # Kali aja ada di module ini - dependency_lists = route.cfg.source_code_dependency_list + dependency_lists = self.project_info.dependency_manager.get(route.location).dependency_list route_position = route.cfg.get_line_index(route.name) for dependency in dependency_lists: if dependency[0 ]> route_position: @@ -497,7 +501,8 @@ class ACLAnalyzer(): elmt = ctx[j] j+=1 name = f"{name}.{elmt}" - for method in acl_class.cfg.source_code_method_list: + acl_file_method_list = self.project_info.dependency_manager.get(acl_class.location).method_list + for method in acl_file_method_list: if method['type']!='class_method' or (method['type']=='class_method' and method['parent']!=m['original']): continue if(name==f'{comparator}.{method["name"]}'): @@ -519,7 +524,8 @@ class ACLAnalyzer(): tmp_name = name if parent_class: tmp_name = f"{parent_class}.{name}" - for method in acl_class.cfg.source_code_method_list: + acl_file_method_list = self.project_info.dependency_manager.get(acl_class.location).method_list + for method in acl_file_method_list: tmp_comparator = comparator # Fungsi tidal sesuai if method['type']=='module_function' and method['name']!=m['original']: @@ -538,7 +544,7 @@ class ACLAnalyzer(): if check_var in self.acl_info.acl_context: return check_var # Jika ini library - for dep in route.cfg.source_code_dependency_list: + for dep in self.project_info.dependency_manager.get(route.location).dependency_list: lib_name = dep[1]['original'] format_lib = f'lib:{lib_name}::{".".join(components[1:])}' if (components[0]==dep[1]['rename'] or components[0]==dep[1]['original']) and format_lib in self.acl_info.acl_context: diff --git a/src/lib/CFGGenerator.py b/src/lib/CFGGenerator.py index d0fbfb1deca3b676b7f498df613bb2fd0f3f74a3..669cc4c8df71b933708ef4bb359a3a107d6cbd8d 100644 --- a/src/lib/CFGGenerator.py +++ b/src/lib/CFGGenerator.py @@ -19,11 +19,11 @@ class CFGGenerator(): deps_list = self.ast_parser.get_dependency_list(source_code,method_list) replacement = "\\" if platform.startswith("win") else "/" dependency = FileInformation(ctx.location.split(replacement)[-1],ctx.location,deps_list,method_list) - return CFG(ast,ctx,cursor,method_list,deps_list,source_code),dependency + return CFG(ast,ctx,cursor,source_code),dependency class CFG(): - def __init__(self,ast:Node,ctx:ElementContext,cursor:TreeCursor,source_code_method_list:list[dict[str,str]],dependency_list,source_code:str|bytes = "",next_branch:Optional[TreeCursor] = None) -> None: + def __init__(self,ast:Node,ctx:ElementContext,cursor:TreeCursor,source_code:str|bytes = "",next_branch:Optional[TreeCursor] = None) -> None: self.ast:Node = ast self.ctx:ElementContext = ctx self.cursor:TreeCursor = cursor @@ -33,8 +33,6 @@ class CFG(): self.source_code:bytes = source_code self.next_branch:Optional[TreeCursor] = next_branch self.original_cursor:TreeCursor = self.cursor.copy() - self.source_code_method_list:list[dict[str,str]] = source_code_method_list - self.source_code_dependency_list:list = dependency_list self.is_traversing:bool = False def get_line_index(self,text:str)->int: diff --git a/src/lib/DependencyManager.py b/src/lib/DependencyManager.py index 24dc27c638a0f2876b65b3ae11fcfe0a11aaf813..cfc4b291042fb149bde8fcf0c7aeb6add2ee8ca1 100644 --- a/src/lib/DependencyManager.py +++ b/src/lib/DependencyManager.py @@ -1,3 +1,18 @@ +from sys import platform + +class FileInformation(): + def __init__(self,name,path,dependency_list,method_list): + self.name:str = name + self.path:str = path + self.dependency_list:list = dependency_list + self.method_list:list = method_list + + def __repr__(self) -> str: + return self.__str__() + + def __str__(self) -> str: + return f"FileInformation(name={self.name},path={self.path},dependency_list=[{len(self.dependency_list)} item],method_list=[{len(self.method_list)} item])" + class DependencyManager(): def __init__(self) -> None: self.informations = [] @@ -9,7 +24,9 @@ class DependencyManager(): # Belum ada self.informations.append(information) - def get(self,name,path): + def get(self,path:str)->FileInformation|None: + replacement = "\\" if platform.startswith("win") else "/" + name = path.split(replacement)[-1] for info in self.informations: if info.name == name and info.path == path: return info @@ -21,15 +38,3 @@ class DependencyManager(): def __str__(self) -> str: return f"DependencyManager(informations={self.informations})" -class FileInformation(): - def __init__(self,name,path,dependency_list,method_list): - self.name:str = name - self.path:str = path - self.dependency_list:list = dependency_list - self.method_list:list = method_list - - def __repr__(self) -> str: - return self.__str__() - - def __str__(self) -> str: - return f"FileInformation(name={self.name},path={self.path},dependency_list=[{len(self.dependency_list)} item],method_list=[{len(self.method_list)} item])" \ No newline at end of file diff --git a/src/lib/RouteSanitizationAnalyzer.py b/src/lib/RouteSanitizationAnalyzer.py index ff7abf2cb40b631b9c33b62b43ea3224ce9a8f7d..d9b87f8188e289498ddd09cbd6b9bc8abde3b663 100644 --- a/src/lib/RouteSanitizationAnalyzer.py +++ b/src/lib/RouteSanitizationAnalyzer.py @@ -35,7 +35,8 @@ class RouteSanitizationAnalyzer(): return vuln_routes def analyze_class(self,route:ElementContext)->list[str]: - method_lists = list(filter(lambda x:x['name']!='__init__' and x['type']=='class_method' and x['parent']==route.get_base_element_name(),route.cfg.source_code_method_list)) + file_method_list = self.project_info.dependency_manager.get(route.location).method_list + method_lists = list(filter(lambda x:x['name']!='__init__' and x['type']=='class_method' and x['parent']==route.get_base_element_name(),file_method_list)) # Remove yang ada di no check list for ctx in route.context: if ctx.startswith("Exempt::"): @@ -47,12 +48,13 @@ class RouteSanitizationAnalyzer(): unsanitized_methods = [] for f in method_lists: ctx = ElementContext(f['name'],'function',route.location,[]) - ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code_method_list,route.cfg.source_code_dependency_list,route.cfg.source_code)) + ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code)) if(not self.analyze_function(ctx)): unsanitized_methods.append(f['name']) return unsanitized_methods def analyze_function(self,route:ElementContext)->bool: + file_method_list = self.project_info.dependency_manager.get(route.location).method_list var_list = [] # Cek parent nya untuk menentukaan apakah ada dekorator route.cfg.reset() @@ -91,7 +93,7 @@ class RouteSanitizationAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -128,7 +130,7 @@ class RouteSanitizationAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -165,7 +167,7 @@ class RouteSanitizationAnalyzer(): # Cek apakah fungsinya ada if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -201,7 +203,7 @@ class RouteSanitizationAnalyzer(): # Cek apakah fungsinya dipanggil if fun_name: # cek buat fungsi di kelas yang sama - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if fun_name.split(".")[0]!='self' and rute['type']=='module_function' and rute['name']==fun_name: function_name = fun_name @@ -250,7 +252,7 @@ class RouteSanitizationAnalyzer(): for var in var_list: if parts[0]==var['name']: parts[0] = var['type'] - for rute in route.cfg.source_code_method_list: + for rute in file_method_list: function_name = "" if parts[0]!='self' and rute['type']=='module_function' and rute['name']==".".join(parts): function_name = ".".join(parts) @@ -276,8 +278,9 @@ class RouteSanitizationAnalyzer(): def analyze_module(self,route:ElementContext)->list[str]: #TODO CFG + file_method_list = self.project_info.dependency_manager.get(route.location).method_list # Cari info semua fungsi di module - method_lists = [m for m in route.cfg.source_code_method_list if not (m['type']=='class_method' and m['name']=='__init__')] + method_lists = [m for m in file_method_list if not (m['type']=='class_method' and m['name']=='__init__')] # Remove yang ada di no check list for ctx in route.context: if ctx.startswith("Exempt::"): @@ -290,7 +293,7 @@ class RouteSanitizationAnalyzer(): for f in method_lists: ctx = ElementContext(f['name'],'function',route.location,[]) # set cfg - ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code_method_list,route.cfg.source_code_dependency_list,route.cfg.source_code)) + ctx.set_cfg(CFG(f['ast'],f['ctx'],f['cursor'],route.cfg.source_code)) if(not self.analyze_function(ctx)): if f['type']=='class_method': unsanitized_methods.append(["class",f['name'],f['parent']]) @@ -300,6 +303,7 @@ class RouteSanitizationAnalyzer(): def is_in_acl_list(self,route:ElementContext,name:str,ctx:list[str]=[]): # Format name: fun atau self.fun + file_method_list = self.project_info.dependency_manager.get(route.location).method_list for acl_class in self.project_info.acl_class: acl_class.cfg.reset() if(acl_class.type=='library' and acl_class.location==route.location): @@ -326,7 +330,7 @@ class RouteSanitizationAnalyzer(): if acl_class.location==route.location: # Kelas/fungsi lokal # Kali aja ada di module ini - for function in route.cfg.source_code_method_list: + for function in file_method_list: if(acl_class.type=='class' and function['type']=='class_method' and function['parent']==acl_class.get_base_element_name()): #TODO hanya handle 1 accessing misal a.b, a.b.c gak bisa full_name = name @@ -355,7 +359,7 @@ class RouteSanitizationAnalyzer(): else: # Beda file, cek di import ada gak # Kali aja ada di module ini - dependency_lists = route.cfg.source_code_dependency_list + dependency_lists = self.project_info.dependency_manager.get(route.location).dependency_list route_position = route.cfg.get_line_index(route.name) for dependency in dependency_lists: if dependency[0 ]> route_position: @@ -384,7 +388,8 @@ class RouteSanitizationAnalyzer(): break elmt = ctx[j] name = f"{name}.{elmt}" - for method in acl_class.cfg.source_code_method_list: + acl_file_method_list = self.project_info.dependency_manager.get(acl_class.location).method_list + for method in acl_file_method_list: if method['type']!='class_method' or (method['type']=='class_method' and method['parent']!=m['original']): continue if(name==f'{comparator}.{method["name"]}'): @@ -397,7 +402,8 @@ class RouteSanitizationAnalyzer(): if m["rename"]: # Pake rename comparator = m["rename"] - for method in acl_class.cfg.source_code_method_list: + acl_file_method_list = self.project_info.dependency_manager.get(acl_class.location).method_list + for method in acl_file_method_list: if method['type']=='class_method' and (f"{method['parent']}.{method['name']}"==f"{comparator}.{name}" or f"{parent_class}.{method['name']}"==f"{comparator}.{name}"): return True # Fungsi tidal sesuai