The Tangled Web: A Guide to Securing Modern Web Applications (2011)
lcamtuf.coredump.cx
lcamtuf.coredump.cx
At Matasano, we gave The Web Application Hacker's Handbook to candidates to cover that gap.
I think it happened quite a bit earlier (perhaps 2005 -> 2010), at least when you look at some of the "prime" web properties. Gmail or Google Docs in 2010 were already pretty close to what we have today. Hard to believe, but XMLHttpRequest actually dates back to 1999! JSON isn't much younger.
I don't think the models of web development have changed dramatically since the publication of TTW. There are some other, more incremental changes that aren't reflected in the current edition - there are two examples in my other comment here (Service Workers, parser harmonization, etc) - but by and large, the content should be still largely relevant.
Then again, I keep pointing out that in addition to rest, there's a architecture for "movable code" in Fielding's paper as well (and rpc, as distinct from rest).
A number of things:
* framework - use popular, battery-tested framework. Avoid new shiny HN front-page framework for production. If you want to experiment with it, and eventually replace the old framework, then wait until the community is strong enough.
* frontend - mostly HTML/CSS/JS, we carry too much legacy baggage: years of hacks and workarounds in the spec and in implementation. Make smart use of CSP.
* backend - quite stable these days if you first take care of your server. However, sanitizing inputs and outputs is both context-sensitive and challenging. Don't forget about sandboxing, authorization and state eviction, and keys management (api keys, user keys, server keys, automation keys such as Jenkins credentials).
* package management - there are vendors and SaaS (Github, and I think Gitlab too?) provide alerts and reports on software dependencies updates, so we are doing slightly better in this area.
The entire stack of an application is not as simple as putting a pipe system together, indeed.
I would say to use frameworks to your advantage, but remember to look under the hood. There’s no substitute for understanding the entire stack and knowing what your tools are doing.
Yeah, proper authorization is complex.
With that mindset, I'll not be surprised if people just send raw json to the client and "filter access" in javascript...
[1] https://www.dbrnd.com/2016/08/postgresql-9-5-row-level-secur...
https://www.postgresql.org/docs/current/static/ddl-rowsecuri...
[ed: apparently there's some hope: https://www.graphile.org/ ]
I would not be so sure about that. Chances are a lot more is being hacked than ever is published / discovered.
Some aspects have gotten better. Flash is dying, for example, and that's a huge help (I remember when the email showed up in my inbox from the Rails team, passing along that Google had informed them the same-origin sandbox was broken thanks to a Flash bug...).
Other aspects have gotten worse. The sheer number of new APIs in browsers, accessible via JavaScript, is frightening. And plenty of the problematic old ones are still around too. Plus ways to turn security features into privacy invasions (like the HSTS supercookie, which is both cool and makes me want to quit everything forever).
If you have even a small amount of interest in passive recon, it is excellent- http://lcamtuf.coredump.cx/silence.shtml
Some things have changed for the better. For example, there's been a push to harmonize the behavior of some of the core parsers and APIs. Say, we now have less variability in how HTML is handled across different browsers.
On the flip side, there are also several new APIs and JS features that have some scary security implications. Service Workers come to mind.
The near-complete demise of Java and Flash are the two other major changes since 2011.
Either way, the book should still give you a very robust understanding of the fundamentals (and a mental framework to evaluate the dangers of some of the new stuff).
[1]: https://frederik-braun.com/sw-sri-challenge.html
[2]: http://blog.airbornos.com/post/2017/08/03/Transparent-Web-Ap...
- There's an "updatefound" event with which you can listen for updates to the Service Worker
- You can request the new SW file from browser cache with: fetch('/serviceworker.js', {cache: 'only-if-cached', credentials: 'same-origin', mode: 'same-origin'})
You would hope that that's all you need (just register for updatefound in the SW file, and when it updates, check the new one, if verifying fails, warn the user). Unfortunately, the new SW can kill the old SW with skipWaiting(). I opened a bug to try and fix that [1].
In the meantime, you could instead listen for the updatefound event in the web application. However, the example fetch() above would go through the new SW, which is no good, but...
- You can bypass the SW from the web app, but only by basically relying on a bug in the spec: if you send a request from an <iframe srcdoc="..."> (or data/object url) it doesn't go through the SW. That will probably be fixed, but a less hacky mechanism will probably replace it [2].
There are some other remaining issues (some of which are discussed in [1]), but given the above the probability of detection of a malicious Service Worker is very high.
To add insult to injury, the Internet Assigned Numbers Authority added a fair number of top-level domains in recent years (for example, .int and .biz), and it is contemplating a proposal to allow arbitrary generic top-level domain registrations. If it comes to this, cookies will probably have to be redesigned from scratch.
If they ever decide to relax the rules, it may become a bigger deal.
It seems like the "everybody is doing it this way" thinking is currently about having strong server side security. But I believe that fundamentally opens/leaves-out the browser as a loophole.
Yet the common criticism against end-to-end encryption in the browser (even with the native Web Crypto API) is that JS-land can never be treated seriously (and you probably shouldn't).
BUT I feel like that leads to not even trying, and adding anything is better than nothing. So I/we/others are trying (for instance, see this HackerNoon article on "How to Build a P2P end-to-end encrypted Twitter" http://hackernoon.com/so-you-want-to-build-a-p2p-twitter-wit... ). Because my philosophy is that no matter how insecure JavaScript may be, it is a whole let less secure than trusting a 3rd party corporation (Google, Facebook, whoever) with your data openly, that you then hope they keep secure -- that just seems like ignorance.
Yet, I doubt people will come around to this for a long time (they'll be pushed into it because of Bitcoin and other forces), but it doesn't seem popular amongst the "this is how we've always done it" way of thinking.
Shouldn't we at least push in that direction? The ideal: Hardware wallets that trusted-open-source-verified-auditied web browsers have JS APIs that pass-through to. Then JS doesn't handle it, it won't be in browser memory, and even if the OS is compromised you'd have to be at Intel-level spectre meltdowns before the hardware wallet can be cracked.
Admittedly, I feel naive even hoping/thinking/believing that such security could/would/will exist given how many things could go wrong. But again, I still feel like that is better than central servers storing all our data maybe-encrypted.
I recently wrote a browser extension that verifies (using PGP) the integrity of the page, and thanks to subresource-integrity also the integrity of external scripts and css, making it possible to trust that the JavaScript application you are running is what the developers intended you to be running. Making E2E encryption in the browser much safer. Just to give a counter to your "is that JS-land can never be treated seriously" statement. Link: https://github.com/tasn/webext-signed-pages/
It's used by EteSync to secure its web client.
Note: I do believe JS ought be taken seriously but I can't ever seriously tell that to people because nobody does. But I hope because of projects like yours that people stop having arguments against it. Great job, let's chat.
The browser extension works great with browsers, but it's lacking with PWA, and this fills in the gap. \o/
If you don't - visiting the signed pages won't do anything. The extension would just say "no signature expected" and won't even show there is something (i.e. no "noticed an unknown untrusted signature" statuses).
- Do you see any issues with detached signatures? Modifying HTML file is complicated, adding a <link rel="openpgp signature" href="page.html.sig" /> (included into the signed content) is easy and doesn't require any custom tooling for signing. Just `gpg --armor --detach-sig page.html` and everything's ready.
I have this (not exactly) as one step of a staging CI pipeline:
[ -z "${SIGN_PRIVATE_KEY}" ] || (
gpg -v --import <(echo "${SIGN_PRIVATE_KEY}") &&
find ./output -type f \( -name "*.html" -o -name "*.pdf" \) -exec gpg --armor --detach-sign '{}' \;
)
And it just works, no extra requirements. Very similar principle is applied to production system, but with manual signing (`make sign`) rather than CI-entrusted key.But then I don't have a browser extension, but a small watchdog daemon in Go (using golang.org/x/crypto/openpgp) that does the checks for me.
- Or, why not HTTP headers? Something like "X-OpenPGP-Signature" or RFC6648-compliant "vnd.com.stosb.gpg.signature" would also work. HTTP trailers are also an option, I guess, but they're more obscure stuff so probably a worse idea (unless server has the subkey and signs dynamic content on the fly - then trailers can be useful, as opposed to buffering data).
I am using GnuPG signing to verify that some pages weren't tampered with. But I've used detached signatures instead. Initially, I've had an idea of embedding signatures inline, but I found it much easier to implement, and the only downside was that both files had to be updated simultaneously, possibly complicating the deployment logic. I've just tolerated possible deploy-time warnings, keeping check that monitoring status get back to green in a second, but e.g. deploying to a different directory and atomically replacing a symlink should've worked, as well as using Docker containers and re-routing traffic.
I nearly flagged it but I think I'll hold off and see if linking to ads is the new norm here, because I haven't noticed that before.
Edit: whoops, should have read this before posting "Please don't complain that a submission is inappropriate. If a story is spam or off-topic, flag it. Don't feed egregious comments by replying; flag them instead. If you flag something, please don't also comment that you did." Apologies, I'll leave my original comment for the curious but won't ask this question again.
Likewise, if an intelligent person writes a useful book or service (Show HN), what is inappropriate about sharing it?
I flagged it.
If you flag something, please don't also comment that you did.
Also I think that is more about comments that are nothing more than saying you flagged something. If a comment is acceptable without the words "flagged" then it should be acceptable with those extra few letters.
I have noticed a lot of quasi press releases and advertisements on the site lately.