- From: Rich Tibbett <richt@opera.com>
- Date: Thu, 24 Oct 2013 12:05:34 +1100
- To: Device APIs Working Group <public-device-apis@w3.org>
I want us to work through a real-world UPnP compromise that has publicized recently. The specific compromise we can focus on was made against Netgear routers [1]. the tl;dr version of [1] is that, by visiting a specific URL on your router, you can gain persistent access to it and all its settings without passing through any authentication process. We could do some hand-wringing on how this happened in the first place but it would be more productive to detail how the Network Service Discovery API is capable of mitigating against such attacks. I will summarize some initial thoughts here and would welcome other input on this topic. Firstly, all existing router-level devices (including the compromised Netgear devices) would not be exposed to web pages via this API because they do not provide CORS support. To opt in to web sharing, UPnP devices need to implement CORS on specific UPnP service endpoints. It should be obvious that router-level devices and other sensitive services should not expose CORS HTTP headers and thus should never be exposed to web pages in the first place. A secondary attack vector arising here is if a web page gains access to a service residing on the same device as router functionality (e.g. I could request and be granted access to media services via CORS on a device that also implements router services). An exploit that takes advantage of this could look as follows: navigator.getNetworkServices('serviceA').then(function(networkServices) { var serviceUrl = new URL(networkServices[0].url); // http://url.spec.whatwg.org/#api var exploitUrl = serviceUrl.protocol + '//' + serviceUrl.host; exploitUrl += (serviceUrl.port ? ':' + serviceUrl.port : ''); exploitUrl += '/secondaryService/maliciousMethodCall'; // Use XHR to interact with exploitUrl... }); According to the current specification this attack vector would fail if 'secondaryService' did not implement CORS or did not provide CORS to the requesting origin. However, to initial a simple GET request to a particular URL as detailed in this particular exploit, a web page could simply do the following: var imgEl = new Image(); imgEl.src = exploitUrl; document.body.appendChild(imgEl); That would have the effect of requesting this URL via HTTP GET regardless of whether that resource is an image or not (which it clearly isn't and that device, according to [1], is now pwned). I have briefly mentioned a way we could avoid this exploit where local network urls will be obfuscated from their original host [2] thereby avoiding a leak of local network IP addresses and ports. Let's say in the example above that serviceUrl returned 'app://<uuid>/'. The original service endpoint url for this service was actually 'http://10.0.2.1:5000/myService' and app://<uuid>/ simply acts as a proxy to that URL. What this proxy does is make 'http://10.0.2.1:5000/myService' the _root_ path of 'app://<uuid>/'. Developers cannot call anything above '/myService' in the www hierarchy and developers cannot infer paths to any other potential services on the same device from the provided url. The 'app://<uuid>/' serviceUrl acts as a full HTTP proxy to http://10.0.2.1:5000/myService and any sub-resources therein (e.g. app://<uuid>/logo.png maps to http://10.0.2.1:5000/myService/logo.png, etc). Having such a concept removes the ability for a web developer to infer other service endpoint URLs from any other shared service endpoint URLs. A remaining challenge with that approach is that services, once connected to web pages via app:// based URLs. may still leak their IP address in service messaging data calls. E.g. a service providing a pointer to a media resource may transfer data via XHR to a web page that looks as follows 'http://10.0.2.1:5000/myService/_media/0123.ogg'. Exposing this URL to web pages would allow them to infer other well-known services on the same device by running the exploit code I included above. A full solution should would obfuscate both the initial service endpoint url and monitor service messaging itself with a view to obfuscating in-messaging urls via XHR. For this I propose we add an additional user agent processing step whenever a web page calls xhr.response, xhr.responseText or xhr.responseXML on an app:// URL. Primarily, the additional XHR processing step would be that if the XHR url requested begins with 'app://' then parse any response body for matches to the original URL host+port combination and replace with any matches with an app:// URL based reference to that same resource. The finer details of this process would be defined fully within the NSD API spec (I'm just presenting the main proposal for now). When we are obfuscating local network URLs at both the service sharing and service communication levels we will be able to fully isolate network services from each other. Also, the only network services that can be shared with web pages are CORS-enabled services and sensitive network resources should not expose such headers (thereby excluding them from any NSD API sharing). At this point we have successfully mitigated any exposure to the kind of attack in [1]. Other thoughts and proposals on this would be welcome, specifically mitigating or avoiding altogether the attack vectors detailed in [1]. Showing we can avoid/mitigate such attacks is an essential step in demonstrating APIs suitability. Best regards, Rich [1] http://shadow-file.blogspot.com.au/2013/10/complete-persistent-compromise-of.html [2] http://lists.w3.org/Archives/Public/public-device-apis/2013Oct/0129.html
Received on Thursday, 24 October 2013 01:06:01 UTC