Mar 23, 2012

Rugged Summit Summary

I spent the last week in Washington DC as an invited expert to the Rugged Summit, part of the Rugged Software initiative.

The very minute I announced I'd be participating I got several messages on Twitter saying Rugged is a failure and I shouldn't go. Those messages were sent from people I like and trust. Sure, I was reluctant to a manifesto written to developers by security experts. Also, I hadn't heard much since the Rugged announcement in 2010.

But shouldn't I try to bring my view---a developer's view---to the table? Of course I should!

At the summit I got to work with some amazing people. Ken van Wyk, Joshua Corman, Nick Coblentz, Jeff Williams, Chris Wysopal, John Pavone, Gene Kim, Jason Li, and Justin Berman. Four very intense days. And still no silver bullet :).

Rugged Software In Short
My take on rugged is defensible software free from well-known bug types. A rugged application should be able to withstand a real attack as long as the attack doesn't exploit unknown bugs in the platform or unknown bug categories in the app. If the rugged application is breached the developers and operations should be able to recover gracefully.

Rugged also applies to operations and there's an ongoing Rugged DevOps initiative.

Why Should Organizations Become Rugged?
We first focused on *why* organizations should produce or require rugged software. Does software security also enhance software quality? Should we try to measure return on investment, reduced cost, reduced risk or what? What would make a CIO/CTO decide to go rugged?

Fundamentally we believe rugged software is part of engineering excellence. And we all need to do better. Software is enhancing our lives and revolutionizes almost everything mankind does. We want software to be good enough to enable further revolution.

Software security is currently in a state of vulnerability management. That's a negative approach and it hasn't made frequent breaches go away. Rugged is a more positive approach where you're not supposed to find a bunch of vulnerabilities in pentesting.

Here's three examples of motives for rugged we worked on.

"Telling your security story" could be a competitive advantage. Look at http://www.box.com/enterprise/security-and-architecture/ and put it in the context of Dropbox's recent security failures. Imagine the whole chain of people involved in a system being built to chip in to produce evidence of why their product or service is secure.

Another idea is to define tests that prove that you're actually more secure after becoming rugged than before. We believe executives feel security is a black art and a pentest+patch doesn't show if the organization is 90 % done or 1 % done. HDMoore's Law could be such a test (works without Rugged too of course). How to actually test against Metasploit will have to be figured out.

Third, if buyers of software started demanding more secure software that would drive producers to adopt something like Rugged. So we worked on a Buyers' Bill of Rights and a Buyer's Guide. Buyer empowerment if you will.

The Rugged Software Table of Contents
The rest of the summit was spent on various aspects of how we think software and security can meet successfully. Our straw man results will be published further on and there will be plenty of chances to help making it the right thing.

But the table of contents may give you an impression of where we're headed:

  1. Why Rugged?
  2. This is Rugged
    _
  3. The Rugged Tech Executive
  4. The Rugged Architect
  5. The Rugged Developer (I will write the first version of this section)
  6. The Rugged Tester
  7. The Rugged Analyst
    _
  8. Becoming a Rugged Organization
  9. Proving Ruggedosity
  10. Telling the Rugged Story (internally and publicly)
  11. How Rugged Fits in with Existing Work
  12. Success Case Study

Feb 18, 2012

We Need a Free Browser, Not Just an Open Source Browser

The security community was chocked when Trustwave came clean and revoked a subordinate root certificate it had sold to a third party which explicitly said it would use it to introspect SSL traffic.

The news of Trustwave's severe malpractice sparked demands for removing the Trustwave root certificates from the Mozilla trust stores (Firefox, Thunderbird, SeaMonkey). The demand was filed as a bug in Bugzilla and the issue has also gotten a fair amount of attention on the Mozilla-dev-security-policy mailing list.

We experienced the same process – Bugzilla + mailing list outbursts – during the recent DigiNotar and Comodo scandals.

Kill or Not to Kill, That's the Question
According to Trustwave they had to sell the man-in-the-middle certificate since other CAs do it. That in itself is extremely worrying. These bastards who've been charging us $$$ for maintaining trust on the Internet. They've not only been negligent in their security operations but also done business selling out the trust built in by all browsers.

So, should Mozilla kill the Trustwave root because of their misconduct? Tricky question.

On the one hand I feel Trustwave's CA business deserves nothing less than the ditch. They did the wrong thing with open eyes.

On the other hand we probably have a large scale problem at our hand – CAs worldwide have been issuing subCA certs that allow employers, governments, and agencies to intercept the traffic we all thought was authenticated, encrypted, and integrity checked. Killing the Trustwave root doesn't fix that.

Think about it. The whole trust model crumbles. Can customers now claim someone else must have manipulated their buy order for the stock that later plummeted? Can payment providers who leak credit cards now claim somebody must have MItMed them? Will the increase in online shopping continue once mainstream media understands and writes about this issue?

Whichever path we take it has to lead to reestablished trust in the CA model. The alternatives such as building on DNSSEC or Moxie's excellent Convergence are nowhere near mainstream roll-out.

But you know what? Democracy and openness seem to work. Mozilla has made the right decision.

CAs world-wide have until April 27 to come clean. Mozilla says the following on its security blog:

"Earlier today we sent an email to all certificate authorities in the Mozilla root program to clarify our expectations around certificate issuance. In particular, we made it clear that the issuance of subordinate CA certificates for the purposes of SSL man-in-the-middle interception or traffic management is unacceptable. We made it clear that this practice remains unacceptable even when the intended deployment of such a certificate is restricted to a closed network.


In addition to this clarification, we have made several requests. We have requested that any such certificates be revoked, and their HSMs destroyed. We have requested the serial numbers of those certificates and fingerprints of their signing roots so that we, and other relying parties, can detect and distrust these subCA certificates if encountered. We have requested that any CAs who have issued subCA certificates fulfill these requests no later than April 27, 2012."

Where else did you see such a clear message to the CAs who have abused our trust? Mozilla makes me proud.

We Need a Free Browser, Not Only an Open Source Browser
The handling of Comodo, DigiNotar and Trustwave tells me we truly need Mozilla and Firefox. Nowhere else in the web community have I seen such openness, freedom of speech, and focus on regular users' interests. Hey, even internet trolls get their say on the mailing list :).

Sure, I love my Chrome, I know Google is a high-paying partner to Mozilla, and I know Firefox has been lagging behind in performance and developer tools. But there's something really great and important in a free alternative.

Speaking of lagging behind ... JavaScript performance and Chrome's V8 have been industry standard for a few years. But when I run the SunSpider 0.9.1 benchmark on my new MacBook Air I get:

  • Chrome v17.0.963.56: 280.8 ms
  • Firefox v10.0.2: 233.0 ms

Therefore I would like to urge the Mozilla Foundation to get us tab sandboxing and silent auto-upgrades in Firefox so I can go all-in!

We need a free browser, not just an open source browser.

Jan 6, 2012

Stateless CSRF Protection

In the era of RESTful services and rich internet applications it's important to find security solutions that don't impose unnecessary state or computation on servers. I previously wrote a post on stateless session ids. Let's have a look at how we can protect against cross-site request forgeries (CSRF) without server-side state.

CSRF Basics
Forged requests are nasty attacks. They rely on the fact that your browser automatically adds cookies to HTTP requests if it has cookies associated with the target domain and path. That includes session cookies.

Let's say you're currently authenticated to twitter.com. If you visit another site on another domain that site can issue requests to twitter.com and your Twitter session cookie will be added to those requests.



How can domain B issue requests to domain A, formally doing a cross-site HTTP request? Well, there are some obvious cases – images, JavaScript, and CSS.

<img src="whatever.domain.org/path/logo.png" />

… is allowed from any site, which means a malicious site can contain tags like …

<img src=”https://secure.bank.com/checkAccounts" height=0 width=0 />

Such a tag will issue an HTTP GET to secure.bank.com/checkAccounts including the victim's session cookie for *.bank.com should he or she be logged in. The browser doesn't know if there's an image on that URL or not. It just fires the request. And by setting the image size to 0x0 the victim will see nothing.

CSRF With POST
Most sensitive stuff require an HTTP POST since a GET should be idempotent and not change any state server-side. So can a malicious page issue an HTTP POST to any domain? Yes.



The CSRF code from the image above ($ is jQuery):

<form id="target" method="POST" 
 action="https://1-liner.org/form">
  <input type="text" value="I hate OWASP!" name="oneLiner"/>
<input type="submit"
 value="POST"/>
</form>


<script>
  $(document).ready(function() {
     $('#target').submit();
  });
</script>

CSRF Against RESTful Services
But maybe you've left HTML forms behind and go with rich clients, a RESTful backend and communication via JSON? Can a malicious page issue an HTTP POST targeting such services? Yes.

You can change the encoding of HTML forms to text/plain and do some tricks to produce parseable JSON in the request body. Here's an example that I got working with a Java JAXRS backend:

<form id="target" method="POST" 

action="https://vulnerable.1-liner.org:
8444/ws/oneliners" 

style="visibility:hidden"
 enctype="text/plain">
  <input type="text"

   name='{"id": 0, "nickName": "John",
          "oneLiner": "I hate OWASP!",

          "timestamp": "20111006"}//'
   value="dummy" />
  <input type="submit" value="Go" />

</form>

Notice the enctype and that the JSON is in the input name, not the value. The above form produces a request body looking like this:

{"id": 0, "nickName": "John","oneLiner": "I hate OWASP!","timestamp": "20111006"}//=dummy

… which is accepted by for instance the Jackson parser.

CSRF Protection With Double Submit
Traditional anti-CSRF techniques use tokens issued by the server that the client has to post back. The server validates the request by comparing the incoming token with it's copy. But that small word "copy" means server-side state. Not good.

Double submit is a variation of the token scheme where the client is required to submit the token both as a request parameter and as a cookie.



A malicious page on another domain cannot read the anti-CSRF cookie before its request and thus cannot include it as a request parameter.



Two Misconceptions About Double Submit
There are two common misconceptions about the double submit CSRF protection.

First, it has been suggested that the session cookie should be used for this purpose. Since you have to use JavaScript to pick up the cookie value and add it as a request parameter the cookie cannot have the HTTPOnly attribute. And you want HTTPOnly on your session cookie to prevent session hijacking via cross-site scripting.

But you should not use the session cookie as anti-CSRF cookie. Instead add a specific anti-CSRF cookie which does not have the HTTPOnly attribute and keep your session cookie protected.

Second, people have stuck with server-generated, stateful anti-CSRF cookies. But double submit cookies can be generated client-side and don't have to be saved by the server at all.

Stateless CSRF Protection with Double Submit
The protective measure of double submit lies in the fact that a malicious site cannot read the cookie and include it as request parameter. That condition still holds if the cookie is generated by the client and never saved by the server.

So let the client generate the anti-CSRF value and only compare and check format of cookie and request parameter on the server. Ergo, stateless CSRF protection!



Hardening the Double Submit Protection
Double submit protection breaks down if the attacker somehow can read or set the anti-CSRF value. We can harden double submit against malicious reads.

First of all we make the client change the anti-CSRF value upon every request. This is typically done by centralizing backend calls to a custom AJAX proxy, possibly inherited.

Second, we zero the anti-CSRF cookie directly after each backend call. This will allow for accurate server-side detection of forged requests. A zeroed double submit cookie is a clear signal of either a client-side bug or a forged request. With zeroed anti-CRSF cookies the attacker has to issue his/her attack to exactly when the cookie is set by the client.

Drawbacks of Double Submit
You typically hear two drawbacks of the double submit protection – it's reliance on JavaScript to add the cookie value as request parameter, and the possibility to read the anti-CSRF cookie via cross-site scripting.

The issue with JavaScript is diminishing as JavaScript is becoming a requirement for more and more sites anyway.

The cross-site scripting critique is invalid. If you can script the site you already own all of it and can setup your own AJAX proxy, read any tokens in the DOM etc.

Dec 17, 2011

The Anatomy of a Twitter Storm

Hi! I'm @johnwilander and yesterday I unwillingly created a Twitter storm.

#GodIsNotGreat and Twitter Trends
It was Friday afternoon in Stockholm, Sweden and I came across a tweet with the interesting tag #GodIsNotGreat. Earlier that day I had read about famous atheist and writer Christopher Hitchens passing away but there was something else going on around this tag. In the tag stream I read about christians threatening tweeters using the tag and several claims that Twitter had pulled the tag from the trends list.

I couldn't find the tag in my trends list nor in the US or European list. Still, tweets with the tag were pouring in. In the stream I found a tweet from @HillyFoz saying:

"So Twitter, it's ok for #reasonstobeatyourgirlfriend to trend but you saw fit to put a stop to #GodIsNotGreat ?"

Apparently #ReasonsToBeatYourGirlfriend had been a trend. Now that's interesting too. So I wrote The Tweet what would become a Twitter storm:


As you can see in the screenshot, numerous people eventually retweeted this.

I could see the amplification within a minute. Suddenly around 10 people had retweeted it and new retweets where being reported faster than I could open them on the activity tab.

At this point I reviewed my tweet and saw that I had claimed something I couldn't back up with a source or a reference. Such things make a about-to-be-PhD blush a little :). Soon enough I started to get complaints. I considered deleting the tweet but decided to let it live on to see what this storm would be like.

Here Come the Trending Bots
Time for the first bot to spot me. Apparently I was trending in the UK:


While the retweets, complaints and comments were pouring in I quickly became a trend in USA and Canada too:



About 30 minutes later the spam bots had caught on and I started getting all kinds of weird stuff. Some of them I couldn't tell if they we're real people or bots. For instance this (not even a reply to my tweet):


I did not respond :).

The final bot step was when the @favstar50 bot congratulated me to my first 50+ favorited tweet.

Trying to Find a Source
Some of the complaints I got where getting nasty so I thought I might be lucky enough to find a source and patch my earlier tweet. UK online paper Huffington Post gave me at least half an excuse as they wrote:

"The hash tag #GodIsNotGreat also began trending, which was followed by a storm of protests by the religious, many unaware that the hash tag was a tribute to the author's passing.


Twitter reportedly removed the topic from the trending lists following threats of violence towards the creators of the hash tag. The irony that Hitchens book, one that makes stark the link between religion and violence, had stirred the religious to then threaten violence was not lost on the twitterati."

But my antagonists quickly dismissed Huffington Post as a bad source and also pointed out that they said "reportedly" which I failed to do in my 140 chars. So much for the patchwork.

The Day After
When I got up Saturday I checked my email. Well ...


I had got quite a few new followers. Woot! But I guess most of them will unfollow when I go back to tweetin' about JavaScript and application security. Easy come, easy go, huh? Note the browser tab for Twitter with 19 new notifications that dropped in while I was taking the screenshot.

I checked my Klout score:


It looks like the revenue diagrams Uncle Scrooge has on his wall :).

Later I found out that Gizmodo had written an article about it – Shutup, Twitter Isn't Censoring Your Dumb Trends. There, in the middle of their bashing was my tweet! Luckily, Gizmodo didn't dig out the source but rather took poor Jessica K's commenting retweet as an example. Phew.

Lessons Learned
My lessons learned:
  • I should probably check the sources of every tweet, not just my tech tweets.
  • Rumors spread extremely fast on Twitter. As long as the message is interesting, people retweet.
  • Twitter trends are not based on volume, they're based on derivatives, or speed if you will. If the increase of the #GodIsNotGreat tag would have been steady it would have still been a trend. But it wasn't.

Apr 9, 2011

REST and Stateless Session IDs

Nowadays there's a general reluctance to introduce (more) server-side session state because of scalability. And there's specific reluctance to session state in RESTful web services, due to design principles.

In the stateless requirement of REST we read:

"The client–server communication is constrained by no client context being stored on the server between requests. Each request from any client contains all of the information necessary to service the request, and any session state is held in the client. The server can be stateful; this constraint merely requires that server-side state be addressable by URL as a resource." [Wikipedia]

This is a tough requirement, especially if we want features such as authentication and sessions.

So, can we have session ids without server-side session state? Yes.

The Relation Between Sessions and Authentication
There's often a tight relationship between authenticating users and holding their sessions. Anonymous sessions are not very sensitive whereas authenticated sessions have to be protected against hijacking, fixation, forging, and replay. Actually, a valid session token authenticates the session, so you're basically authenticating yourself every request. Which leads us to the first stateless session solution ...

No Sessions => Authenticate Every Request
If session ids are in fact authentication tokens we might as well use the mental model of no sessions, instead authenticate each request. The old HTTP Basic Authentication does this by storing your username and password for subsequent requests. But there are more advanced versions such as authentication in Amazon's S3 REST API.

They use a custom HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code). To authenticate a request, you first concatenate selected elements of the request to form a string. You then use a shared "AWS Secret Access Key" to calculate the HMAC of that string, i.e. you sign the request. Finally, you add this signature as a parameter of the request.

GET /photos/puppy.jpg HTTP/1.1
Host: johnsmith.s3.amazonaws.com
Date: Mon, 26 Mar 2007 19:37:58 +0000


Authorization: AWS 0PN5J17HBGZHT7JJ3X82:frJIUN8DYpKDtOLCwo//yllqDzg=


Looking deeper into how this scheme works you find the following spec:


Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;


Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) );


StringToSign = HTTP-Verb + "\n" +
________Content-MD5 + "\n" +
________Content-Type + "\n" +
________Date + "\n" +
________CanonicalizedAmzHeaders +
________CanonicalizedResource;


Canonicalization of course requires some processing such as converting headers to lower-case and sorting them lexicographically. The date works as a timestamp and narrows the replay window.

The server then does the same signing with the shared secret associated with the AWSAccessKeyId. So we're switching from server-side session state to more cycles and latency on both client and server.

Worth noting:
  • Signed requests are much stronger than mere session ids. Cross-site request forgeries will be mitigated with this scheme.
  • By authenticating all requests with a shared secret we don't have any time-bound sessions or timeouts. Just fire whenever you want.
  • The persistent shared secret is much more sensitive than a temporary session id. A cross-site scripting attack will steal the shared secret which is much worse than session hijacking. This means the scheme is less suitable for browsing sessions and more suitable for machine-to-machine communication.

Stateless, Hashed Session ID and Salt
The server can generate session id cookies by hashing usernames and a random global salt:

sessionIdCookie_v1 = username ":" SHA256(username + global salt)

The salt is used for all sessions but only valid for a certain timeframe, say 15 minutes. A new salt is produced every 5 minutes and incoming session ids produced with the previous but still valid salt will be exchanged for a new session id with the fresh salt. That means a session timeout of 15-5=10 minutes.

If we truly want to go stateless we cannot kill such a session since that would require a server-side table of revoked session ids. So in the stateless case an attacker will have a 15 minute replay window in which he/she will refresh the session and have endless access.

Stateless, Encrypted Session ID
By just storing a server-side symmetric crypto key we can effectively decrypt incoming session IDs and trust their contents. Imagine a cookie based on:

sessionIdCookie_v2 = AES_GCM(128 bit key, auth tag, username + timestamp)

This means we don't have to store each session ID. Instead we pay the price of decrypting incoming cookies and checking that the timestamp is within a timeframe, say 15 minutes. For all incoming session IDs older than 5 minutes we regenerate a new cookie to effectively run a 15-5=10 minute session timeout window.

Again, if we want to go stateless we cannot kill such a session since that would require a server-side table of revoked session ids. So an attacker will have a 15 minute replay window in which he/she will refresh the session and have endless access.

Conclusion
There are three competing parameters to prioritize between:
  • Server CPU cycles per request
  • Server-side session state
  • The replay window
The tradeoff between CPU cycles and memory footprint will change with new technologies such as non-blocking IO in node.js. So yesterday's best practice might not be valid today.

The difference between regular session hijacking and hijacking of stateless session ids is that successful theft of a stateless session id authenticates the attacker even if the victim has logged out. Remember, the server doesn't store the session state. And even if the server would store the boolean isLoggedIn for each user, an old session id will still be valid if the user logs in again, as long as it hasn't timed out.

So ask yourselves what your tradeoff between CPU cycles and server-side state is. Then consider the replay+refresh leverage of a successful cross-site scripting attack.

Apr 8, 2011

Friday JavaScript & Web Dev Links

I'm summing up some reading tips for JavaScript and web development. Just thought you'd like 'em.

JavaScript

Command-Line JavaScript on Rhino
So you want to write command-line JavaScript on Rhino? Here's how you do it on Mac OS:
  1. Download Rhino 1.7R2: http://www.mozilla.org/rhino/download.html
  2. Unzip Rhino in for instance Applications/Utilities/Java
  3. Download JLine: http://jline.sourceforge.net/
  4. Unzip JLine in for instance Applications/Utilities/Java
  5. Move jline-0.9.94.jar to /Library/Java/Extensions
  6. In a shell: cd /Applications/Utilities/Java/rhino_1_7R2
  7. In the very same shell: java org.mozilla.javascript.tools.shell.Main
Code away!

Building Large-Scale jQuery Applications
A good read on RIA architecture and links to lib and framework choices, not only for jQuery junkies:

JavaScript Primitive Types Becoming Objects
About JavaScript's primitive types and how they become objects when their properties are used:

Scoping and Hoisting in JavaScript
If you haven't looked into scoping and variable assignments in JavaScript, read this and improve your programs:

'String'.replace() Only Replaces First Instance
String.prototype.replace, i.e. 'yourString'.replace(), only replaces the first instance of the regexp. So beware. Twitter made the mistake and got vulnerable because of it. Read about it and a suggested patch:

Non-Blocking JavaScript Loading (and more) With head.js
With Head JS your scripts load like images - completely separated from page rendering, and in parallel!

Web Development

RESTful Design, Patterns and Anti-Patterns
A nice webcast on REST design. For instance brings up the idea of session ids with constant state on the server. But as always, I wonder when the CSRF storm is going to hit all these REST services out there?

Chrome Web Dev Extensions
Google Chrome is becoming many web developers' favorite browser. The bundled developer tools are good. But check out the extensions too, for instance the CSS reloader:

iframe Loading Techniques and How They Affect Performance
Want your iframes to stop blocking and allow onLoad to fire earlier? Check these techniques out:
http://www.aaronpeters.nl/blog/iframe-loading-techniques-performance


Did I miss a good resource or read? Just fire away below.

Mar 24, 2011

The new security features in Firefox 4

The new security features in Firefox 4.

  • Content Security Policy (CSP). This is completely new opt-in security innovation and it's among the first to address the Internet plague called cross-site scripting (XSS). Currently Firefox 4 is the only browser supporting CSP but Webkit browsers (Chrome and Safari) are developing their own flavor. The feature lets the developer specify a whitelist of source domains for JavaScript, images, media, and styling. The servers passes on the whitelist policy in a response header and the browser then enforces the policy for all subsequent resource loads when rendering the page. CSP also demands that all JavaScript code be loaded from files and not be inline. Since XSS attack code typically is either from a domain not on the whitelist or inline, the browser will not execute it if CSP is enabled. Coming up with the correct whitelist and moving all your JavaScript to files will be a burden on developers so adoption will take time. Twitter has already deployed a CSP on mobile.twitter.com and will enable it for twitter.com after a trial period (http://engineering.twitter.com/2011/03/improving-browser-security-with-csp.html).
  • HTTP Strict Transport Security (HSTS). This is also a policy mechanism. It allows developers to tell browsers that this domain should only be accessed over SSL and the certificate may not cause any browser warnings. The policy is again sent via a response header so you would think it could be included in CSP. But there is a crucial difference. HSTS also specifies a time for how long in the future the browser should enforce it. After all the policy directive is about future requests. So the browser caches the HSTS policy for a whole domain and possibly for its subdomains which is fundamentally different from CSP which applies its policy to each page individually and allows a new policy on every request. PayPal have been one of the main contributors to HSTS and have deployed a policy for some time. HSTS is already supported by Chome and the Firefox plugin NoScript.
  • X-Frame-Options (XFO). Again, a response header security directive, originally a Microsoft innovation. It specifies whether the page should be allowed to be framed by another page or not. As such it's a partial countermeasure for clickjacking. But it really shouldn't be presented as such, rather a non-framing option for developers.
  • ES5/JavaScript Strict-Mode. Another Firefox first. JavaScript, formally named EcmaScript, is evolving and in version 5 there is an opt-in "strict mode" which gets rid of many of the nasty things in earlier versions. Attackers love the old oddities whereas developers hate them. So we can probably look forward to a fairly good adoption rate out there as soon as other browsers implement it (current statushttp://kangax.github.com/es5-compat-table).
  • Do-Not-Track (DNT). This is a privacy feature requested by the US Federal Trade Commission and jointly designed by Stanford Security Lab and Law School. It's an opt-in request header, i e sent by the browser not the server, which specifies that the enduser doesn't want to be tracked. This is of course a major issue for advertise-driven companies such as Google and Facebook who earn money on tracking endusers and serving them in-context ads. Security professionals are arguing that nobody will be able to know if they've been tracked anyway so we'll probably have to wait for large enduser adoption and a public lawsuit on some major company before DNT starts to mean something.