Skip to Content

Gateway REST services open up the SAP landscape for consumption and operation from clients outside that trusted SAP landscape, including those evil browsers. Evil as we all know, the web cannot be trusted. A critical aspect in the Gateway architecture is therefore to mitigate the impact of web-based security attacks.

Cross-Site Request Forgery (CSRF)

One of the most exploited security vulnerabilities on the web is cross-site request forgery. The essence of a CSRF attack is that a malicious site misleads a trusting site in believing that a transactional request comes with approval of the user. The working of a CSRF attack is as follows: 1) after the user has set up an authenticated session with an application site, 2) the user while still within this authenticated browser session visits a malicious site, and 3) the malicious site tricks the user in sending requests to the application site that are actually constructed by the malicious site. Misleading the trusting site that the request comes with approval from the authenticated and authorized user, while in fact it originates from a malicious site. Hence the name cross-site request forgery.

The success of CSRF attacks depends on 3 factors:

  1. The ability to load malicious javascript code within the authenticated browser session.
  2. The ability to misuse the user authentication to the application site. In most browser/webapplications scenarios the user’s authentication state is maintained in cookies after successful authentication – required to preserve the authenticated state. If the malicious site can lure the user into sending a malicious request from the authenticated browser session, that request will automatically include all cookies including the authentication state. And thus be authorized to the trusting site without the user being aware nor approved the request.
  3. The predictability of the transaction request, so that the malicious site is able to automatically construct a request that will be serviced by the trusting site.


The first factor is common exploited by social engineering. The user is somehow seduced to load javascript code from the malicious site into the current browser session, without the user even be aware. Typical example is to send an email to user with hidden javascript code, and when the user opens it a request is send to malicious site. The protection against this risk are a combination of tooling – mail filters; and educating the users – do not just open any received mail. Although the quality of both security measures increases (yes, users are also more and more aware of the risks on the web), this protection is certainly yet not 100% foolproof.Note that this factor is only present if the consumption of the webservices is via a browser. In case of a native application, and also in case of an embedded browser in native App (e.g. Fiori Client, Kapsel, Cordova), the user cannot visit others sites and have its client context become infected / compromised.The second factor is inherent present in all browsers. Without it, each request send from browser would first need to go through the authentication protocol with the remote webapplication, involving browser redirects, identity stores. And in case of username/password browser logon, the user would have to reenter his/her credentials over and over again. Thus: preserving the authentication state after initial authentication is needed to avoid the processing and elapse time for the authentication protocol handling, and to prevent unhappy users. User-friendliness and security are often in contradiction.

Protection against CSRF attacks: CSRF Token

CSRF protection focusses on the 3rd factor: make sure the request cannot be (automically) predicted and thus constructed. Introduce CSRF Token protection.The essence of CSRF Token protection is that the token is a secret key that is only known to the authenticated browser session and the trusting site, and that the authenticated browser session must include in each modifying request to the trusting site in order to convince the trusting site that the request is coming with consent from the user.CSRF token protection is utilized on modern webapplication platforms, including SAP ICF, Microsoft IIS, …

CSRF protection applied in Gateway

SAP Gateway applies the following protocol to protect against CSRF:

  1. The user opens in browser a session with the Gateway based webapplication, and must first authenticate. This can be via any of the authentication methods: username/password, integrated Windows Authentication, X.509, SAML2, OAuth. After successful authentication, the browser has established an authenticated user-session with this trusting web application.
  2. The webapplication code loaded in the browser (HTML5, JavaScript) invokes HTTP GET requests to the Gateway REST services to retrieve data. The GET request can only be used to retrieve data, not to request a modifying transaction on a Gateway service.
  3. In case the client application wants to execute a transaction via Gateway REST service, it must invoke this via a POST, PUT or DELETE request. To ensure to the trusting Gateway REST service that the transaction request indeed originates from the user through the client application, the request must be signed with a CSRF-Token as secret key only known by the client application context and the Gateway webapplication.
  4. The CSRF-Token must be requested by the client application from the Gateway webservice. This can only be done via a non-modifying HTTP GET request. If the client application needs the CSRF Token for subsequent transactional request(s), it must include header variable X-CSRF-Token with value ‘FETCH’ in a non-modifying HTTP Get request send to the Gateway service. As all browsers enforce same-origin policy, the browser will only send HTTP GET requests issued from resource/code loaded in the browser that has the same origin/domain as the Gateway REST service. When code loaded via another (cross) site tries to send the HTTP GET request, the browser will refuse to send it.
  5. Gateway webservice only serves request to return X-CSRF-Token for non-modifying HTTP GET Request. It is not possible to retrieve the X-CSRF-Token via a modifying HTTP PUT/POST/DELETE action. Reason is that these requests are not subject to same-origin policy, and thus can be issued from code loaded from another domain (note: the essence of JSONP crossdomain handling).
  6. When Gateway receives a non-modifing GET Request with header variable ‘X-CSRF-Token’ equal to ‘FETCH’, it random generates a new token and returns the generated value to the requesting client in the response: via header variable and cookie. As result of same-origin browser policy, cookies can only be read by javascript code originating from the same domain. Malicious code loaded from another domain cannot read the cookie nor header variable. Also the random generated value cannot reasonable be guessed by the malicious code.
  7. The client application reads the CSRF Token from the HTTP GET Response, and includes the value as header parameter X-CSRF-Token in modifying HTTP requests to Gateway webservice. As the token value is also returned in GET ‘FETCH’ response via cookie, the value will also be included as cookie variable in each subsequent request from the client application in the current browser session.
  8. When Gateway receives a modifying request, SAP ICF runtime inspects the request on presence of X-CSRF-Token in both request header as in cookie. If present in both, it next compares the 2 values. Only if present and equal, the modifying request is guaranteed to come from the client application context, and is granted for execution by the Gateway REST service.

Proofing of Gateway CSRF protection

As stated above, a CSRF attack depends on the ability for malicious site to automatically construct a malicious request, that next the user is somehow lured into sending to the trusting site, and that is well-crafted to mislead the trusting site that the request is with the approval of the authenticated user.

The URL, including REST action is typically static; and could reasonable be ‘guessed’. And as same-origin only applies to HTTP GET request, it is also possible to send PUT/POST/DELETE requests that originate from the malicious site. But in order to have SAP ICF and thus Gateway trust and next execute such a transactional request, the request must be signed with the CSRF-Token as secret key in request header + cookie. The browser automatically includes all the cookies in the request. But the request header is not automatically reused/added by the browser, and the malicious code must therefore explicly set it in the XmlHttpRequest. However the CSRF Token value can only be retrieved and read by JavaScript code that originates from the same domain as the Gateway webservice. Not from JavaScript code that originates from another, external domain. Therefore the malicious code cannot reasonable construct a complete transaction request that includes the proper value of CSRF Token in both request header and client cookie. And Gateway is enabled to detect the malicious request as not being legitimate.

Note: this posting is earlier published on my personal but professional blog on Gateway Development subjects / http://wvstrien.blogspot.nl/2014/08/gateway-protection-against-cross-site.html

To report this post you need to login first.

56 Comments

You must be Logged on to comment or reply to a post.

  1. Ashwin Dutt R

    Hello William,

    Thanks for sharing the info here 🙂

    Everybody has the questions regarding CSRF Token and here its

    very well explained and its really helpful to understand how exactly things work with CSRF Token in GW.

    Great.

    Regards,

    Ashwin

    (0) 
    1. William van Strien Post author

      Hi Jitendra,

      the Gateway / ICF issued token is valid during the lifetime of the ICF / SAP session; if that is expired then the token will become invalid. Your session will be kept alive if the webapplication client makes requests to it; if within the hour no requests are made it is likely to be expired and you need to set up a websession. Note that you then also will have to re-authenticate with Gateway to instantiate a new authenticated session.

      My advice: either you apply a ‘optimistic’ approach, re-use the within client maintained / cached CSRF token for POST / PUT / DELETE later on, and if Gateway responds with invalid token; then ‘refresh’ the token by issuing a GET Request, and next repeat the POST/PUT/DELETE.

      Or always for any POST/PUT/DELETE request first make sure you have a valid CSRF Token by always preceeding it with a GET request.

      Given your timespan of an hour, I advocate in this scenario the latter approach; as likely the CSRF token will no longer be valid and needs to be refreshed.

      Regards, William.

      (0) 
      1. Jitendra Kansal

        Hi William,

        I believe second approach would be fine. Let us try on this. Will get back to you if i need any inputs from you.

        Thanks for tips.

        Rgrds,

        JK

        (0) 
  2. Prabaharan Asokan

    Hello William,

    1.Is it possible to identify from which domain we are getting HTTP requests(GET or POST) in a Gateway OData service? So that i can neglect all other domains and pass data to the requests only when they come from specific domain.

    2.Currently we are using HTML5 webapps. Codes are easily vulnerable and can be hacked using developer tools(Be it chrome or IE). Is there any authentication mechanism to handle data/code security.

    Regards

    Prabaharan

    (0) 
    1. William van Strien Post author

      Hi Prabaharan,

      1) this kinda sounds as if you want to implement your own CSRF. Is the context non-browser, so that you cannot rely on same-origin protection?

      At http level you can inspect the referrer of the request; and then use a whitelist approach to execute the requests only for trusted referrers; or a blacklist to deny specific non-trusted. Be aware that Gateway standard CSRF still must be honoured, SAP ICF will block updating actions if not conform the CSRF requirements.

      2) That is not a CSRF situation; here the user is very much aware of that (s)he is trying to hack the system.

      Regards, William.

      (0) 
  3. Syam Babu

    Hi William.

    Fantastic Stuff on CSRF.

    Just have small question.How it will works while performing batch operation with multiple requests like (PUT/POST).

    Thanks,

    Syam

    (0) 
    1. William van Strien Post author

      Hi Syam,

      Thanks, glad you like.

      Wrt batch; the X-CSRF-Token is set in the Header of the POST request that collects the batched command in it’s request body, and that is submitted to the $batch endpoint of the service

      Example:


      POST https:/<server>/sap/opu/odata/<namespace>/<servicename>/$batch

      Authorization: …

      Content-Type: multipart/mixed; boundary=batch(36522ad7-fc75-4b56-8c71-56071383e77b)

      X-CSRF-Token: …


      Regards, William.

      (0) 
  4. Syam Babu

    Hi William,

    I have few questions as given below.

    1) Is there any time out options for CSRF Token?

    2) Will metadata fetch the CSRF Token or how to fetch CSRF tokens if I don’t have GET method implementation.

    Thanks,

    Syam

    (0) 
    1. Ashwin Dutt R

      Hello Syam,

      Just sharing info.

      1. I do not know the exact time frame when token gets expired. For sure there is some time frame.

      William can give more info on that 🙂

      But once the user is idle for some time, then token gets expired for that session.

      2. Yes u can use metadata URL of a Create Service to get the token.

      Since getting metadata is a GET operation , token can be fetched from metadata URL as well 🙂

      Regards,

      Ashwin

      (0) 
    2. William van Strien Post author

      Hi Syam, Ashwin (thanks for answering ahead 🙂  )

      1.) Yes, there is expire behavior in Gateway to prevent same token to be accepted indefinitely. Actually, the Gateway X-CSRF-Token value is session based; and will remain valid for duration of the authenticated SAP session between Gateway client and Gateway server. The proposed protocol is that you either FETCH the X-CSRF-Token upon application start, or first time you need it (JIT).

      But be aware that in case of webapplication (SAPUI5, Fiori, any other HTML5 (knockout.js, angular.js, …)), the SAP session may expire although the application itself is still displayed in your browser. This occurs if the user is not actively using the app for a period beyond the configured SAP session expire time (default 20 minutes). As result also the in app’s lifecyle retrieved X-CSRF-Token value is no longer valid. In such situation the webapplication must relogon to Gateway server / service to establish a new authenticated SAP session, either explicit visible for user in case of username/pw, or implicit in case of e.g. X.509 certificate based authentication. And next also and always the application must self explicitly FETCH a new CSRF Token that is valid in the new SAP session. A more extended, robust protocol is therefore following:

      • Application start its lifecycle
      • At first GET request against Gateway service, as side result also FETCH the X-CSRF-Token, and preserve the returned value in application client context
      • In subsequent modifying request (PUT,POST,DELETE) against Gateway service, use the value of that preserved X-CSRF-Token
      • If Gateway responds with a 403, then apparently the X-CSRF-Token is no longer valid (due expiration of SAP session); then application must re-FETCH a new value, preserve this in application client context, and repeat/retry the modifying request.

      2.) Ashwin is correct; the X-CSRF-Token can be requested on Gateway by any GET request. It is a Gateway-level protection, not bounded to specific Gateway service. So you utilize an HTTP GET for the $metadata document; but also utilize the HTTP GET to another Gateway service, as long as that service is on the same Gateway system.

      Regards, William.

      (0) 
  5. Mike Jackson

    Hi William,

    Great information however I’ve another question. We are currently developing a android app that is making use of OData Services provided by the Gateway. The app will be managed by Airwatch and only used by a small number of internal users. For this reason I was trying to avoid the need for them to use the CSRF functionality. Is there any way it can be disabled so it does not have to be used ?

    Regards

    Mike

    (0) 
      1. William van Strien Post author

        I was not aware it is possible to disable the CSRF token handling. I consider this a design fault in the Gateway system; that is merely there for backwards compatibility. Be very considered whether you want to go this road of disabling security measures that are built into the Gateway interoperability layer.

        (0) 
      2. Mike Jackson

        Ashwin,

        Do you know if we can use this parameter for post SP02 built services, ie those registered under the odata/sap/ node in SICF ?

        Regards

        Mike

        (0) 
    1. William van Strien Post author

      Hi Mike and Ashwin,

      it is not adviced to disable or bypass the Gateway CSRF token. In my opinion, you should never try to bypass security. Be aware that CSRF token is not a client security measure, but to protect the business data in SAP landscape; that is exposed via Gateway. Gateway is transparent to what type of client is invoking its functionality: your service that you invoke via the Android App, could also be invoked from an HTML5 App, and thus open for CSRF security risk.

      And moreover, there is no need; conforming as Gateway client to the CSRF token protocol is not complex; you merely once in your Gateway session request via GET the token, and next for any modifying request you include that received token in the header. That’s it. Not worth trying to disable or bypass.

      Best regards, William.

      (0) 
      1. Mike Jackson

        William,

        Many thanks for the really quick response and agree that it’s not a client security measure. However as Ashwin has pointed out the SAP documentation seems to imply that I can add CHECK_CSRF_TOKEN parameter to the odata/sap/custom service to disable it (accepting that this would not be best practice ?.

        Regards

        Mike

        (0) 
        1. Andre Fischer

          Hi Mike,

          I don’t understand the whole discussion why one would like to avoid the use of CSRF tokens. What is the reason behind this?

          As described by William it is not a big deal to aquire one and send it alongside with the next update request.

          CSRF token support has been added to the underlying SAP NetWeaver stack for a reason which is enhanced security.

          As William also pointed out we have only added an option not to use CSRF tokens for backwards compatibility of services that are based on SP02.

          Best Regards,

          Andre

          (0) 
          1. Mike Jackson

            Andre,

            Sorry to be clear I have every intention of using CSRF. However as we are working to very tight deadlines for delivery I wanted to understand my options if we ran into difficulties.

            Mike

            (0) 
            1. Andre Fischer

              Ok, understood.

              But I am not sure whether you would save much time here.

              On the contrary your app would have to be changed afterwards if you would plan to go for a SP02 compatible behaviour.

              I will keep fingers crossed and hope that you don’t run into any issues.

              Andre

              (0) 
  6. Doron Grinstein

    In a scenario where an attacker successfully mounts a XSS attack, the delivered (malicious) JavaScript would be able to read the contents of a previously requested X-CSRF-Token (in a GET ‘FETCH’, as described) – that data would likely be in session storage (accessible to injected JavaScript code, which is running on the attacked (same) domain/origin).

    That malicious code could then set the X-CSRF-Token header from the previous step and perform a POST/PUT/DELETE operation which would include the necessary security artifacts (cookie and X-CSRF-Token header).

    In the above scenario, the security mechanism breaks down, no?

    So, to summarize my question – IF a XSS attack is successful, it could circumvent the CSRF defense above, correct?



    (0) 
    1. William van Strien Post author

      HI Doron,

      XSS and CSRF are 2 different types of attacks; although XSS can be used as step 1 for CSRF attack to send browser to another site without knowledge from user.

      XSS malicious code executed in the page client context, has access to the cookie information; and can thus read it. To misuse this, also the malicious modifying request must be loaded via XSS and executed from the page client context. This is not a CSRF attack, in which the malicious code is on another site.

      this kind of attack must be prevented by security measurement in the webapplication: validate all user input and escape dynamic output, to detect and prevent successful XSS attacks. See: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

      William.

      (0) 
      1. Doron Grinstein

        Yes, after I wrote the question above, I surmised that it is imperative to defend against XSS because if that happens, then it is game over.. Thanks for responding.

        Doron

        (0) 
  7. Chris Paine

    Hi,

    I came across the CSRF protection in gateway recently. I’ve been using OData to read and write to HANA XS for a while, and assumed Gateway would do the same. It doesn’t, it implements CSRF.

    So I thought – OK? Why?

    1) It is supposed to protect against the case where a cookie in the browser allows a malicious site to alter data on your SAP system.

    So to send a PUT or POST or DELETE from a browser without user knowing is going to involve 1 of 2 things.

    a) An injection of HTML on the page adds either a form that is going to POST some data (typical type of attack  CSRF protects against) or a link e.g. img tag which GETs data.

    b) An injection of some script, e.g. JS on page that is going to do the PUT/POST/DELETE

    In the case of (a – POST) the payload will be malformed and Gateway isn’t going to accept that as valid OData – so no security worries anyway. And for (a – GET) CSRF protection isn’t even applied.

    In the case of (b) well if I can embed JS, I can just as easily embed a GET pull the header and then do an update with the CSRF token.

    In the case that the script is actually from a different domain, then CORS will kick in and stop the access – but if somehow the injection is on my own domain, I don’t see how we’re protected.

    So I’m at a loss. What protection does CSRF actually offer Gateway?

    I look forward to having this explained as I’m sure there must be something I’m missing.

    Cheers,

    Chris

    (0) 
    1. Chris Paine

      There’s a great explanation, which does better than I have at:

      Play Framework

      It is recommended that you familiarise yourself with CSRF, what the attack vectors are, and what the attack vectors are not. We recommend starting with this information from OWASP.

      Simply put, an attacker can coerce a victims browser to make the following types of requests:

      • All GET requests
      • POST requests with bodies of type application/x-www-form-urlencoded,multipart/form-data and text/plain

      An attacker can not:

      • Coerce the browser to use other request methods such as PUT and DELETE
      • Coerce the browser to post other content types, such as application/json
      • Coerce the browser to send new cookies, other than those that the server has already set
      • Coerce the browser to set arbitrary headers, other than the normal headers the browser adds to requests

      Since GET requests are not meant to be mutative, there is no danger to an application that follows this best practice. So the only requests that need CSRF protection arePOST requests with the above mentioned content types.

      Since Gateway does not support POST requests with bodies of type application/x-www-form-urlencoded,multipart/form-data and text/plain (or if it does there’s your problem right there!) there is no need for CSRF protection.

      So please explain why we need to do a seemingly pointless OPTIONS query before doing a POST/PUT/DELETE.

      Cheers,

      Chris

      (0) 
      1. Chris Paine

        It has been suggested to me by the ever impressively knowledgeable Ethan Jewett < (hope that’s the right one) that perhaps the reason for this is:

        Just in case.

        I.e. just in case an attacker finds a zero day exploit in a browser and uses that to attack your Gateway.

        Personally I think that’s a little unlikely, I tend not to look up all day in case of falling space debris… 😉 but I guess, it depends on what data we are talking about.

        So can I suggest the compromise 🙂 :

        If I send a valid authentication header – don’t bother checking for a CSRF header – because that would be pointless!

        (0) 
      2. Vladislav Volodin

        > So please explain why we need to do a seemingly pointless OPTIONS query before doing a POST/PUT/DELETE.

        It is not pointless. Imagine that you want to send a very sensitive and super-secret data in headers (e.g. a user name and password… who knows). The browser wants to protect you, and instead of doing this it asks the server politely, whether it will allow such requests from the user, but without sending this data.

        The server usually answers – “yes/no, I (don’t) allow“, and after that the browser immediately sends things that you wanted to send.

        (0) 
    2. William van Strien Post author

      Hi Chris,

      I’m myself not familiar with HANA XS OData handling, and do not know (understand) why it does NOT implement CSRF protection. I do understand why Gateway DOES apply CSRF protection, namely to protect the SAP resources against malicious modifying requests issued via unaware browser clients.

      CSRF attacks have multiple formats. One is a combination of the 2 things you identified, namely a separate HTML file (a) with embedded javascript (b) that sends a request (e.g. via XMLHttpRequest object) to the attacked site. In case of a GET request, the browser via same-origin policy will disallow sending the request; but POST/PUT/DELETE requests are allowed. (an example of this CSRF attack: Troy Hunt: OWASP Top 10 for .NET developers part 5: Cross-Site Request Forgery (CSRF))

      It is therefore that Gateway only responds with CSRF Token on GET requests, as that request must be issued from code loaded from the same web application context. And it trusts modifying requests that have the same CSRF Token in both request header + cookie, as only javascript code that is loaded from same-origin is allowed in browser to read the received GET header in GET response.

      See also: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

      The Gateway CSRF protection is implementation of the “Cookie-to-Header Token” prevention:

      https://en.wikipedia.org/wiki/Cross-site_request_forgery:

      Security of this technique is based on the assumption that only JavaScript running within the same origin will be able to read the cookie’s value. JavaScript running from a rogue file or email will not be able to read it and copy into the custom header. Even though the csrf-token cookie will be automatically sent with the rogue request, the server will be still expecting a valid X-Csrf-Token header.


      Same prevention technique is applied in the modern and populair angularjs framework

      cc: Andre Fischer

      (0) 
      1. Chris Paine

        Hi William,

        Firstly, I think we should be clear – if a hacker is capable of inserting JS into your page, then there is nothing you can do to prevent being pwned in this situation – they have just as much the ability to pull the token from a GET or OPTIONS call to the gateway server. Let’s not consider that CSRF tokens are a safety measure in those situations – they aren’t. as per the referenced cheat sheet – my emphasis:

        Cross-Site Scripting is not necessary for CSRF to work. However, any cross-site scripting vulnerability can be used to defeat token, Double-Submit cookie, referer and origin based CSRF defenses.

        https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

        Secondly, whilst it is true that you cannot read non-standard headers from a cross-origin GET (ref – http://stackoverflow.com/questions/5822985/cross-domain-resource-sharing-get-refused-to-get-unsafe-header-etag-from-re) CORS works for all HTTP methods. If the CORS settings of the source site allow passing of headers they can be read from a GET (as well as other HTTP methods). If CORS is protecting against the header being exposed in JS, it will also prevent the actual modifying POST.

        From the Wikipedia article on CORS on when it is implemented:

        For AJAX and HTTP request methods that can modify data (usually HTTP methods other than GET, or for POST usage with certain MIME types)…

        It’s also worth noting that in the article you referenced that POST is explicitly mentioned as being the vector for CSRF attacks (as this is HTML injection, not JS injection).

        Thirdly, there is no particular issue in JS code being loaded from alternate domains – if this was the case, we wouldn’t be able to use the AJAX components of the jquery lib when we load it from jquery, or the corresponding components of UI5. It’s more the domain being queried must be the same as the domain that the page is being loaded from. (There are little nuances here around code being executable or not and what it can/cannot do if it is running in an IFrame in another page – the whole third party ad tracking thing.) But CORS prevents any unauthorised cross domain access.

        The referenced article mentions that CORS is needed to make the cross-domain calls – so it will stop the CSRF attack if it is hosted on a different domain. Unfortunately the author of the article puts together a great example that seems to show this isn’t so. However, it only works because 1) He uses IE8 and 2) he exploits a bug in IE8 where it does not apply CORS if only the port is different (He uses localhost:84 and localhost:85). You’ll see that the article specifically calls out that Firefox and Chrome don’t work for the exploit used.

        It would be interesting to hear Andre’s view point. I believe it will be as per Ethan’s view (not a direct quote – but summary of our conversation):

        The best security is deep and many layered and protects not only against the things that you know may happen, but also against those that you’re pretty sure won’t.

        Personally, I believe that the risk that coders make a stuff-up in their code trying to handle CSRF and expose the tokens for even easier hijacking is more likely than zero-day exploits in browsers enabling alternate content types and PUTs and DELETEs being exploited, but I guess that’s my view, and others may have a different one. Perhaps if my code was updating huge financial transactions, I’d want more security rather than less, and I’d be willing to implement a “just in case” bit of code. But for most people, I see that what we’re doing here is slowing the speed of mobile applications and introducing unnecessary complexity.

        Cheers,

        Chris

        (0) 
          1. William van Strien Post author

            Hi Chris,

            CORS and CSRF protection have different intents: CORS is to intentionally allow invocation of external webservices from the scope of a webapplication; e.g. from javascript [part of the webapplication] invoke a public webservice to retrieve the stockquotes. This is intentional behaviour from the context of the webapplication. To allow its usage, the public webservice via CORS ‘contract’ either must allow all domains, or at least the domain of the webapplication.

            CSRF exploits are also intentional, but from hacker’s perspective. CSRF protection is server-side protection to protect from hacker-intentional but user-unintentional modification of server-side resources.

            Note that in the example the javascript is not embedded in a page of the webapplication; but is embedded in an external html page that is loaded in the authenticated browser session with the attacked webapplication. Also note that this is just an example of a CSRF exploit; there are multiple methods known in the world (and likely more in the hacker’s community…)

            Also I like to repeat Andre’s doubt: “I don’t understand the whole discussion why one would like to avoid the use of CSRF tokens. What is the reason behind this?

            …it is not a big deal to aquire one and send it alongside with the next update request.”

            To acquire a Gateway / ICF CSRF token only costs runtime at maximum one (1) extra GET request (likely the webapplication would already do a GET request at initialization, and the developer can then combine that initialization request with retrieval of CSRF token via FETCH header). That single request can hardly slow down the [perceived] speed of (mobile) webapplications.

            (In CORS handling, all requests to external domain can be preflight with an extra request.)

            Regards, William.

            (0) 
            1. Chris Paine

              Hi William, sorry you didn’t read/understand my previous response. The example given doesn’t work, it only ever worked because Tony used IE8 and the same hostname with different ports. CORS stopped the exploit on other browsers.

              If I ask you to hop on one leg each time for 10 seconds before I let you into my house, would not make sense? After all it is only just 10 seconds? Just do it!

              My point is, and was, CSRF protection on Gateway is pointless if the user is using non-compromised browsers.

              Cheers,

              Chris

              (0) 
            2. Chris Paine

              Perhaps I should answer again the doubt of Andre:

              I don’t understand the whole discussion why one would like to avoid the use of CSRF tokens. What is the reason behind this?

              …it is not a big deal to aquire one and send it alongside with the next update request.”

              Whilst frameworks like UI5 have embedded handling for CSRF tokens, there are always edge cases that require a little more work to ensure that applications work with CSRF protection. Specifically around the timeout of user sessions, there may be issues with the token handling and re-acquisition. Code needs to be written and tested to ensure that users do not loose data because of a connection refused due to CSRF protection.

              Such code needs to be maintained. There is a finite risk that a some point the code will NOT handle the tokens correctly due to a mistake on the part of the original coder, or perhaps those maintaining and adjusting the code.

              When I weigh the risk of errors in app and cost of maintaining and testing for CSRF protection situations vs. the risk that a new and hitherto unknown exploit is allowing the hijacking of browsers to POST from a form with different content type and the cost that such an attack may have on my business, I’m finding that the cost/risk of code errors/testing introduced due to having to handle CSRF protection is higher.

              This is why I make the ridiculous comparison of asking someone to hop on one leg for 10 seconds before letting them into my house. I’m already doing the check of who they are, but I’m only going to let people in that do something pointless, just to be doubly sure.

              (0) 
              1. William van Strien Post author

                Hi Chris,

                I do not consider the risk of a missed code error a justification to comprise security. Developers have the responsibility to best-protect their application, and to test it on all build aspects: functional and non-functional (performance, scalability, security, )

                Also, the client-side handling for ‘Cookie-to-Header Token’ prevention is simple, not rocket-science to implement. And examples are provided to teach / demonstrate the developer on ‘how-to’.

                The modern and amongst developers populair angularjs framework applies same CSRF “Cookie-to-Header Token” prevention technique:

                [https://docs.angularjs.org/api/ng/service/$http] “When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN)…”

                Also here, developers themselves must setup in their client/javascript code the client-side handling for the CSRF protection.

                Best regards, William.

                (0) 
                1. Chris Paine

                  The thing is, by not implementing CSRF protection, we aren’t making our services insecure. There are no known ways to use CSRF against Gateway currently.

                  There is the case of protection against unknown attacks, but is that worth the cost, risk, effort?

                  Not using CSRF protection does not mean you are making your service insecure. It just trading “just in case” against real life complexity, risk and cost.

                  Depending on the data concerned, that “just in case” might be worth it. It won’t always be.

                  Architects have a responsibility to their companies to balance these risks and decide. We have the responsibility to inform them clearly and not just pretend that security is the only and overwhelming factor to consider.

                  (0) 
  8. David Clegg

    In SMP, the servlet filters that implement CSRF handling will only allow the client to perform the X-CSRF-Token: FETCH request once on the session. The generated CSRF token value is then remembered on the HttpSession and checked there on mutating requests. Under that scenario, we expect that a client application performs the CSRF: FETCH operation early on (typically during authentication) and hangs on to the value for the duration of the session. An attacker’s JavaScript might *try* to perform a CSRF: FETCH so it could set up a subsequent modifying operation, but the server wouldn’t provide a valid CSRF token for that attacker code to use. And the CORS protection should prevent the attackers code from trolling through the JavaScript objects of the valid app to retrieve the token.

    I don’t know if Gateway has similar restrictions around divulging the CSRF token value.

    (0) 
    1. Chris Paine

      Hi David,

      from what I can see, the token is provided on each and every request that include the X-CSRF-Token:Fetch header for a GET, using a cookie is enough authentication to have the token retrieved – e.g. no need for an Authentication header.

      Cheers,

      Chris

      (0) 
      1. Chris Paine

        In a bit of fun – the token is also returned even when you do a OPTIONS call, which gateway responds to with a 405

        (0) 
  9. David Clegg

    I think we have gaps in the OData (and other) protocol definitions to really get this right.

    I’ve been discussing XSRF protection topics with multiple colleagues from multiple angles recently and here are the problems that I am seeing:

    1) Following OWASP cheat sheet recommendations, SMP will only respond to an X-CSRF-Token: FETCH request once for a session. If a client re-issues a FETCH or otherwise presents an invalid token value, the session is terminated and we return an HTTP 403 status and X-CSRF-Token: Required response.

    This *designed* behavior has some negative consequences for client usability.

    a) For mobile clients it means that initially http requests have to be serialized around establishing the session and performing the fetch. If there are multiple threads in the client making multiple parallel requests, and one of them is doing the fetch and another tries to do a modifying request w/out the CSRF, or another makes a parallel fetch request, then the server kills the session and the client is hosed. We can work this out with the SDK team by enforcing serialization at critical points.

    b) From the SAP UI5 based admin cockpit, the browser establishes an authenticated session and does the XSRF fetch. But if the user wants to open a new window (Ctrl-N or open new tab) so they can maintain context on the original Admin UI view, but use the other view (with the same session cookie) to navigate to other areas of the application – if they try do do a modifying operation from the 2nd view,. then we should terminate the session and basically kill *both* views for the administrative user.

    c) XSRF tokens in our header-based implementation are intrinsically linked to corresponding session cookies. When the session is invalidated or expires or is pruned due to resource constraints on the server, the XSRF token implicitly expires as well. The client doesn’t get to find out about this expiration until it tries its next POST/PUT/PATCH/DELETE operation with the old token (403 + X-XCRF-Token: Required). The session cookie is set as HTTPONLY, so java-script level client code cannot be expected to access or manage the session aspects here. When the XCRF token has expired, the client needs to both retain the content of the rejected request (business operation data), and redirect through a series of requests to re-authenticate, and fetch a new token, and then re-submit the modifying request with the new token on the new session.

    In recent discussions, we have recommended that the ${metadata} target for the OData services would be the right place for a client to go with its X-CSRF-Token:Fetch GET request to renew the token. If metadata is small, and all OData services are responding to Fetch requests on these URLs, OK. But there is nothing in the OData standards to say this will work uniformly.

    For the Admin cockpit UI, we just put a timeout (that is less than the normal session timout for the server) so it automatically logs out the user and presents a login screen. In most cases this avoids the CSRF token timeout issue, but it isn’t pretty or fool-proof, and doesn’t deal with the tabbed browser problem.

    I’m still looking for better solutions.

    (0) 
    1. Vladislav Volodin

      Often $metadata is cached, and it might happen that the server will not process your request, and simply return the cached version.

      So, I’d say that using $metadata for CSRF is an unreliable solution.

      Ideally if we are talking about REST (as a stateless concept), there should be no SAP_<sid> cookies at all.

      (0) 

Leave a Reply