OSWE: Source Code Review and What the WEB-300 Syllabus Actually Teaches
Why This One
Most web testing I had done up to this point was black box. You poke at the application from the outside, watch how it responds, and build a picture of what is happening on the other side from the shape of that response. It works, and there is real skill in it, but you are always inferring.
OSWE takes that away and hands you the source code instead. No more inferring. The vulnerability is somewhere in the files in front of you, which sounds easier and is not, because a modern application is tens of thousands of lines and the interesting bug is usually four lines that look completely reasonable in isolation.
That shift is the entire reason I wanted this certification. The course is WEB-300, Advanced Web Attacks and Exploitation, and the cert you get at the end is the OSWE.
What The Certification Is
Briefly, since this is not the interesting part:
- The exam runs 47 hours and 45 minutes, followed by another 24 hours to submit documentation.
- It is scored out of 100 and you need 85 to pass.
- You get target applications to compromise, and for each one the shape is the same: get authenticated access you should not have, then turn that into code execution on the server.
- Your deliverable is not a screenshot. It is a working exploit script that runs end to end without you touching anything in the middle, plus a report.
- The certification does not expire.
That last point about automation is worth sitting with, because it changes how you have to work. A manual chain of steps you performed once in Burp is not an answer here. If a human has to intervene halfway through, it does not count. Everything you find has to be reduced to code that does it reliably.
Source Code Review, Which Is The Actual Skill
This is what the course is really about, and it is worth spending most of this post on.
Stop reading, start navigating
My first instinct with a new codebase was to open files and read them. That does not scale. A few modules in, the course pushes you toward something more deliberate: work out how the application routes a request before you read a single line of business logic.
Where are the routes defined? What sits between the request arriving and the controller handling it? Which middleware runs, and in which order? Once you can trace an incoming request from the URL to the function that answers it, the codebase stops being tens of thousands of lines and becomes a handful of paths you actually care about.
Two directions to hunt in
There are broadly two ways to move through source, and you need both.
Sink first. Grep for the dangerous things. Places where a command gets executed, where a template gets rendered with user data in it, where something gets deserialized, where a query gets built by string concatenation. Then work backwards and ask whether anything an attacker controls can reach that point. This is fast and it finds the obvious.
Entry point first. Start where user input arrives and follow it forward, watching what validates it, what transforms it, what trusts it. Slower, but it is how you find the bugs that do not look like bugs, especially in authentication and session handling.
Most of the useful findings in the course material sit where those two directions meet: input that reaches something dangerous through a path nobody thought about.
Authentication logic is where the value is
A pattern becomes obvious quite quickly. Injection bugs are usually the second half of the chain. The first half, the part that gets you inside, is almost always a flaw in logic rather than a flaw in parsing. A comparison that does not do what the author assumed. A token generated from something predictable. A reset flow that trusts a value it should have verified. A check that is correct but happens after the thing it was meant to protect.
None of that shows up in a grep for dangerous functions. You find it by reading the authentication and session code slowly and asking, for each step, what the author is assuming and whether the application actually guarantees it.
Static reading is only half of it
The other half is running the thing. The course sets you up to debug applications locally, and this is not optional decoration. Reading code tells you what should happen. A breakpoint tells you what does.
Practically that means being willing to work in whatever the language of the day needs, stepping through PHP in one module and attaching to a Java process in the next, or opening a .NET assembly to read what the source no longer tells you. It is uncomfortable if you have only ever attacked from outside. It is also the fastest way to resolve “I think this variable is attacker controlled”, which is a question you will ask constantly.
Diffing is a shortcut worth learning
Comparing a vulnerable release against the version that fixed it is one of the highest-value habits the course encourages. The patch tells you where to look, and reading the code around it teaches you what the class of bug looks like in the wild. It is also good practice for reading unfamiliar code with a purpose rather than reading it in general.
The Syllabus
The module list has grown over the years, but its shape has stayed consistent, and the shape is the point. Every module takes a real, publicly available application, walks you through reviewing its source, finds a genuine vulnerability, and then makes you chain it into something that matters.
Applications used across the course include ATutor, ManageEngine, DotNetNuke, Bassmaster, ERPNext, openCRX, openITCOCKPIT, Concord, and Guacamole Lite. That list is doing something deliberate. It spans PHP, Java, .NET, Node.js, and Python, so you cannot lean on being comfortable in one language, and it is all software that real organisations actually deployed.
Grouped by what you learn rather than module by module:
Getting in. Type juggling and loose comparison abuse, authentication bypasses that come from logic rather than injection, and session hijacking.
Getting execution. SQL injection escalated to code execution rather than stopping at data extraction, deserialization in .NET, Java, and PHP, server-side template injection, JavaScript injection, and prototype pollution.
Getting around defences. Bypassing file upload restrictions and extension filters, evading regex-based validation, and working within character restrictions, which is one of those things that sounds like a footnote until it is the only thing standing between you and a working exploit.
Reaching further. Server-side request forgery, XML external entity injection, and data exfiltration through blind and second-order techniques where you never see the result directly.
Tying it together. Writing the whole chain as a Python script that runs unattended.
One module is deliberately black box, which is a nice inversion. After a lot of source-assisted work you get handed an application without the code and have to lean on what you have learned about how such applications are built.
Try Harder, And What That Actually Means
You cannot write about OffSec without addressing this, because “Try Harder” is not marketing. It is the design principle behind the entire course, and it shows up in how the material is deliberately structured.
It is easy to misread as “suffer more”, and it is not that. What it means in practice is that the material stops short on purpose. It shows you a technique thoroughly, then hands you something adjacent and expects you to close the gap yourself. The gap is the lesson. If you fill it by finding someone’s write-up, you have completed the task and skipped the thing you paid for.
Where this becomes concrete is the exercises, and this is the part I would push hardest on: finish them, all of them.
The guided exercises follow the module and are the easy half. The Extra Mile exercises are the ones that matter. They are not guided, there is no walkthrough, and they exist specifically to make you apply what you just read to something nobody is going to hold your hand through. Every one of them I completed taught me more than the module it was attached to. Every one I was tempted to skip was skipped because it was uncomfortable, which is exactly the wrong reason.
The same goes for the challenge labs, the independent applications you compromise with no guidance at all. They are the closest thing to real conditions the course gives you, and they are where you find out whether you can actually do this or have only been following along. Work through them. Do not treat them as optional revision material you will get to if there is time, because there will not be time.
A practical way to hold the mantra without it becoming self-punishment: when you get stuck, stay stuck deliberately for a while. Re-read the code. Set another breakpoint. Write down what you know for certain and what you have only assumed, because it is almost always a wrong assumption rather than missing knowledge. Give it a real, honest attempt before you go looking for help. Being stuck is not a sign the course is going badly. On this course, being stuck is the course.
That said, “Try Harder” was never meant to be “suffer alone indefinitely”. OffSec runs an official Discord community, and using it is entirely legitimate when you have genuinely exhausted your own angles on a course exercise or a challenge lab. There are other students working through the same material and staff around, and a nudge in the right direction after two days of going nowhere is not cheating. Ask well and it works better: describe what you have already tried and what you believe is happening, rather than posting the problem and waiting. You usually find the answer while writing the question anyway.
One hard line, though. That applies to the course, never to the exam. Asking for help with exam targets, hinting at what you are seeing, or fishing for confirmation is a straightforward violation of OffSec’s exam rules, and the consequences run to having your result voided and your certifications revoked. During the exam you are on your own, and that is the entire point of it. Keep the two completely separate in your head.
Preparing
Once the course starts, the exercises and challenges above are your preparation. Before it starts, two things mattered more than anything else for me.
The first is Python. Not the language in general, but specifically being fluent at driving HTTP with it. Sessions, cookies, redirects that you need to not follow, multipart uploads, parsing a token out of a response and feeding it into the next request, retry logic for things that are timing-sensitive. If writing that feels like a chore, fix it before you start the course, because by the end every chain you build has to be expressed that way.
The second is reading code you did not write, on purpose, regularly. Pick a published vulnerability in an open source web application, get the vulnerable version, and try to reach the bug from the source before you read anyone’s write-up. Then read the write-up and see what you missed. That exercise is close to what the course asks of you, and it is free.
Beyond that: build a local lab where you can run and debug these applications comfortably, and take notes as you go in a form you can search later.
About The Exam Itself
I am not going to describe what is in it. Not the technologies, not the vulnerability classes, not the number of steps or how the chains fit together. OffSec’s exam content is confidential and I signed the same agreement everyone else does, and beyond that, a review that quietly tells you what to expect removes the thing the exam is actually measuring.
What I will say is process, which is public anyway. The clock is long enough that you should plan sleep into it rather than treating it as a sprint. Take your evidence as you go, because reconstructing it afterwards while tired is miserable. Get your report structure ready before you start. And keep your exploit script runnable at every stage rather than building it all at the end, since the requirement is that it works unattended, and code that has only ever been run in fragments has a habit of not doing that.
Was It Worth It
Yes, and not for the reason I expected.
I went in wanting to be better at finding web vulnerabilities. What I came out with was a different relationship with source code. Being handed a repository used to feel like an obligation to read all of it. Now it feels like a map, and I know which parts of the map are worth walking.
That has changed practical things. Code review on engagements is faster and I trust my conclusions more. When I find something black box, I can usually explain the underlying cause rather than just demonstrating the effect, which makes for a far more useful report. And the automation requirement, which felt like bureaucracy at first, turned out to be the discipline that makes a finding reproducible for the person who has to fix it.
It is not a cheap certification and the time commitment is real. But if your work involves web applications and you have access to the source, or you want to be the person who asks for the source, it earns its place.
Notes and Disclaimer
- This is my own experience. No exam content is disclosed here, by design.
- Course structure, pricing and packaging change over time. Check OffSec’s official pages before committing.
- Shared for educational purposes.