Archive for the ‘csrf’ tag
Secure coding with Ruby on Rails 7: Cross-site request forgery (CSRF)
Although discovered already in 1988 by Norm Hardy, cross-site request forgery (CSRF) has been the shooting star of web attacks in 2008. As a result it has become one of the 2009 CWE/SANS Top 25 Most Dangerous Programming Errors.
The idea behind CSRF is that an attacker sends a malicious request to the target application using a trusted connection which he expects to have been established by an innocent user. In case of web applications this could be done by hiding the request in a web page with harmless content. If the user visits the malicious web page while he is logged in to the target application in another browser tab, the dangerous request is send to the target over the trusted connection between browser and web application. Two basic scenarios are possible. In the first scenario the attacker forges a request to a commonly used web application so that it doesn’t matter who opens the malicious web page. The other scenario is to trick somebody who is known to have special privileges for one web application to open the prepared web page.
In both scenarios the malicious web page of the attacker is crafted so that it sends a hidden request to the target application. For example a HTTP GET request could be executed by using the src attribute of an img tag like in the following line of code. In this case it would delete one user account.
<img src="http://victim.example.com/user/destroy/1" />
Another possibility to hide a request in a web page is displayed in the next example. It’s a hidden HTTP POST request which changes the name and email address of the logged in user. It sends the request automatically on page load. With the changed email address the attacker can use the “forgot password?” function in order to receive a newly generated password and capture the account.
<SCRIPT>
function SendAttack() {
var form = document.createElement("form");
form.style.display = "none";
this.parentNode.appendChild(form);
form.method = "POST";
form.action = "http://victim.example.com/profile.php";
form.first_name = "Bad";
form.last_name = "Guy";
form.email = "attacker@example.com";
form.submit();
}
</SCRIPT>
<BODY onload="javascript:SendAttack();"></BODY>
These two examples demonstrate that HTTP GET as well as HTTP POST are vulnerable by CSRF. Hence it is not enough to allow only POST requests to alter data. Other measure need to be applied, too. An obvious client-side countermeasures is to use separate browsers for surfing and administration, but Rails provides a server-side measure as well. The method protect_from_forgery() automatically inserts a security token in all forms and Ajax request generated by Rails. The token is calculated from the current session and the server-side secret. If the session storage is not CookieStorage the secret needs to be passed as option to the method. If an attacker is trying to send a request without the valid token to the application an ActionController::InvalidAuthenticityToken error is raised.
In Rails versions newer than 2.0 protect_from_forgery() is called for all HTTP POST requests by default. Hence it only has to be taken care of that HTTP GETÂ and HTTP POST requests are used appropriately (see W3C checklist) and that this is enforced. For assuring that actions are only called by HTTP POST requests Rails provides the verify() method which can be added to a controller as demonstrated in the following example. It is also shown how to define actions which should be callable by other HTTP methods than POST with the except option.
class MyController < ApplicationController verify :method => "post", :except => :index end
In older Rails versions the protect_from_forgery() method can be used like shown in the following lines of code. In this example CSRF protection is disabled for the index action.
class MyController < ApplicationController protect_from_forgery :except => :index end
For further information on cross-side request forgery see www.cgisecurity.com/csrf-faq.html.
Popularity: 1% [?]
