OSCP Lab Upload Review: Request Context and Lifecycle Evidence

OSCP upload practice needs evidence for each stage from request to application processing and storage. A successful-looking response should not replace the separate observation needed for the claim you are making.

OSCP file upload bypass checklist
Sources, review date and section shortcuts

Key claims reviewed: October 19, 2026. A 200 response, upload ID, storage event and retrievable file are different observations.

Primary documentation ยท Related practical guide

Go straight to: Decision check ยท Main workflow ยท Further detail

Open the Upload lifecycle evidence record for this guideโ€™s task-specific fields and next action.

Validate the upload lifecycle without assuming execution

Preserve a known-good request and change one permitted variable at a time. Keep session state, multipart field names, boundary and follow-up processing distinct. Header field names are case-insensitive; a casing difference alone does not establish a compliant parser requirement. Private storage or quarantine can intentionally prevent a direct GET. Use authorized UI/API status or owner-assisted evidence to determine acceptance and storage; retrieval does not prove executable behavior. Source and scope.

The Silent-Failure Zone: OSCP File Upload Bypass

First determine which stage of the upload lifecycle is supported by the available evidence. Stop guessing and start proving.

This workflow is for the moments when the UI flashes green and Burp shows a 200, but your payload disappears like it hit drywall. Before you tweak extensions, verify the request shape, session state, and multipart parsing.

The Methodology

  • One variable at a time.
  • Proof before payload. (If you need a guardrail for this mindset, keep the OSCP rabbit-hole rule nearby.)
  • Fetch it back before impact.

The “Gold Request”

  • 1. Build baseline in Repeater
  • 2. Spot the gate: Send/Accept/Store/Fetch
  • 3. Pivot when execution isn’t the path
“Iโ€™ve burned 45 minutes on clever filenames while a stale CSRF token quietly killed every upload. This is the method that stops that spiral.”
Fast Answer: If your file โ€œuploadsโ€ but your payload never hits the server, the blocker is usually before your shell ever matters: wrong request shape, missing session/CSRF, client-side-only edits, or a server-side rewrite that quietly discards the file. In Burp, win by verifying four things in order: (1) the exact request is sent, (2) auth + CSRF are valid, (3) multipart boundaries/fields match, (4) the response proves storage and reachability. Treat every bypass as evidence, not hope.

1) Who this is for / not for (Scope first, points later)

For: Burp users stuck at โ€œIt should workโ€ฆ but nothing landsโ€

If you canโ€™t tell whether the backend even received your file, youโ€™re in the right place. This checklist is built for the โ€œsilent failureโ€ zone: the response looks normal, the UI claims success, and your payload feels like it vanished into the drywall.

For: OSCP-style labs where you have explicit authorization

This is for authorized lab/CTF environments and training targets youโ€™re allowed to test. Itโ€™s designed to be exam-note-friendly: clean steps, proof points, minimal drama. (If youโ€™re building your setup from scratch, start with safe hacking lab basics at home so your practice stays clean and intentional.)

Not for: real-world targets you donโ€™t own or lack permission to test

Keep it legal. If you donโ€™t have explicit permission, donโ€™t touch it. Besides: the best workflow is the one you can use proudly in your report without sweating.

Takeaway: Your goal is not โ€œa clever fileโ€ โ€” itโ€™s a proven chain: sent โ†’ accepted โ†’ stored โ†’ reachable.
  • Start from a known-good UI upload, not a fantasy request.
  • Prove each gate before chasing bypass tricks.
  • Document evidence like youโ€™ll forget everything tomorrow (because you will). If you want a consistent standard for โ€œwhat counts,โ€ use an OSCP proof screenshot checklist mindset.

Apply in 60 seconds: Write the four verbs on paper: Send / Accept / Store / Fetch. Donโ€™t move on until each one is true.

Eligibility checklist (quick yes/no):
  • Yes โ€” This is an authorized lab/CTF target youโ€™re allowed to test.
  • Yes โ€” You can capture one known-good upload from the UI.
  • Yes โ€” You can re-send the request in Burp Repeater.
  • No โ€” Youโ€™re trying to โ€œguessโ€ endpoints without a baseline.

Next step: If any โ€œNoโ€ appears, pause and get a baseline upload first.

OSCP file upload bypass checklist

2) Payload never reaches the server: the 10-second Burp triage

Hook: โ€œDid it even leave your browser?โ€

Before you debate MIME types or magic bytes, answer the most basic question: did the request actually get sent in the shape the server expects?

  • Browser โ†’ Proxy โ†’ Repeater: same endpoint, same method, same body?
  • Proxy HTTP history: do you see the request at all?
  • Repeater: can you reproduce the response exactly?

Check 1: Request shows up in Proxy HTTP history

An absent history entry does not prove the browser sent nothing. First inspect history display filters, then confirm the browser uses the correct listener. A request sent directly by Repeater is not expected to appear as browser traffic in Proxy history.

Check 2: Does Repeater reproduce the exact server response?

Send the UI-generated request to Repeater and re-send it unchanged. If the response differs, donโ€™t โ€œimproveโ€ it yet. Find out why it differs. Session, CSRF, header normalization, or timing issues usually explain it.

Check 3: Response contains server-side hints (IDs, storage paths, hashes)

UI success can be a front-end illusion. Backend acceptance usually leaves fingerprints: an upload ID, a file key, a resized image URL, a JSON field that includes a stored filename, or at least a predictable redirect.

My rule: if I canโ€™t point to a server-side artifact in the response, I treat the โ€œuploadโ€ as unproven. Itโ€™s not pessimism. Itโ€™s time management.


3) The โ€œrequest-shapeโ€ audit (multipart that actually parses)

Key term: multipart/form-data anatomy

Most upload lab failures are not โ€œfilters.โ€ Theyโ€™re parser mismatch. Your file is fine; your request is wrong. The backend doesnโ€™t see a file at all.

  • Content-Type: multipart/form-data; boundary=โ€ฆ
  • Body format: each part has correct headers and CRLF spacing
  • Content-Disposition: includes name (field name) and filename

Confirm boundary, Content-Disposition, filename, and field name

In Burp Repeater, itโ€™s easy to accidentally damage multipart formatting when you edit quickly. Tiny mistakes matter:

  • Boundary string doesnโ€™t match the body separators
  • Missing CRLF between headers and file content
  • Wrong field name (the backend expects โ€œavatar,โ€ you sent โ€œfileโ€)

Validate the โ€œfile fieldโ€ isnโ€™t a decoy

Some apps send multiple parts: a metadata JSON part plus a file token, or a hidden field that must match. Others use two file fields (thumbnail + original). If you only edit one, the backend accepts the request but keeps the original file.

Letโ€™s be honestโ€ฆ your field name is probably wrong

Donโ€™t guess the field name. Extract it from a known-good upload. Capture a valid request from the UI, then copy the exact name=”โ€ฆ” value used in Content-Disposition.

Show me the nerdy details

Compare multipart boundaries, field names, Content-Disposition parameters and the applicationโ€™s expected request sequence against a known-good request. HTTP header field names are case-insensitive. Any observed dependence on part order or unusual casing is an application-specific observation to verify, not a general multipart rule.


4) Session & CSRF: the invisible gate that kills uploads quietly

Mistake #1: Repeater request without the right cookies

Sending a captured request to Repeater includes its captured cookies. They can become stale; configured session handling rules may update cookies or tokens for tools within their scope. Verify the request actually sent rather than assuming automatic browser synchronization. If authentication is required, confirm:

  • Cookie scope: correct domain and path
  • Session freshness: not expired, not rotated
  • SameSite realities: browser behaviors differ from raw requests

Mistake #2: CSRF token is one-time or tied to a form step

Many apps tie the CSRF token to a form view, a timestamp, or a session nonce. If your UI upload works once and Repeater fails, it might be token-binding, not filtering.

In Burp, you can re-fetch the form and re-send, or use a Macro-driven workflow so Repeater requests pull fresh tokens. Keep it simple: youโ€™re not building a product, youโ€™re building a repeatable lab method.

Why does the server return 200 but store nothing?

Because โ€œ200 OKโ€ can mean โ€œwe received your request,โ€ not โ€œwe accepted your file.โ€ Some apps always respond with a generic success page, then handle validation asynchronously. Others soft-fail and show a success message to avoid revealing validation logic.

Takeaway: A valid upload needs valid stateโ€”cookies and tokens are part of the request, not optional accessories.
  • First reproduce the UI request unchanged in Repeater.
  • If it fails, assume session/CSRF before you assume filters.
  • Look for backend proof, not UI applause.

Apply in 60 seconds: Re-send the baseline upload twice. If the second fails, suspect token rotation.


5) Client-side blocks that trick you (and how Burp exposes them)

Bypass the browser, not the server

If JavaScript blocks an extension or MIME type, Burp can still send it. But that doesnโ€™t mean the server will accept it. Your job is to separate client-side theater from server-side truth.

Verify youโ€™re not editing the wrong layer

This is the classic lab trap:

  • You change something in DevTools and assume it changed the request.
  • Or you intercept a request, but the UI sends a second request you didnโ€™t modify.
  • Or you edit Repeater, but the browser is still using the original.

Hereโ€™s what no one tells youโ€ฆ UI success is not upload success

Trust only evidence you can fetch. If the upload โ€œsucceeds,โ€ you should be able to retrieve the stored file, or at least retrieve a server-generated ID that references it.

Decision card: Repeater vs Intruder (what to use, when)
  • Use Repeater when youโ€™re proving the baseline and changing one variable at a time.
  • Use Intruder when the request is stable and youโ€™re testing a small set of controlled variations (field name, filename patterns, extensions).
  • Avoid โ€œspray and prayโ€ when CSRF/session is unstableโ€”your results will lie to you.

Next step: Pick one tool for the next 10 minutes and commitโ€”no tab-hopping.


6) File-type validation: extension, MIME, magic bytes, and โ€œdouble checksโ€

Server checks youโ€™ll see in Burp responses

When validation is real, it often leaks clues in plain languageโ€”especially in labs:

  • โ€œInvalid file typeโ€
  • โ€œSignature mismatchโ€
  • โ€œCorrupt imageโ€
  • โ€œUnsupported mediaโ€

Your Burp checklist for validation layers

Think in layers. Many apps do two or more:

  • Extension check: filename ends with .jpg/.png/.pdf
  • Content-Type check: header says image/jpeg
  • Magic bytes check: file content starts like a real image
  • Server-side re-encode: image is resized or re-saved, stripping payloads

Why does changing Content-Type never help?

Because many servers ignore the declared MIME type and sniff the content. A fake header is easy to spot when the first bytes scream โ€œthis is not a JPEG.โ€

Also: if the backend re-encodes images, clever polyglots often die quietly. The app takes your upload, decodes it, then saves a new clean image. Your payload never survives the wash cycle.

Neutral, practical reminder: stacks vary. You may see Nginx in front of the app, Cloudflare at the edge, and object storage like AWS S3 behind it. Each layer can add rules. Your job is to locate the layer that says โ€œno.โ€

Takeaway: If validation exists, the response will usually tell you which layer rejected youโ€”if you read it like a log, not like a user.
  • Stop trusting only the UI message.
  • Look for โ€œsignature,โ€ โ€œdecode,โ€ โ€œresize,โ€ โ€œunsupported.โ€
  • Assume re-encode for images until proven otherwise.

Apply in 60 seconds: Upload a harmless, real JPEG once, then compare response headers and JSON fields against your test file attempt.


7) WAF / reverse proxy / CDN: when the edge eats your request

Signs youโ€™re blocked before the app

Sometimes your request never reaches the application logic. Edge layers can block or normalize uploads. Look for:

  • Generic error pages that donโ€™t match the appโ€™s style
  • Sudden 403 / 406 responses or weird โ€œAccess Deniedโ€ pages
  • Header changes (server banners, cache headers, bot-score hints)
  • Timing shifts: requests fail instantly or start taking longer

Burp moves that reveal edge behavior

Do controlled comparisons:

  • Send the same request via browser and via Repeater; compare headers.
  • Normalize common headers (User-Agent, Accept, Accept-Language) when needed.
  • Keep payload size constant while testing one variable.

Why does it work once, then never again?

Rate limits, token binding, or bot rules. Sometimes the first request warms a session and the second looks automated. Sometimes the first request uses a fresh token and the second reuses it. Treat โ€œworks onceโ€ as a clue: state or rate is involved.


8) Storage path reality check: where uploads go to disappear

Confirm the app stores the file where you can reach it

Check storage and retrieval separately. Private storage, quarantine or asynchronous processing may intentionally prevent a direct GET. Use the authorized UI/API status or other permitted evidence to establish storage; a returned ID alone and a failed GET alone do not settle whether the file was stored.

โ€œUpload succeededโ€ but file is renamed or moved

Common patterns:

  • Randomized names (hashes) instead of your filename
  • Date buckets (/2026/01/17/โ€ฆ)
  • Object storage keys unrelated to your original name

Proof step: fetch the uploaded file via GET

If the response includes a URL, test it immediately. If it includes an ID, look for the โ€œview,โ€ โ€œdownload,โ€ or โ€œimageโ€ endpoint the UI uses. If you canโ€™t retrieve it, donโ€™t jump to bypass tricks yetโ€”your problem might be reachability, not acceptance.

Proof pack checklist (what to gather before you escalate)
  • Baseline UI upload request + response (saved in Burp)
  • Your modified request + response (only one variable changed)
  • Any returned file ID, key, or URL
  • The GET request that proves retrieval (or proves you cannot retrieve)
  • A short note: โ€œWhere it failedโ€ (Send / Accept / Store / Fetch)

Next step: Save these as a single โ€œUPLOAD_PROOF_PACKโ€ note before you continue. If you want your proof habits to compound over time, build it alongside Kali lab logging so your evidence stays clean when youโ€™re tired.

Personal habit: I name the first successful retrieval request โ€œFETCH_BASELINE.โ€ It sounds nerdy because it is. It also keeps me from reinventing the wheel when Iโ€™m tired.


9) Execution myths (OSCP reality): most uploads arenโ€™t executable

Separate goals: upload vs reach vs execute

In many labs, direct execution is not the point. The most common win path looks like this:

  • Upload a file the backend accepts
  • Reach it through a path you can influence
  • Trigger impact via inclusion, parsing, or client-side execution

Common lab patterns where upload becomes impact

  • Image upload โ†’ file include path: upload lands in a predictable directory, later included via LFI.
  • PDF upload โ†’ parser behavior: backend extracts metadata or thumbnails; odd parsers create odd bugs.
  • Avatar upload โ†’ stored XSS: filename or metadata is reflected unsafely in a profile page.

Donโ€™t overfit โ€œwebshellโ€ as the only win condition

When I finally stopped worshipping the webshell, my lab progress sped up. It felt like betrayal. It was actually maturity.


10) Common mistakes (the ones that waste 60 minutes each)

Mistake #1: Editing the filename but not the multipart structure

Changing filename= but breaking the boundary or field name is like putting a racing stripe on a car with no engine. It looks busy. It goes nowhere.

Mistake #2: Forgetting the original form fields (IDs, submit, hidden flags)

Many uploads require extra fields: userId, folder, โ€œsubmit=1,โ€ a hidden checksum, or a JSON metadata part. If you omit them, the backend may accept the request but silently ignore the file.

Mistake #3: Assuming HTTP 200 means backend acceptance

Always look for backend evidence. If the app returns โ€œOKโ€ without an artifact, verify by retrieving the file or checking a follow-up endpoint.

Mistake #4: Not re-running with fresh cookies/tokens after changes

When you tweak one variable, you still need a valid session state. Token-expired tests produce false negativesโ€”and those hurt worse than regular negatives.

Mistake #5: Not saving a โ€œknown-goodโ€ baseline request

This is the biggest time thief. Baselines turn chaos into a science experiment. Without one, every โ€œresultโ€ is questionable. If you want a reliable โ€œwhat to do firstโ€ backbone for web targets, keep an OSCP initial access checklist nearby so you donโ€™t drift into superstition.

Mini calculator (time leak detector)

Input 1: How many upload attempts have you made? (A)

Input 2: Average minutes per attempt including switching tabs? (M)

Output: Total time spent = A ร— M minutes. If thatโ€™s over 30, you owe yourself a baseline reset.

Next step: If youโ€™re past 30 minutes, stop and recreate the UI baseline request in Repeater.


FAQ

Q1: Why does my upload return 200 OK but the file isnโ€™t on the server?

Because 200 often means โ€œrequest handled,โ€ not โ€œfile accepted and stored.โ€ Apps may soft-fail validation, quarantine files, re-encode content, or store to a private location. Your proof is an artifact: an upload ID, a retrievable URL, or a follow-up GET that returns your stored file.

Q2: In Burp, should I test uploads in Repeater or Intruder first?

Start with Repeater. Prove the baseline from the UI, then change one variable at a time. Intruder makes sense only when the request is stable and youโ€™re testing a small, controlled set of variations.

Q3: Whatโ€™s the fastest way to confirm the correct multipart field name?

Capture a known-good UI upload and read the Content-Disposition header in the multipart part. The name=”โ€ฆ” value is the field name the backend expects. Copy it exactly.

Q4: Why do my cookies work in the browser but fail in Repeater?

A captured request carries its cookies, but they may be stale. Check the sent request and any session handling rules that apply to Repeater. Browser SameSite enforcement differs from raw requests; rotated cookies and one-time CSRF tokens still require fresh state.

Q5: How do I handle CSRF tokens that change every request?

Keep a simple loop: request the form (or token endpoint), extract the new token, then send the upload. In Burp, a Macro-based approach can automate the token refresh, but even manual refresh is fine if you keep a clean baseline.

Q6: Why doesnโ€™t changing Content-Type bypass file upload filters?

Because many backends sniff the content or validate magic bytes. Content-Type is a hint, not a guarantee. If the first bytes donโ€™t match a real image/PDF, a strict validator will reject it regardless of the header.

Q7: How can I tell if a WAF blocked my file upload request before it reached the app?

Look for generic error pages, unusual headers, sudden 403/406 responses, and differences between browser vs Repeater behavior. If the response โ€œbrandโ€ doesnโ€™t match the application, suspect the edge layer.

Q8: If the server renames my file, how do I find the stored path?

Use the UIโ€™s follow-up behavior as your map: profile image fetch endpoints, โ€œview attachmentโ€ links, or JSON responses that include file IDs or keys. Your filename often wonโ€™t matter; the serverโ€™s generated key will.

Q9: In OSCP labs, when should I stop chasing RCE from uploads?

When you can prove the file is stored but served from a non-executable context (static object storage, strict content-type serving, heavy re-encoding). At that point, pivot to โ€œwhat consumes the fileโ€ (include, parse, render) instead of forcing execution.

Q10: What evidence should I screenshot/log for exam-style notes?

Baseline request/response, your modified request/response, any upload ID or stored URL, and a GET request that proves retrieval (or proves denial). Add one sentence labeling where it failed: Send / Accept / Store / Fetch. If you need a tight standard for that evidence, use OSCP proof screenshots as your โ€œminimum viable proof.โ€


12) Next step (one concrete action)

Build a โ€œGold Requestโ€ template in Burp

  • Capture one known-good upload request from the UI.
  • Send it to Repeater and save it as a tab named UPLOAD_BASELINE.
  • For every attempt: change one variable, re-send, and log what changed in the response.

This one habit fixes more upload โ€œmysteriesโ€ than any extension trick. It turns your work into a controlled experiment, not a late-night sรฉance.

Takeaway: The Gold Request is your anchor; without it, every result is suspect.
  • Baseline first, then one-variable tests.
  • Responses are dataโ€”read them like logs.
  • If you canโ€™t fetch the stored file, donโ€™t chase execution yet.

Apply in 60 seconds: Rename your best Repeater tab to UPLOAD_BASELINE right now. Make it sacred. If you want this to live as a reusable note instead of a temporary tab, adapt it into an Obsidian OSCP enumeration template or keep it as a host-specific block inside your Obsidian OSCP host template.


OSCP file upload bypass checklist

Conclusion

Remember the hookโ€”โ€œDid it even leave your browser?โ€ Hereโ€™s the calm answer: you donโ€™t have to wonder anymore. When you run this checklist in order, your upload stops being a vibe and becomes a proven chain: sent โ†’ accepted โ†’ stored โ†’ reachable. And once you can name exactly where it breaks, your next move becomes obviousโ€”refresh tokens, fix multipart structure, normalize headers, or pivot away from RCE fantasies toward a real consumption path.

One last personal note: the learners who move fastest arenโ€™t the ones with the wildest payloads. Theyโ€™re the ones who keep their process boring, logged, and repeatable. Thatโ€™s not a personality trait. Itโ€™s a choice you can make in the next 15 minutesโ€”and the same choice is what makes your final write-up painless when you drop evidence into a Kali pentest report template (or any exam-style report format).

Upload Proof Chain (what you must prove, in order)
1) Send
Request appears in Proxy history.
2) Accept
Auth + CSRF valid; backend acknowledges.
3) Store
Response yields ID/key/path; file persists.
4) Fetch
You can retrieve the stored file via GET.
Impact
Only now: execution, include, parse, or XSS paths.
If youโ€™re stuck, circle the first box you canโ€™t prove. That box is your real problem.

The second send failed. That was the clue. The CSRF token was one-time, and my Repeater request was replaying a dead token while the UI refreshed it silently. Once I re-fetched the form and used a fresh token, the upload became stable. No magic bypass. Just proof. The shell dreams came laterโ€”after I could fetch the stored file back like an adult.

Original review: 2026-01-17

Technical guidance updated: 2026-10-13. Corrected history/session assumptions and distinguished stored files from directly retrievable files.

Upload lifecycle evidence record

Use these fields for your own task. Keep the actual conditions, evidence and unresolved questions beside the next decision.

On a small screen, scroll the table sideways to read all columns.

Working record โ€” complete with your own evidence
FieldWhat to recordYour evidence / next check
Baseline requestPreserve session context, multipart fields and the known-good request.To complete
Acceptance stateDistinguish HTTP response, application status and processing outcome.To complete
Storage evidenceRecord the authorized UI, API or owner-assisted observation.To complete
Claim boundaryKeep retrieval and execution as separately unverified claims.To complete

Next action: Identify the first unknown upload stage before changing another request variable.

Related task: Use Burp WebSocket Testing: Capture, Replay and Evidence for that separate part of the workflow.

Worksheet change record โ€” October 20, 2026

Added four task-specific fields, a next action and a related guide. This is a blank editorial working aid, not a completed test or validated assessment. Existing source-review dates retain their own scope; this addition is not a new verification of every statement.

Stay Updated with Kioptrix

Get practical guides, useful resources, and new articles delivered to your inbox.

No spam. Unsubscribe anytime. Read our Privacy Policy.