Is it ok to use wildcard CORS with a csrf token?

Viewed 525

I usually add * as the CORS allow origin header during development and wondered if I even have to change that if I use a csrf token to secure my site from forged requests.

2 Answers

The base case for CSRF protection are requests that actually change something on the server. If it's just a GET that doesn't change stuff, you are good to go, because the same origin policy in browsers will not allow an attacker website to create requests to the original site (through a valid, logged on user's browser of course). So there is the same origin policy as protection for GETs.

Until you add access-control-allow-origin: *. With that, a malicious website can contain Javascript to download data from your service, and will be able to access the response - because you allowed it to.

Of course if there is something like a header-sent token authentication or similar so that this is not possible, then you are good to go. But the question was whether * in the CORS header is ok if you have the standard CSRF protection - and unfortunately it is not.

Its definitely not secure. You are circumventing the same origin policy. A concrete example: You have a webshop and an endpoint to change a users bank account http://mycoolwebshop/api/v1/users/3/changebankdata This endpoint can be called via an Ajax POST request. At every request, you are attaching the csrf token as HTTP header.

An attacker could forge a malicious request that is sent when the victim clicks a button on the attackers website:

<html>
<body>
<script src="https://code.jquery.com/jquery.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
    $( document ).ready(function() {
            csrf_token = document.cookie.match("CSRF-TOKEN");
            csrf_token = csrf_token["input"].split("=")[1];
        $("button").click(function(){
            $.ajax({
            url: "http://mycoolwebshop/api/v1/users/3/changebankdata",
            type:'POST',
            contentType: "application/json",
            xhrFields: {
                withCredentials: true
                },
                data: JSON.stringify({ Bank-Account: "01234345" }),
            dataType: "json",
             headers: {
                "CSRF-TOKEN":csrf_token
                },
            success: function(){
                alert("ok");
            },
            error: function(jqXHR, textStatus, error){
                //alert(textStatus);
            }
        });
    });
});
</script>

<button></button>

The idea is here that the cookie is read from the browser's cookie store and attached as a custom HTML header. However, this only works if CORS allow origin is set to * otherwise SOP doesn't allow custom request headers from cross domains.

Related