Incomplete Implementation of CTAP2 (FIDO2) protocol in Chrome? - google-chrome

I've been investigating the implementation of CTAP2 protocol with Google Chrome (protocol between Fido Authenticator and Fido Client (e.g. Chrome)), which should be supported in Chrome since version 69.
So I dumped the chrome request to the authenticator in two cases:
1. U2F (CTAP1) with yubico demo website.
Here everything goes as expected and chrome follows the CTAP1 protocol.
2. FIDO2/Webauthn (CTAP2) with webauthn.org
And the browser has a strange behaviour:
It starts by following the CTAP2 protocol by sending a AuthenticatorGetInfoRequest
The Authenticator replies with AuthenticatorGetInfoResponse
But then Chrome switches to the CTAP1 protocol by sending a Registration Request Message (U2F_REGISTER)
Is it a problem with Chrome implementation: CTAP2 is not enabled entirely yet (it seems to be implemented in Chromium sources)?
Or is the problem coming from the authenticator: sending a response that makes Chrome switch to CTAP1?
Or something else entirely?

In AuthenticatorGetInfoRequest, the authenticator must respond with a string list of the supported versions among "U2F_V2" and "FIDO_2_0". Note also in case of NFC or CCID, a "FIDO_2_0" (CTAP2) only authenticator shall anwser directly "FIDO_2_0" on the SELECT command. I don't know about HID and BLE.
So maybe your authenticator is listing "U2F_V2" in the protocol versions list in AuthenticatorGetInfoRequest.
I also imagine the Chrome code base about this was moving fast and can be partial or not strict. To my tests in early 2020, the Chrome CTAP capabilities seem now stable and compliant.

Related

CORS on Firefox and potential help on chrom private local network access

I am currently using the FLASK developer HTTP server, and I am trying to build a local service (run on localhost) that serves files for a remote visualization website.
Here is the code for the python side
#app.route('/task/<path:path>', methods=['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'])
def static_file1(path):
p = "./task/" + path
return flask.send_file(p, conditional=True)
For safari, it just works like a charm.
As this screenshot indicates, flask development http server can serve files partially.
However, it didn't work for firefox for one request but not for the other.
And here are the headers for the first failed request
Successful request header
So I do believe the CORS header (Access-Control-Allow-Origin) is set correctly, otherwise the second request would fail.
Then what did I do incorrectly?
Second part:
It also doesn't work in Chrome, both requests failed, but I found the article below explaining new security features:
https://developer.chrome.com/blog/private-network-access-preflight/#:~:text=%23%20What%20is%20Private%20Network%20Access,to%20make%20private%20network%20requests.
But even with "Access-Control-Allow-Private-Network" set to "true" (See screenshot above), both requests still failed in chrome. And error msg:
Access to XMLHttpRequest at 'http://localhost:10981/task/a5c8616777d000499ff0cd5dbb02c957/datahub.json' from origin 'https://somepublic.website' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space `local`.
Any suggestion would be helpful!
Thanks!
Update 1:
After enabling ad-hoc SSL context (unsigned certificate) on the flask side, and using https on both localhost and "the public website", and changing the "#allow-insecure-localhost" flag in chrome to true, it works in chrome now. But still doesn't in firefox.
If you check the specification you will see that it is a "Draft Community Group Report" and
This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track.
The contribute list is made up entirely of people working for Google.
I can't find any mention of it in Firefox's bug tracker.
It looks like this is a highly experimental specification, which Firefox simple doesn't implement.
There doesn't appear to be any way to persuade Firefox to provide access from a secure, public Oritin to an insecure private origin.

How to get the Request Headers using the Chrome Devtool Protocol

The new chrome versions 72+ does not send the requestHeaders .
there was a solution:
DevTools Protocol network inspection is located quite high in the network stack. This architecture doesn't let us collect all the headers that are added to the requests. So the ones we report in Network.requestWillBeSent and Network.requestIntercepted are not complete; this will stay like this for the foreseeable future.
There are a few ways to get real request headers:
• the crude one is to use proxy
• the more elegant one is to rely on Network.responseReceived DevTools protocol event. The actual headers are reported there as requestHeaders field in the Network.Response.
This worked fine with the old chromes but not with the last versions. here is a small summery I made for the versions a coulded test
a solution for chrome v67 was to add this flags to disable Site Isolation :
chrome --disable-site-isolation-trials --disable-features=IsolateOrigins,site-per-process --disable-web-security
Now all of this does not work with the last chrome v73
maybe it is caused by this:
Issue 932674: v72 broke devtools request interception inside cross-domain iframes
you can use Fetch protocol domain that is available since m74
the solution gaven does not work neither, the Fetch.requestPaused does not contain the request headers...
I found some info that maybe causes that:
DevTools: do not expose raw headers for cross-origin requests
DevTools: do not report raw headers and cookies for protected subresources. In case subresource request's site needs to have its document protected, don't send raw headers and cookies into the frame's renderer.
or it is caused when it is an HTTP/2 server?
Does the HTTP/2 header frame factor into a response’s encodedDataLength? (Remote Debugging Protocol)
...headersText is undefined for HTTP/2 requests
link
1- How can I get the Request Headers using the Chrome Devtool Protocol with chrome v73+?
2- Can a webextension solve that?
3- Is there another way which will be stable and last longuer? like tshark+sslkeylogfile which I'm attempting to avoid. thank you

Do Mobile Browsers send httpOnly cookies via the HTML5 Audio-Tag?

I try to play some mp3 files via the html5 audio-tag. For the desktop this works great (with Chrome), but when it comes to the mobile browsers (also Chrome (for Android)), there seem to be some difficulties:
I protected the stream with some password an therefore the streaming server needs to find a special authentification cookie (spring security remember-me). But somehow the mobile browser doesn't send this cookie when it accesses the mp3-stream via the audio tag. When I enter the stream URL directly to the address bar everything works just fine.
While I searched for the lost cookie I found out, that the mobile browser still sends some cookies (e.g. the JSESSIONID) but not all. Further investigations (quick PoC with PHP) revealed that the mobile browsern seems to refuse to send cookies via the audio-tag which have the HttpOnly Flag set. So my question is:
Is this a specified behaviour, why are there differences between the mobile and the desktop versions (of Chrome) and is there a way control the behaviour from the client side?
By looking more deeply into the HTTP packages I found out, that the Android browser doesn't request the mp3-stream itself, but delegates this to stagefright (some android multimedia client). A quick search revealed, that for the old Android versions (before 4.0) stagefright cannot handle cookies:
https://code.google.com/p/android/issues/detail?id=17553 <-- (Status: spam) WTF...
https://code.google.com/p/android/issues/detail?id=17281
https://code.google.com/p/android/issues/detail?id=10567
https://code.google.com/p/android/issues/detail?id=19958
My own tests confirmed this. The old stagefright (Android 2.3.x) doesn't send any cookies at all, the stagefright from a european S3 (android 4.1.2, stagefright 1.2) sends only the the cookies which do NOT have the httpOnly flag.
So I think that everybody has to decide himself which solution he wants to use:
enable httpOnly: android has no access at all but its secure
disable httpOnly: less secure against XSS, but works for Android >4.0
disable cookie authentication at all: insecure but works for all
Note: The problem with simply disabling httpOnly is that you make your whole application vulnerable to cookie hijackers. Another possible solution would be to have a special rememberme cookie for the stream (without httpOnly) and another rememberme cookie with httpOnly enabled.
I had the same problem and disabling HttpOnly or Secure flags on cookies didn't solve the problem on Android 4.2 and 4.4 chrome browser.
Finally I figured the cause. I had a cookie with its value containing special characters colon ( : ) and pipe ( | ), etc. After disabling that cookie with special characters the videos play fine in Android 4.2 and 4.4.
Hope this helps someone.

Chrome extension to listen and capture streaming audio

Is it possible for a Chrome extension to listen for streaming audio from any of the browser's tabs? I would like to capture the streaming audio data and then analyse it.
Thanks
You could try 3 ways, neither one does provide 100% guarantee to meet your needs.
Before going into more detailed descriptions, I must note that Chrome extensions do not provide convenient tools for working on per connection level - sufficiently low level, required for stream capturing. This is by design. This is why the 1-st way is:
To look at other browsers, for example Firefox, which provides low-level APIs for connections. They are already known to be used by similar extensions. You may have a look at MediaStealer. If you do not have a specific requirement to build your system on Chrome, you should possibly move to Firefox.
You can develop a Chrome extension, which intercepts HTTP-requests by means of webRequest API, analyses their headers and extracts media urls (such as containing audio/mpeg MIME-type, for example, in HTTP-headers). Just for a quick example of code you make look at the following SO question - How to change response header in Chrome. Having the url you may force appropriate media download as a file. It will land in default downloads folder and may have unfriendly name. (I made such an extension, but I do not have requirements for further processing). If you need to further process such files, it can be a challenge to monitor them in the folder, and run additional analysis in a separate program.
You may have a look at NPAPI plugins in general, and their streaming APIs in particular. I can imagine that you create a plugin registered for, again, audio/mpeg MIME-type, and receives the data via NPP_NewStream, NPP_WriteReady and NPP_Write methods. The plugin can be wrapped into a Chrome extension. Though I made NPAPI plugins, I never used this API, and I'm not sure it will work as expected. Nethertheless, I'm mentioning this possibility here for completenees. This method requires some coding other than web-coding, meaning C/C++. NB. NPAPI plugins are deprecated and not supported in Chrome since September 2015.
Taking into account that you have some external (to the extension) "fingerprinting service" in mind, which sounds like an intelligent data processing, you may be interested in building all the system out of a browser. For example, you could, possibly, involve a HTTP-proxy, saving media from passing traffic.
If you're writing a Chrome extension, you can use the Chrome tabCapture API to record audio.
chrome.tabCapture.capture({audio: true}, function(stream) {
var recorder = new MediaRecorder(stream);
[...]
});
The rest is left as an exercise to the reader; MDN has more documentation on how to use MediaRecorder.
When this question was asked in 2013, neither chrome.tabCapture nor MediaRecorder existed.
Mac OSX solution using soundflower: http://rogueamoeba.com/freebies/soundflower/
After installing soundflower it should appear as a separate audio device in the sound preferences (apple > system preferences > sound). Divert the computer's audio to the 2ch option (stereo, 16ch is surround), then inside a DAW, such as 'audacity', set the audio input as soundflower. Now the sound should be channeled to your DAW ready for recording.
Note: having diverted the audio from the internal speakers to soundflower you will only be able to hear the audio if the 'soundflowerbed' app is actually open. You know it's open if there's a 8 legged blob in the top right task bar. Clicking this icon gives you the sound flower options.
My privoxy has the following log:
2013-08-28 18:25:27.953 00002f44 Request: api.audioaddict.com/v1/di/listener_sessions.jsonp?_method=POST&callback=_AudioAddict_WP_ListenerSession_create&listener_session%5Bid%5D=null&listener_session%5Bis_premium%5D=false&listener_session%5Bmember_id%5D=null&listener_session%5Bdevice_id%5D=6&listener_session%5Bchannel_id%5D=178&listener_session%5Bstream_set_key%5D=webplayer&_=1377699927926
2013-08-28 18:25:27.969 0000268c Request: api.audioaddict.com/v1/ping.jsonp?callback=_AudioAddict_WP_Ping__ping&_=1377699927928
2013-08-28 18:25:27.985 00002d48 Request: api.audioaddict.com/v1/di/track_history/channel/178.jsonp?callback=_AudioAddict_TrackHistory_Channel&_=1377699927942
2013-08-28 18:25:54.080 00003360 Request: pub7.di.fm/di_progressivepsy_aac?type=.flv
So I got the stream url and record it:
D:\Profiles\user\temp>wget pub7.di.fm/di_progressivepsy_aac?type=.flv
--18:26:32-- http://pub7.di.fm/di_progressivepsy_aac?type=.flv
=> `di_progressivepsy_aac#type=.flv'
Resolving pub7.di.fm... done.
Connecting to pub7.di.fm[67.221.255.50]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [video/x-flv]
[ <=> ] 1,234,151 8.96K/s
I got the file that can be reproduced in any multimedia pleer.

How can I make Chromium send the new WebSocket handshake?

I came across this code change in Chromium. It says Chromium now supports both handshake versions, which the code seems to confirm. I mean the second version at Wikipedia (draft-ietf-hybi-thewebsocketprotocol-06).
However, when I connect to my server, the only thing I obtain is the old version, i.e. including these headers:
Sec-WebSocket-Key1: 4 #1 46546xW%0l 1 5
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
but not the new version which would be a request containing:
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
What am I missing here? I downloaded the latest nightly build and it has been included more than two weeks ago, so that cannot be the cause I guess.
How can I make a WebSocket send the new handshake version?
The code link you posted is for the server-side of the handshake (there is a few places this will likely be used in Chrome such as remote debugging and as a proxy for extensions).
If you really want use the new HyBi-07 protocol version you can try using this branch of web-socket-js that I made. Once Chrome switch to the new protocol, web-socket-js will switch by default also. In order to make web-socket-js work in a browser that already has WebSockets support you will need make some minor tweaks to it to use a different object name instead of WebSocket.
I expect Chrome/WebKit will add the new protocol before long. Note that the API changes to add binary support have only recent been decided so Chrome the new protocol may be added before the API fully supports the new functionality enabled by the protocol.
The only browser I know of that implements the 07 protocol is this build of FF4:
http://www.ducksong.com/misc/websockets-builds/ws-07/