2

I am developing an ASP.NET Core web api project whose only client will be a mobile app developed in Xamarin. There will be no web frontend for the application.

Can CSRF attacks be executed if the user can only login and consume the api from the mobile app?

EDIT

The api performs authentication by username and password by calling an endpoint configured with allow anonymous access. If the authentication process is successful, it returns a JWT that is used to authorize future calls.

2
  • How does the API perform authentication?
    – MechMK1
    May 15 '20 at 9:47
  • 1
    @MechMK1 please see my edit.
    – CristisS
    May 15 '20 at 10:45
3

A CSRF attack works by making the browser submit a request to another website. Because the browser automatically adds cookies to outgoing requests, the website will see that you have a valid session (assuming you're logged in at the time) and process the request, even if it came from evil.example.com. To protect from this, you verify the referrer, or add and verify some token that is not a cookie (commonly called an anti-CSRF token).

By understanding the attack and being an app developer (knowing how apps work), you might already see that CSRF attacks do not apply to apps in the same way.

If you have broadcast events that trigger an action in your app, then of course you should check with the user if they really want to do that, because any other app can trigger it (unless you require a custom permission to trigger the broadcast receiver). It's different from websites because it's intentional: you need to explicitly put in your manifest that "yes, I want others to be able to call this function". On websites, even the "delete user" feature in the admin panel is always exposed, you can't mark that as not being callable externally (anyone can browse to that URL), so to protect a website you need SameSite/anti-CSRF/referrer-checking.

In Android, you can open socket connections and do whatever. It's a proper programming language, not a browser. There is no concept of "same origin", "forbidden content types" or "forbidden headers" because you are the HTTP client, you're not asking the browser to send an HTTP request. And so it doesn't help to set things like SameSite or do referrer checking. But also, your code won't automatically add a security token to outgoing requests triggered by other apps. The only way would be if you explicitly add a broadcast event listener that lets other trigger actions in your app, but even then, the attacker can't specify the HTTP request, they can only trigger your listener to run.

An attacker can't simply (by default) make your app perform a malicious request. Anti-CSRF tokens or referer checking is not needed. You just need regular user authentication. Because the user is logged in on your app and not on the website, the attacker can't target the app's API from an unrelated webpage. An attacker can't make use of the session token (e.g. JWT) that your app obtained for the logged-in user, because the attacker can't specify a request for your app to add a session token to (unless you program it that way manually).

2
  • re: "can't simply make your app perform a malicious request", what if an attacker targeted the app's API from a non-related webpage? If webviews aren't completely sandboxed from each other, and the app uses a webview, could the attack work?
    – dandavis
    May 15 '20 at 18:32
  • @dandavis If I'm not mistaken, webview stores things like cookies in the app's folder, so e.g. /data/data/org.example.app/... so another app wouldn't simply be able to spawn a webview and get at your secret tokens. But that might be worth double-checking, even if I feel reasonably sure about this. As for talking to the API directly or from a non-webpage, then the authentication would be missing.
    – Luc
    May 15 '20 at 18:43
3

A CSRF attack can only be done with requests with those three http request content types: application/x-www-form-urlencoded, multipart/form-data and text/plain. If your end point checks the request content type and makes sure it is not one of those three, that end point is protected from CSRF. So if you make the request content type be something like application/json, and you check that in the code (not just parse http request body using a json parser but actually verify the http request content type header), then you're safe. For existing deployed APIs with clients you do not control, maybe you won't be able to do this.

Another good protection, if you need to allow cookie authentication, use SameSite: Strict cookies if you don't need to allow cross origin requests.

If the end point you wish to protect doesn't do anything without authentication and only accepts authentication using a token, not a cookie and not http basic auth, then a browser doing an AJAX request from code on a malicious site won't be able to perform an authenticated request, and that is also a complete defense against CSRF. This seems to be your case.

12
  • The first two proposals (SameSite and changing content type) don't apply to apps and won't help secure it. Your Java code is talking to the API and submitting requests, not a browser. SameSite will not do anything (the same-origin concept doesn't exist in an app because, well, it's an app and not a website running in a browser on a domain) and your code is not going to deny you to use certain content types. And if it did, your app would be broken rather than secure. The last paragraph would be a secure solution, though!
    – Luc
    Apr 9 at 11:07
  • CSRF as a concept only exists in the context of a browser and a malicious site causing the victim's browser to perform HTTP request to the site. All HTTP server security has to contend with the fact that anyone can send anything at all toward the sever, but they don't have a cookie that they can cause the browser to send.
    – Z.T.
    Apr 9 at 11:11
  • Exactly, so setting SameSite: Strict or using application/json won't prevent an attacker from sending the HTTP request, as you suggest doing in this answer.
    – Luc
    Apr 9 at 11:21
  • Of course it will protect the user. Imagine a bank has an endpoint to transfer money from logged-in user's account to a target account. The victim is logged in to this bank. They navigate to a malicious site that uses JS code to create a form to transfer money and causes the browser to submit it. If the login cookie is SameSite: Strict, then the request will be sent without the cookie, so it will arrive and be unauthenticated and the bank will not do anything. If the request has to be sent as json and the server checks that, the malicious site can't get browser to send that. Both defeat CSRF.
    – Z.T.
    Apr 9 at 11:26
  • If the attacker doesn't have the ability to use the victim's cookie that they have in their browser, there is no attack at all. Of course the attacker can use curl to send any request. But how are they getting the victim's cookie to steal their money?
    – Z.T.
    Apr 9 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.