Python Scripting Engine - The Art Of Browser Automation with Python
The Python Scripting Engine has following options -
Python Scripting Engine:
--python PYTHON Executes provided python code.
--python-after PYTHON_AFTER
Executes provided python code after single fuzzing attempt of form.
--python-file PYTHON_FILE
Reads and Executes provided python code from file.
--python-request PYTHON_REQUEST
Python code which will modify the HTTP Request.
--python-request-file PYTHON_REQUEST_FILE
File containing python code to manipulate HTTP Request.
--python-response PYTHON_RESPONSE
Python code to manipulate HTTP Response.
--python-response-file PYTHON_RESPONSE_FILE
File containing python code to manipulate HTTP response.
The Python Scripting Engine allows users to custom python code before/after fuzzing the form and control the browser object. It provides the driver to automate and interact with the running browser using python.
Owning the browser using --python
, --python-after
, --python-file
options
The --python
options takes python from pentester and executes it. The --python-after
is same just executes python after --button
is pressed. The --python-file
is same as --python
option just takes .js files to execute.
This provides insane amount of flexibility, extendibility and modification. You can interact with the browser using driver object provided by Python Scripting Engine.
This allows users to do whatever they want to do, just the barrier is imagination.
Few things which you can do with this are -
- Create python code to crack the captchas
- Fuzz multi pages forms
- Automate browser further using the browser object provided by Python Scripting Engine, which is not possible via javascript option
- Tackle the complex navigation by automating the browser
For Example, following is the code we used to fuzz the two page application. First page requires users to enter the mobile number and other page verifies that number. Now I want to fuzz the second web page so I wrote the following python code to automate the first page, and then fuzz the second page using BrowserBruter :
python3 BrowserBruter.py --elements text-center --button font-semibold --payloads usernames.txt --target https://localhost.com/ --attack 1 --python "e1 = driver.find_element(By.CSS_SELECTOR, 'input.w-full.text-center'); e1.send_keys('0987654321'); driver.find_element(By.CSS_SELECTOR, 'button.btn-primary.mt-6.w-full.font-semibold').click(); sleep(0.5)"
Here,
--elements text-center
is the text field which takes the otp on second page--button font-semibold
is the button to be pressed on the second page--payloads usernames.txt
is file containing payloads--target https://localhost.com/
is the target application--attack 1
specifies that this is sniper attack--python "e1 = driver.find_element(By.CSS_SELECTOR, 'input.w-full.text-center'); e1.send_keys('0987654321'); driver.find_element(By.CSS_SELECTOR, 'button.btn-primary.mt-6.w-full.font-semibold').click(); sleep(0.5)"
is the python code to automate the first page of the flow.
This was an actual real world application we fuzzed using the BrowserBruter and automated the two page registration flow using Python Scripting Engine as shown below -
Note: the details like target and scope are confidential that's why they are hidden in above image.
Owning HTTP traffic with --python-request
, --python-request-file
, --python-response
, --python-response-file
The Python Scripting Engine can help you to control the HTTP traffic as well.
The --python-request
option is used to take Python code which will be executed to control the HTTP request. For Example, consider the below code:
python3 BrowserBruter.py --elements username,password --payloads sqli.txt --target http://localhost/login3.php --button "button.btn.btn-default" --attack 1 --fill username,password --python-request "request.headers['python-added'] = 'added-by-python'"
Here,
--elements username,password
are list of elements to be fuzzed--payloads sqli.txt
are list of payloads--target http://localhost/login3.php
is the URL of target--button "button.btn.btn-default"
is the button to press--attack 1
is the sniper attack mode--fill username,password
indicate the username,password field to be filled--python-request "request.headers['python-added'] = 'added-by-python'"
the python code to modify the HTTP request
The --python-request-file
is the same as --python-request
options just takes python code in file.
The --python-response
option is used to take Python code which will be executed to control the HTTP response. For Example, consider the below code:
python3 BrowserBruter.py --elements username,password --payloads sqli.txt --target http://localhost/login3.php --button "button.btn.btn-default" --attack 1 --fill username,password --python-response "response.headers['python-added'] = 'added-by-python'"
Here,
--elements username,password
are list of elements to be fuzzed--payloads sqli.txt
are list of payloads--target http://localhost/login3.php
is the URL of target--button "button.btn.btn-default"
is the button to press--attack 1
is the sniper attack mode--fill username,password
indicate the username,password field to be filled--python-response "response.headers['python-added'] = 'added-by-python'"
the python code to modify the HTTP request
The --python-response-file
is the same as --python-response
options just takes python code in file.
So this is how you can utilize the Python Scripting Engine do whatever you want to do. These are by far the most powerful options available in Browser Bruter.
Integrating Machine Learning into Browser Bruter to crack the captchas
Yes, The Python Scripting Engine is just so flexible, it literally allows to integrate the Machine Learning Models into Browser Bruter for better.
For Example, below is the sample web page for login, but it has captcha image as can be shown below -
Note: Above lab can be found inside res/samples/captcha/
directory and can be run using python3 captcha.py
Now, After training a Machine Learning model to crack the above captcha, I have saved it as can be shown below.
Now, I have written following python code which will utilize the Machine Learning to crack captcha:
import os
import random
import cv2
import string
from PIL import Image, ImageDraw, ImageFont
from captcha.image import ImageCaptcha
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.utils import to_categorical
import requests
# Function to preprocess and predict text from a sample captcha
def predict_captcha(model, sample_captcha_path, label_to_int):
# Load and preprocess the sample PNG captcha
sample_captcha = cv2.imread(sample_captcha_path, cv2.IMREAD_GRAYSCALE)
#sample_captcha = cv2.cvtColor(sample_captcha_image, cv2.COLOR_BGR2GRAY)
sample_captcha = cv2.resize(sample_captcha, (28 * 4, 28))
# Chop the sample captcha into four characters
character_width = 28
characters = [sample_captcha[:, i:i + character_width] for i in range(0, sample_captcha.shape[1], character_width)]
# Preprocess each character and make predictions
predicted_text = ""
for char_image in characters:
char_image = char_image.reshape((1, 28, 28, 1)).astype("float32") / 255.0
predictions = model.predict(char_image)
predicted_label_idx = np.argmax(predictions)
predicted_label = list(label_to_int.keys())[list(label_to_int.values()).index(predicted_label_idx)]
predicted_text += predicted_label
return predicted_text
# Map labels to integers
label_to_int = {char: idx for idx, char in enumerate(string.ascii_letters + string.digits)}
num_classes = len(label_to_int)
# Load the saved model
model = tf.keras.models.load_model("res/samples/captcha_model.keras") # Change this to the correct path of the model (better provide full path)
# Re-compile the model to ensure metrics are set
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
image_element = driver.find_element(By.ID, "captcha_image")
img_url = image_element.get_attribute('src')
response = requests.get(img_url)
with open('image.png', 'wb') as file:
file.write(response.content)
# Example usage of the prediction function
predicted_text = predict_captcha(model, 'image.png', label_to_int)
print("Predicted Text:", predicted_text)
image_input_element = driver.find_element(By.ID, "captcha_input")
image_input_element.clear()
image_input_element.send_keys(predicted_text)
Now we can provide above code to Browser Bruter using below command:
python3 BrowserBruter.py --elements username,password --payloads sqli.txt --target http://localhost:5000/ --button submit --attack 1 --fill username,password --python-file res/samples/bb-predict.py --debug
And we have successfully leverage the potential of machine learning in to Browser Bruter.
This is a small Proof of Concept for the functionality of the Python Scripting Engine, the possibilities is countless.
Hope on to the next section to learn about options that alter the working of Browser.