Easy · Start here
Overview
▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄ ▄▄ ▄▄▄▄ ▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄
▐▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▌▐▓▓▌ ▐▓▓▌ ▐▓▓▓▓▌■▓▓▌▐▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▌
▐▓▓ ▓▓■▐ ■█▓▓█▀■ ▐▓▓▌ ■▓▓▌▐▓▓█■▐▓▓▌ ▐▓▓▌▓▓▌▓▓▌▐▓▓█▄ ■ ▐ ■█▓▓█▀■
■▓▓▌ ▓▓ ▐▓▓▌ ▐▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▌ ▐▓▓▌■▓▓▓▓▌▐▓▓▓▓▓▓▓▌ ▐▓▓▌
▓▓█■ ▓▓▌ ▐▓▓▌ ▐▓▓▌▐▓▓█ ▐▓▓▌ ▐▓▓▌ ▄▄▄ ▐▓▓▌ ▐▓▓▌▐▓▓█▄ ■ ▐▓▓▌
▐▓▓▓▓▓▓█ ▐▓▓▌ ▐▓▓▌■█▓▓▌▐▓▓▌ ▐▓▓▌▐▓▓▓▌▐▓▓▌ ▐▓▓▌▐▓▓▓▓▓▓▓▌ ▐▓▓▌
▐▀▀■ ▀▌ ▐▀■▌ ▐▀■▌ ▐■▀▌▐▀■▌ ▐▀■▌▐▀■ ▐▀■▌ ▀▀▌▐█▀ ■▀█▌ ▐▀■▌
What this site is
A complete, evidence-backed account of a security review of Burp Suite Professional
2026.10.1 for Linux — the desktop client, its installer, and the licensing system that stands between
the free and paid editions.
It is not a summary written after the fact. Every claim here traces to something retained: a log from a
running instance, a decompiled class, a decrypted string, a bytecode listing, or a script that reproduces
the result. Where a claim could not be reproduced, the site says so instead of quietly dropping it.
The point it is making
Burp's licensing system is not careless. A licence key is verified against asymmetric key material built
into the client. Activation is a second, independently signed artefact. Both are re-checked on every
launch. On-disk tampering is rejected. Thousands of deliberately malformed keys were fed to the validator
and every one was refused, without a single unexpected exception. That is a serious, well-built control.
And none of it matters, because the program can be told it is licensed without a licence ever being
involved. Once the validation is finished, the paid-edition decision collapses into a presence check:
is there a licence object sitting in this memory slot? The program also exposes a public way to put an
object in that slot and mark it activated, with no verification at all. One published object — no key, no
activation, no cryptographic material — and the product presents itself and behaves as fully licensed:
|
before |
after |
| licence object in memory |
absent |
a stand-in object |
| paid features allowed |
0 of 26 |
26 of 26 |
| window title |
"Community Edition" |
"Professional" |
| anything written to disk |
— |
nothing |
The lesson is the one worth carrying away from this site: the strength of a check is not the strength of
the system. A control that is verified once and then trusted forever, by consumers that only test that
its output exists, is a control that protects the acquisition of a licence while leaving the use of it
wide open. Every serious effort went into the lock, and the door next to it was never closed.
How to read this
The same account is written three times over, at three depths — three versions of one investigation,
for three kinds of reader. Pick one with the switch under the banner, or with the tabs:
- Easy (green) — plain language, no class names. What was found, what it means, and what should change.
Written for someone deciding whether to care.
- Medium (amber) — the same findings with the technical vocabulary: the gate logic, the bytecode that
matters, the evidence tables.
- Expert (red) — the complete technical report, split into pages: full chronology, decompiled sources,
log excerpts, data tables, every limitation and every untested hypothesis.
Switching level keeps your place — the current topic is carried across, so Easy → the installer problem
lands on Medium → the JVM hijack rather than back at the front page.
The sidebar on the left is the table of contents. Each section expands with + and collapses with −;
the pages are the leaves. It starts fully collapsed so the tree stays short, and it can be hidden entirely
with the ☰ button in the breadcrumb bar above the text (or the [ key) when you want the full width for
reading. Your choice is remembered between visits.
The full report
The whole technical report is available in two formats, both self-contained:
They contain everything this site summarises and everything it only gestures at: the complete
investigation chronology with timestamps, the installer findings, the failure taxonomy, complete log and
bytecode excerpts, and every limitation.
Raw data
The full archive of raw data — every runtime log and UI dump, the complete session transcripts (900
tool calls), the decompiled class tree, the decrypted string corpus, the cross-reference database, and the
experiment scripts — is available on request, at the author's discretion.
Ask at admin@dtrh.net, saying who you are and what you want it for. The site itself carries a
representative subset: the working session transcript,
screenshots and raw logs, the proof-of-concept sources, and
a screen recording of the review.
Changelog
What changed, and when. Every entry is a change to this account of the review, not to the software — the
target stayed frozen at burpsuite_linux_v2026_10_1.sh throughout.
| Version |
Date |
Change |
Where it landed |
| 1.0 |
29 Oct 2026 |
First account: the licensing review (pass criteria, the four-phase proof), the installer review, and the failure taxonomy. |
this site, first pass |
| 1.1 |
30 Oct 2026 |
Evidence bundle reconciled against the shipped artefacts; the report's most prominent open question replaced by a tested result. Added the JVM-hijack finding (INS-12) and the unsandboxed-scripting finding (SNIP-1). |
licence section, installer section, failure taxonomy |
| 1.2 |
30 Oct 2026 |
Closed the two questions that the test environment had left hanging: the earliest possible moment to inject, and a complete fake runtime tree — the second of which turned INS-12 from "executes a planted program" into a demonstrated hijack that bundles an attacker's runtime into the installation. |
installer section, the entitlement-timing result |
| 1.3 |
30 Oct 2026 |
This revision. Took the last open question — whether another part of the program shares the scripting compiler — and closed it as a negative, with two findings attached. (1) The compiler is free: three of the fourteen script kinds carry no licence requirement, so a reduced-edition copy already runs user code inside itself; the report's "needs in-process code" precondition is therefore weaker than it claimed. (2) Nothing feeds that compiler text from the traffic, so visiting a hostile page through the proxy still cannot execute attacker code. |
How we checked it, What actually contains it, Limits, and the full report (§6.13d, F10, H.3) |
The pattern worth noticing in this table: three of the four revisions made a negative result do the
real work. The record of what was tried and refused is the part that survives contact with the next
reader.
Easy · Start here
What this document is
This site is a plain-language account of a security review of Burp Suite Professional 2026.10.1 for
Linux — a widely used commercial tool for testing web applications.
The review asked one question: how does the program decide that you have paid for a licence, and can that
decision be reached some other, easier way?
The answer was yes, and the way it fails is interesting. The parts that check a licence key are strong.
The part that uses the result of that check is a single yes/no in the program's memory, and the program
lets anything running inside it change that yes/no to "yes".
Nothing here is hypothetical. Every claim was reproduced on a real, unmodified installation.
What this is not. This is not a way to get a free licence from outside the program. The
weakness requires code already running inside the application. What it shows is an architectural problem
that matters for anyone who designs licence checks — and a second, unrelated installer problem that is
more serious in practice.
Easy · Start here
The short version
In one paragraph. When you type a licence key, the program checks it properly — genuine, signed, not
revoked, not expired — and then asks for a second "activation" step. But once the program is running, the
paid/unpaid decision collapses into something much smaller: is there a licence object sitting in this
memory slot? The program also has a documented, public way to put an object in that slot and mark it
activated, with no validation whatsoever. With no key and no activation of any kind, one published object
made the program present itself and behave as fully licensed.
Why the strong checking didn't prevent it. The checking protects how you get a licence. It does not
protect how the rest of the program uses one. Every feature gate asks "is the object there?" and never
asks "did it get there honestly?"
The three things worth taking away.
- A check is only as strong as what happens after it. Cryptographic verification of a licence key is
irrelevant if the answer is later stored in a field that anything can overwrite.
- The installer is a separate, and worse, story. The program's installer decides which Java runtime to
use by consulting a plain text file it keeps in the user's home directory. A directory named in that
file gets its
java executed — with no prompt. In our test that fake runtime was then adopted, the
whole installation ran on it, and it was copied into the installed product as its permanent runtime.
- Being careful in one place is not the same as being careful. The licence cryptography is treated as
security-critical and is well built. The choice of which executable to run was delegated to a text file.
Those two sit in the same product, and the weaker one decides what runs.
Easy · Start here
The licence check, and why it doesn't hold
How it is supposed to work. On startup Burp looks for a licence key. If it finds one, it verifies it
cryptographically against a key built into the program. If that passes, it asks the vendor's server to
activate it, and stores the result. Both artefacts are re-checked on every launch. That is a sound design,
and our testing could not break it: thousands of deliberately malformed keys were rejected, and editing
the stored licence on disk was rejected too, locally, without ever contacting the vendor.
Where it comes apart. The result of all that checking is a single object in memory. The rest of the
program reads that object. The gate that decides whether a feature is available asks one question — is the
object there? — and nothing re-examines how it arrived.
We wrote a small piece of code that runs inside Burp's own process. It creates a stand-in object, puts it in
that slot through a public method, and marks the program activated through another public method that
performs no checks at all. The result:
| What we looked at |
Before |
After |
| Licence object in memory |
absent |
our stand-in object |
| Paid features allowed |
0 of 26 |
26 of 26 |
| Window title |
"Community Edition" |
"Professional" |
| New project options |
"Professional only" |
fully enabled |
| Anything written to disk |
— |
nothing |
The last row matters: the change lives only in memory. Restart the program and it is Community Edition
again unless the same code runs again. And because nothing is written, there is nothing on disk to detect
and nothing for the vendor's revocation system to act on.
Easy · Start here
The installer problem (the one to worry about)
How installing normally works. The installer is a self-extracting shell script. It unpacks its payload
into a temporary directory, finds a Java runtime to run the actual installer with, and installs.
How it chooses a Java runtime. It tries a series of candidate locations. One of them is a plain text
file in the user's home directory that records previous installations. The installer writes this file
itself, every time it runs.
What we did. We noticed that file already contained paths under /tmp — left there by our own earlier
experiments. Those directories no longer existed, so anyone with permission to create files in /tmp could
re-create them. We created one, put a realistic-looking Java runtime in it with the java program replaced
by a script of our own, and ran the installer again.
What happened. The installer ran our script. It decided our directory was a valid Java runtime, and then
the whole installation ran on our fake runtime. Finally — and this is the part we did not expect — the
installer copied our fake runtime into the installed product, so the program's own runtime is now our
file, and every later launch would run our code.
Why it is the worst finding here. If the installer is run with administrative rights — which is the
normal way to install for all users — then anyone who can write to that path gets code running with
administrative rights, and leaves behind an installation that keeps running their code.
The fix is small. That history file should never be trusted to name a program to execute. It is a
convenience, not an authority.
Easy · Start here
The bigger lesson
Two failures in one product, with opposite characters.
The licensing failure is a design failure. Someone chose, quite reasonably, to represent "licensed" as
an object. Every consumer of that choice then had to remember to check not just that the object exists
but why. None of them did, because the natural thing to write is if (licence != null).
The installer failure is a delegation failure. Someone chose to remember where previous installations
were, which is helpful. Nobody asked what happens if that record becomes an instruction to execute
something.
Both are the same mistake in different clothes: the program let something it does not control decide a
security question. In one case it was a field in memory; in the other, a line in a text file.
That is why the recommendation at the top of the report is architectural rather than a patch: not "add a
check here", but "stop letting mutable state decide".
Easy · Start here
How we checked it
The work was done on a copy of the software, on an isolated machine, with no access to the vendor's
servers. Nothing about the vendor's online services was tested.
The licensing question was answered in three independent ways, so that no single method carried the
conclusion:
- Reading the code. The program ships with its names scrambled and its text encrypted. We recovered
the encrypted text to make it readable, and read the actual logic.
- Watching it run. We attached a small diagnostic program to a running copy, which let us look at the
live values and ask the program's own feature gate what it thought. This produced the "0 of 26 → 26 of
26" numbers.
- A separate, minimal proof. A second, much smaller program was written from scratch to reproduce the
result, so the finding would not depend on our own tooling. It worked. There is also a way to show the
same thing with no diagnostic program at all, using only the program's public API.
The installer question was answered by running the real installer against deliberately chosen
conditions, and checking what it executed. Four attempts failed before the fifth worked; every failure is
recorded in the technical version, because two of them taught us something about the mechanism.
One more question was asked and answered last, and the answer was no. The program ships a feature that
compiles and runs user-written Java inside its own process — the scripted filters people write to colour
and sort their own traffic. If a website could get its code into that compiler, the whole finding would
escalate from "someone with access to the machine" to "any page visited through the proxy". So we checked,
caller by caller:
- The feature is free: three of the fourteen kinds of script carry no licence requirement at all, so a
copy running in the reduced edition already compiles and runs user code inside itself. That made the
finding wider than we had claimed, not weaker.
- But no part of the program feeds that compiler anything from the traffic. Every one of the eleven
places that compile a script compiles a script that was already stored — in preferences, in an editor
window, or in a project file. Not one builds source from a request or a response.
A website can influence the message a filter looks at. It cannot influence the code the filter runs.
So the escalation does not exist, and the report says so as a negative, with the table that closes it.
Negative results are kept. Six plausible attack ideas were tested and refuted: poisoning the
installer's version cache, a symlink trick with a temporary file, a symlinked directory in the cleanup
prompt, editing the stored licence, using the scripting feature to obtain a licence, and driving that same
scripting feature from a hostile website. Each is documented so nobody repeats the work — and the last two
are the most useful, because they mark the boundary of what the scripting feature is actually worth to an
attacker.
Easy · Start here
What should change
Ordered by "would this have prevented the problem", not by effort.
For the licensing design (the root cause).
- Stop letting in-memory state decide. Either keep the licence decision out of reach of anything
running inside the program, or re-verify it at the point of use against something that cannot be
forged. Today one public method call is the entire gate.
- Do not mark a licence as active before activation has happened. The program currently publishes the
licence object as soon as the key checks out, before activation. Activation should complete first.
- Do not collapse 26 features into one yes/no. One object currently unlocks everything at once. If
each entitlement were separately asserted and checked, forging one would not unlock all.
- Do not gate a network service with a licence flag. One of the 26 gates is whether the program may
open a local network service. That turns a licensing bypass into something closer to an access-control
problem.
For the installer (the highest-severity fix).
- Never run a program named by a file the user can write. The record of previous installations should
be used at most as a hint to be re-validated, never as the authority for which executable to run.
- Do not copy a selected runtime into the installation without verifying it against a signed manifest.
For the scripting feature.
- A rule about what code may import is not a sandbox. The product can compile and run Java inside
itself, and the only containment is a stated convention about imports, which the compiler does not
enforce. If such a feature is to exist, the containment must live where the code runs.
Smaller, cheap fixes are listed in the technical version: store the licence key where other users
cannot read it, sign the update feed as well as the update download, and stop trusting group-writable
configuration files.
Easy · Start here
What this does and does not mean
What was demonstrated. Every technical claim in this report was reproduced on a real installation, and
the evidence is retained alongside it for anyone who wants to check.
What was not demonstrated, and is stated as such in the technical version.
- Not a remote attack. All of the licensing findings need code running inside the program. How such
code gets there is discussed — a documented launch option, the extension model, and a scripting feature.
The scripting route was tested twice: it does not supply a licence, and it cannot be driven from a
website. One honest caveat sits under it: the scripting feature does run user code for free, so on a
machine where someone can write the user's preferences or open their project file, that is another way in
(see the next point).
- No remote service was touched. The vendor's activation and update servers were treated as
off-limits.
- One licensing question is still open. Whether an activation response is bound to a specific machine
could not be tested without a real licence.
- Two scripting questions remain open for want of a licensed copy. A project file received from someone
else might carry a script that runs when it is loaded, and an AI-assisted feature might be talked into
running one through a crafted request. Both need the paid edition to test properly, and testing them on a
patched copy would not describe a real customer's setup — so they are listed as gaps, not findings.
- The installer path has a precondition. The history file that names the fake runtime belongs to the
user doing the installing. The mechanism is proved end to end; who can write that file in a real
administrative install is argued rather than measured.
- Screenshots and a screen recording exist but were not visually inspected for this write-up; the
claims rest on the text logs captured during the same runs.
How to read the rest of this site. Use the Medium level for the same findings with the technical
names and the evidence tables. Use Expert for the complete report: full chronology, bytecode, logs,
data tables, and every limitation.
Easy · Start here
Download the full report
The complete technical report is available in two formats. Both are self-contained and identical in
content; the PDF is the print-quality rendering.
Supporting material kept alongside the report:
The report contains the material that this site summarises, plus:
- the full investigation chronology with timestamps taken from the session transcripts;
- the architecture of the licensing subsystem, class by class, with bytecode where the decompiler failed;
- the failure taxonomy (F1–F9) and the seven investigation failures;
- complete log excerpts, code listings and data tables;
- every limitation and every untested hypothesis, labelled as such.
If you only read one page of the report, read §7 (Analysis of Failure Modes) followed by
§9.2 (Recommendations). The findings are in §6, but the reason they matter — and the reason a stronger
licence check would not have helped — is in §7.