Discussion:
[whatwg] How can a server or serverside script identify if a request is from a page, iframe or xhr?
Michael A. Peters
2016-11-01 10:26:26 UTC
Permalink
I was wondering how can a server or script identify if a request is from
page, iframe or xhr?
Doing this would not prevent any XSS attacks, but it would allow a
server/server-side script to detect a potential XSS attack.
I could not find any mention of any reliable way to do this currently.
Here is an example of this idea, when the browser fetches the page the
server sends this as a response header to the browser...
RRS: *
or
RRS: url
or
RRS: iframe
or
RRS: script
And when the browser do a POST it will send one of these (if the server
sent a RRS header) ...
Any server admin that trusts a header sent by a client for security
purposes is a fool. They lie, and any browser extension or plugin can
influence what headers are sent and what they contain.

The only thing you really can do with POST is set a single use CSRF
token that the browser must include with the POST data.

If the browser does not send the token or sends an incorrect/expired
token for the session ID then the server rejects the post (I send a 403
forbidden)
Michael A. Peters
2016-11-01 10:41:39 UTC
Permalink
I was wondering how can a server or script identify if a request is from
page, iframe or xhr?
I really hate answering myself (and so soon after making a post) but it
seems I have found the answer at
https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
and the support is pretty good according to
http://caniuse.com/#feat=contentsecuritypolicy
But on MDN it says "For workers, non-compliant requests are treated as
fatal network errors by the user agent."
But does this apply to non-workers too?
And is there any way to prevent injected hostile scripts?
I guess loading scripts from a specific (whitelisted) url could do the
trick? Or maybe using strict-dynamic.
Darnit it. I may just have answered my own questions here.
Somewhere in the document (body, main, etc.) when a page is generated I
include a data-csrf attribute that contains a single use token only good
for the session id that requested the page (session id in the cookie)

Then any post submission, JS reads that token and adds it to the POST data.

In the case of Ajax submissions, the Ajax response includes a fresh
token that then gets inserted into the data-csrf attribute for the next
time the page sends a POST response.

My web apps usually put it in whatever element has the id of content so
reading it via jQuery is as easy as

$("#content").attr("data-csrf");

Then with the json response, updating it to new token is as easy as

$("#content").attr("data-csrf", json.csrf);

It allows single use tokens and makes CSRF attacks virtually impossible
as long as you have a proper crypto random string generator to create
the new CSRF tokens so they can't be predicted.
Boris Zbarsky
2016-11-01 14:02:22 UTC
Permalink
Wait, are you saying that ContentSecurityPolicy can't be relied upon?
It depends on your threat model.

Content security policy is a tool that allows a web page to defend
itself and its users from cross-site script injection attacks and the
like. A fundamental assumption here is that the user is NOT the
attacker, and hence the user's browser is cooperating with the web page
to protect the user. It's a perfectly fine tool for the "user and page
author are cooperating" threat model.

If, on the other hand, your threat model includes attacks by the _user_
on your server, you absolutely can't rely on CSP to defend against that.
Most simply, the user can use a browser that doesn't support CSP. For
addressing this class of attacks, you _have_ to rely on a completely
server-side solution, because by assumption the client (the browser) is
the attacker in this situation.

-Boris

Loading...