Juniper’s ScreenOS line of VPN boxes included a random number generator (RNG)
design that looks and behaves very much like a backdoor. This design depends on
Dual EC, an RNG designed by the NSA with a fatal flaw: if someone has the
ability to decide the curve constant Q used in Dual EC, they can potentially
predict all future outputs of the generator. Despite Juniper’s claims
otherwise, their RNG construction exposes this flaw. This ability to predict
values results in full VPN decryption capabilities for that adversary.
Additionally, at some point after this design was created, an unknown third
party modified Juniper’s codebase to include a different value of Q. This value
was presumably selected by this third party attacker, granting them this VPN
decryption ability for all ScreenOS boxes.
To be clear, we have no way of knowing how either of these Q values were
generated. In fact, its entirely possible that both values of Q were selected in
secure ways and the third party attacker changed the value just for fun. I find
that unlikely, and so I see two possible scenarios for how these Q values were
selected. In both scenarios, I assume that the third party Q value is malicious;
otherwise, why go to the effort of changing it? Then, either:
Juniper intentionally designed and implemented a Dual EC backdoor and
selected Q as such,
Juniper generated Q safely and the backdoor-like behavior is an unfortunate
cascade of unintended bugs and design decisions
At this week’s CTF team meeting, one of our members was explaining how he solved
a particular problem from RCTF last week. It was an interesting problem
that involved looking through an nginx log of a sqlmap session and determining
the flag based on the queries that sqlmap made.
At the end, once he had figured the problem out, pulling out the flag involved
taking a list of numbers in string form, and turning them into the ascii string
they represented. For instance, the array ['74', '97', '107', '101'] would
become the string Jake. He did this in python:
where list was the list of number strings. This piece of code didn’t feel
particularly intuitive to me. In order to understand what’s going on, you have
to start at the right and work your way backwards through the line to see what
operations are being performed on the list. If you try to read it in natural
language from left to right it says “Join together the result of mapping into
ascii characters the result of mapping into integers the list.”
In Ruby, this same operation would look something like this:
This version reads from left to right, like natural language “First take the
list; then map across it turning elements into integers; then map across it
turning integers into their ascii characters; then join them together.”
Of course, which of these is more readable depends about how you think about
operations. The python approach reads as composition of functions, i.e.
g(f(x)), whereas the ruby version reads as a chain of actions, similar to the
way pipes work in bash, i.e. x | f | g.
Personally, I find the latter more intuitive, but as I watched my friend type
his solution into the python console, I realized another thing that bothered me
about python’s syntax.