As far as I can tell (I can't read O'Caml very well) the crypto library underpinning this makes the same mistake that all PKCS#1 signature verification functions have had at some point or another: they unpick the padding by hand[1], and then decode the ASN1 DigestInfo. The only sane way to do this is to generate the padding from scratch and check if the signature plaintext is the same (the added benefit is your ASN1 decoder is now not on a front-line security boundary).
Is this exploitable in this bounty? No idea. At least, it's the right kind of vulnerability you need to forge a certificate.
PKCS1.5 stripping takes away the leading 0x00 0x01 0xff ... 0x00 -- if this prefix is not present, it fails.
The rest goes through the RSA tranform, and is parsed as PKCS1 DigestInfo, an ASN.1 structure. All ASN parsing checks for presence of trailing bytes, on top and in CONSTRUCTED nodes.
The presence of suffix-checking prevents malleability in my mind. Am I missing something?
ASN parsing code, in general, does not check for presence of trailing bytes (see Bleichenbacher's original signature forgery attack, and CVEs passim). Should they? Yes. Do they? No, it is a frequent implementation error.
In NSS, they did check for trailing bytes, but allowed one part of the ASN1 structure to have an arbitrary value (to work around flaws in other implementations).
To be abundantly clear: I am not saying that any of the presented code has an exploitable flaw. I am saying that the way the code is written has frequently been found to be faulty in the past.
I'm more interested in the OS they hosted their site on.
Mirage, developed in OCaml for the cloud. The part that really interested me: "If a sudden spike in traffic occurs, the web-servers can be configured to create and deploy copies of themselves to service the demand. This auto-scaling happens so quickly that an incoming connection can trigger the creation of new server and the new server can then handle that request before it times out (which is on the order of milliseconds)."
I love this idea so much. There's also OSv which targets the JVM instead of OCamL. It's an open source commercial enterprise. https://github.com/cloudius-systems/osv
I should also have mentioned that Mirage is a core component of the stack for distributed personal clouds. We need to have resilient, scalable infrastructure if we want to own a piece of the cloud for ourselves.
Are the DNS requests used only to scale up in anticipation of more traffic, or is a steady stream of DNS requests required to keep the instances running once they are started?
I see that there is an expiration TTL, but what happens if there is a download in progress for longer than the VM expiration time?
Also how well does this work with persistent HTTP connections (and TLS handshakes)? i.e. will the browser keep a persistent connection to the jitsu proxy and the actual requests might be served by different VMs?
We're actually putting a paper together that uses Jitsu so you might find that answers most of your questions (the team is busy with eval at the moment).
For the time-being, Jitsu [1] 'just' spawns a unikernel which serves requests, with no apparently latency for the requester. At some point, when the unikernel hasn't done anything for a while, it is culled (which is something of an implementation detail). In principle, we should be able to use this as part of a set of tools to create the hyper-elastic clouds mentioned upthread.
I have a bit of a problem understanding why this would be a good thing to be honest.
Capacity demand is handled by resource concurrency thresholds so why would spinning up a new OS (no matter how lightweight) be better than having non-blocking IO threads on a single kernel?
There is no reason the spun up OS can't also have non-blocking IO threads.
Mirage's philosophy is mainly about reducing attack surface and unnecessary overhead. That it makes the OS so small that you can boot it up in milliseconds is just an added benefit.
Ok, but that would only be true if I was going to spin up a new vm to join the load group / cluster but even then no one would do that unless behind a reverse proxy / waf load balancer so the attack vector angle is covered.
I'm not saying MirageOS doesn't sound neat, I'm just not yet convinced it has a general purpose use case.
Due to the startup time your average server would, in practice, still need to run an SSH server for remote administration which is a vector for attack. A MirageOS server you would instead just tear down and start a new version of.
A WAF also still passes through HTTP requests which hit Apache/nginx which calls out into the OS and altogether that give a significant surface area for vulnerability (think e.g. shellshock and ENV variables.)
I also don't think anybody says that MirageOS is ready for the general purpose use case; it's very much specific experimental tooling for (currently) really niche cases.
Unikernels do have a ton of future potential though ....
I'll be reading more into unikernels because it does seem like an interesting topic.
However, I strongly advise you to read up on how production environments are done in security conscious enterprises (banks, payment providers, etc) as you seem to make some assumptions in your comment. To give you some idea of the environments I've designed in the past:
A WAF worth it's name won't pass any request back to a webserver if it matches a known signature, method, payload, etc. This is a functionality commonly called virtual patching. SSH is usually only allowed on internal vlans and often requires some sort of external authentication mechanism like a centralised jumpserver or ldap.
Also, if using Solaris with OVM for SPARC you wouldn't boot up a new server but a non-global zone (think Docker but 2 years from now) which can be started in ~1 second and offer full isolation from the host system. AIX also does something similar and I've seen several different approaches used on Linux from LXC to VMware + F5 irule based auto-scaling groups.
A properly secured SSH server still has a bigger attack surface than no SSH server and likewise a webserver+OS behind a WAF still has a bigger attack surface then a webserver without an OS.
I guess this is defining things from a purely pragmative "more code means a bigger attack surface" perspective. I know that's an oversimplification but there's also some truth to it.
But indeed; the Solaris OVM / LXC stuff spawning minimal OS's without administrative access gets you quite close (and with a more vetted codebase,) so in that regards unikernels are indeed still mainly an academic exercise.
Are you sure? I'm usually very careful with my usage of figures of speech but I'm no language major so maybe I should clarify that I meant that I could see edge cases but not a general purpose one.
Did this clarify my point or in any other way contribute to your undestanding?
MirageOS is useful for creating single-purpose appliances. That fits well with how the cloud is used today (where you typically end up with one service/app per VM anyway). The autoscaling piece is only one aspect and is only in the early stages, so you shouldn't dwell on it.
The overview page and the ASPLOS paper (linked upthread) and the ACM article [1] will help explain the benefits and trade-offs of the unikernel approach. Other people have also started using unikernels so you can read about their experiences too [2].
I'm not keen on putting in SYN cookies and other DOS mitigations until the core TCP stack is really solid. TCP is a protocol that is a remarkable survivor in the face of small bugs that cause packet loss (fast retransmit kicks in, for example), but the manifestation of these bugs ends up being slow throughput.
The current thrust of the effort in the TCP stack is to make sure that we cover all the corner cases, and build a functional testing framework to check regressions and protocol traces versus other implementations. It's also quite remarkable how thin on the ground test suites are for TCP...
Once all this is done, then I have an alpha-grade multipath TCP implementation to merge in, and defences like SYN cookies will be parameterised options that can be activated in a unikernel in response to traffic surges.
i wasn't familiar with syncookies, but the article you linked to says
> Syncookies are discouraged these days. They disable too many valuable TCP features (window scaling, SACK) and even without them the kernel is usually strong enough to defend against syn floods and systems have much more memory than they used to be. So I don't think it makes much sense to add more code to it, sorry.
You probably only want to enable syn cookies when you are under heavy attack, but from the same article:
"I can trivially prevent any inbound client connections with 2 threads of syn flood. Enabling tcp_syncookies brings the connection handling back up to 725 fetches per second."
"This data compellingly supports the continued value of the syncookie and that position seems to have won the day."
Of course this refers to the Linux TCP/IP stack, the Mirage stack is completely different so it remains to be seen what measures will be effective against syn floods.
They seem to assume the reader has a certain level of competency with web traffic monitoring and client/server communicating tools. I suppose this is half the fun.
Still, I'm trying to figure out what they mean by
> "Before you ask: yes, Piñata will talk to itself and you can enjoy watching it do so."
Also, what should I be using to connect using TLS/TCP?
One of the ports (10000) acts like a normal TLS server, one of the ports (10001) is just used to trigger a TLS connection back to you on port 40001, and the 3rd (10002) is a TCP server that when connected to acts like a TLS client.
So to get them to talk to each other you could either write a server that listens on 40001 then proxies any incoming connections back to 10000 (that's what nothrabannosir's named pipes + nc example does), or just connect to 10000 and 10002 and pipe the two connections to each other.
e.x. in Node.js:
var net = require("net");
var server = net.connect({ host: 'ownme.ipredator.se', port: 10002 });
var client = net.connect({ host: 'ownme.ipredator.se', port: 10000 });
server.on('data', console.log.bind(console, 'server'));
client.on('data', console.log.bind(console, 'client'));
client.pipe(server).pipe(client);
Where could I, a total beginner in crypto-stuff, learn more about this kind of thing? What would be the list of things I'd need to know how to do in order to "break in", and where could I learn how to do them?
It's probably the only one that works, and it's just a hint (the conversion function is weird btw, it accepts hexadecimal symbols ranging from '0' to 'z'; it actually "decodes" any base from binary to triacontahexadecimal (36)).
Coursera/Stanford have a crypto course going on right now. It's already well under way but you can watch all the videos and (I believe) still do the quizzes and just pass on the certificate.
https://www.coursera.org/course/crypto
Bitcoin has a separate schema for signing textual messages with a special magic prefix ('\x18Bitcoin Signed Message:\n'), which would prevent such an attack.
Probably want to also go ahead and catch up on the TCP/IP stack; the pqwy/mirage-tcpip repo is some 232 commits behind mirage/mirage-tcpip, and is missing fixes for things like https://github.com/mirage/mirage-tcpip/issues/56
As Bruce Schneier pointed out [1], the price is definitely not meant to be a massive incentive -- any cryptographer worth their salt is going to be worth a hell of a lot more than our prize amount. But at the same time, we're really keen to make it easier to audit protocols in MirageOS, and hope that this Piñata "permitted breakin" is something that'll catch on. The worst case for us is that someone does break in and doesn't tell us how they did it. Let's hope the eventual winner wants to brag, and we get to improve our source code :-)
The challenge is to present a certificate that the pinata interprets as being signed by the CA at the bottom of the page. If you succeed in doing so, you will be given the information required to transfer all of the BTC out of the address listed on that page.
You can try to confuse the ASN.1 parser, or even the protocol level parser.
You can try to defeat certificate validation logic.
You can try to get handshake state-machine do an illegal transition.
You can try to smash its memory and either read it or get your code into it.
You can try to defeat its RNG.
It doesn't let you do adaptive-plaintext attacks, but everything else is up for grabs. And you don't necessarily have to wait for it to politely send you the bitcoin key - it's somewhere in there, in memory!
I think you you guys have formally proven some of this correct? What did you use? Was a proof-assistant like Coq or a model checker or similar? And what properties have been proven correct (so we know what to avoid wasting time on :)?
A bunch of people write crypto software, and want to find out/demonstrate how secure it is. They do so by setting up a system that will transfer ~$2k worth of bitcoins to the first guy who breaks it.
If you take as axiomatic that all security measures can be broken, then you can measure those security measures by the cost of breaking it.
You could measure the amount of time it takes for someone to break this security and grab the cash, but that only provides you with one datum. To really show how secure it is, you would also need to provide a $1000 prize, a $500 prize, a $250 prize, a $125 prize, and so on, all with equally strong security.
Then you start the clock. After the first prize is won, you put out the second prize and start the clock again.
Even if the winners don't share their methods, you can determine how long it took to claim the biggest prize, and compare with the length of time it takes for subsequent lesser prizes. A reduction in the interval spells trouble for your security method, because the attackers found an easier way to get in.
You can then determine the general level of effort required, when people finally stop taking the otherwise free money. If the $125 prize is claimed, and the $62.50 prize is not, you can assume that it costs between $62.50 and $125, plus a certain amount of time, to break your security.
As long as whatever you put behind that security is worth less than that amount of time and money, it will probably be safe from random attackers. Unlike an in-home safe or a bank vault, you can't take calipers and measure the thickness of the walls, to calculate how long it would take to cut through.
This contest doesn't prove anything, but it does suggest a guideline. If no one takes the $2000, then as long as the expected value of a random attack on you is not higher than that, you can feel safe using it. The problem is that it doesn't take much to rise above that amount. Late model car? Nice house? Taking an actual vacation? You're worth at least a spear-phishing attempt.
I appreciate what you're saying but even then, the data you infer this way (apart from the breach itself) is highly suspect. I don't think you really get a view for how much it costs to break and time is a poor proxy.
It tests your defense against random attackers, in the same way that a fence keeps random people off your lawn.
But it doesn't tell you anything about dedicated attackers, and those are the guys you really need to worry about. Anyone who really wants in can climb over the fence, or cut through it, or drive a tank over it.
I'm not a fan of this type of bounty myself, but it might seem like a good idea if you have enough money for a contest prize but not anywhere near what would be needed for a professional audit. Even so, if your bounty is claimed, you still might want to know how much of the work for that first attack is reusable for all subsequent attacks, and that requires a second prize.
Exactly, so if there is a breach, then we've learned about something we need to secure better (win). If there's no breach — and provided people did try to break in — then we're only incrementally more confident in the stack (kind of a cautious win).
So the server always sends the same plaintext (the private key of the bitcoin wallet), encrypted presumably by the same cipher but each time with a different symmetric key of course (negotiated by the handshake). It seems (naively, I'm sure) like this is a weakness, like you could collect a bunch of the encrypted samples, and then use the fact that they are all from the same plaintext in order to figure out what the plaintext is. How many samples would it take before you could deduce the key?
In theory, a block cipher is broken if an attacker can even tell the difference between application of the cipher and of a random permutation, different for each possible key, more efficiently than brute force (i.e. trying every possible key). Since encrypting the same plaintext with a bunch of different random permutations would not help an attacker recover it, I believe an attack like you describe would not be possible without breaking AES.
A weak RNG may create an opportunity for successful cryptanalysis. This can especially be a problems on virtual hardware/platforms that don't have a mechanism for keeping a good random seed, and have predictable hardware events, et cetera.
Is this exploitable in this bounty? No idea. At least, it's the right kind of vulnerability you need to forge a certificate.
CVE-2014-1568 was this problem in NSS.
[1]: https://github.com/mirleft/ocaml-nocrypto/blob/master/src/rs...