Chapter 4. Cross-site Request Forgery

In this chapter, we will cover cross-site forgery. This topic is not exactly new, and believe it or not, we have already encountered this in the previous chapters. In this chapter, we will go deeper into cross-site forgery and learn the various techniques of defending against it.

Introducing cross-site request forgery

Cross-site request forgery (CSRF) exploits the trust that a site has in a user's browser. It is also defined as an attack that forces an end user to execute unwanted actions on a web application in which the user is currently authenticated. We have seen at least two instances where CSRF has happened. Let's review these security issues now.

Examples of CSRF

We will now take a look at a basic CSRF example:

  1. Go to the source code provided for this chapter and change the directory to chp4/python_tornado. Run the following command:
    python xss_version.py
    
  2. Remember to start your MongoDB process as well.
  3. Next, open external.html found in templates, in another host, say http://localhost:8888. You can do this by starting the server, which can be done by running python xss_version.py –port=8888, and then visiting http://loaclhost:8888/todo_external. You will see the following screenshot:
    Examples of CSRF

    Adding a new to-do item

  4. Click on Add To Do, and fill in a new to-do item, as shown in the following screenshot:
    Examples of CSRF

    Adding a new to-do item and posting it

  5. Next, click on Submit. Going back to your to-do list app at http://localhost:8000/todo and refreshing it, you will see the new to-do item added to the database, as shown in the following screenshot:
    Examples of CSRF

    To-do item is added from an external app; this is dangerous!

  6. As we saw in the previous chapter, to attack the to-do list app, all we need to do is add a new item that contains a line of JavaScript, as shown in the following screenshot:
    Examples of CSRF

    Adding a new to do for the Python version

  7. Now, click on Submit. Then, go back to your to-do app at http://localhost:8000/todo, and you will see two subsequent alerts, as shown in the following screenshot:
    Examples of CSRF

    Successfully injected JavaScript part 1

  8. So here's the first instance where CSRF happens:
    Examples of CSRF

    Successfully injected JavaScript part 2

    Take note that this can happen to the other backend written in other languages as well. Now go to your terminal, turn off the Python server backend, and change the directory to node/. Start the node server by issuing this command:

    node server.js
    

    This time around, the server is running at http://localhost:8080, so remember to change the $.post() endpoint to http://localhost:8080 instead of http://localhost:8000 in external.html, as shown in the following code:

        function addTodo() {
          var data = {
            text: $('#todo_title').val(),
            details:$('#todo_text').val()
          }
          // $.post('http://localhost:8000/api/todos', data, function(result) {
          $.post('http://localhost:8080/api/todos', data, function(result) {
            var item = todoTemplate(result.text, result.details);
            $('#todos').prepend(item);
            $("#todo-form").slideUp();
          })
        }

    The line changed is found at addTodo(); the highlighted code is the correct endpoint for this section.

  9. Now, going back to external.html, add a new to-do item containing JavaScript, as shown in the following screenshot:
    Examples of CSRF

    Trying to inject JavaScript into a to-do app based on Node.js

  10. As usual, submit the item. Go to http://localhost:8080/api/ and refresh; you should see two alerts (or four alerts if you didn't delete the previous ones). The first alert is as follows:
    Examples of CSRF

    Successfully injected JavaScript part 1

    The second alert is as follows:

    Examples of CSRF

    Successfully injected JavaScript part 1

Now that we have seen what can happen to our app if we suffered a CSRF attack, let's think about how such attacks can happen.

Basically, such attacks can happen when our API endpoints (or URLs accepting the requests) are not protected at all. Attackers can exploit such vulnerabilities by simply observing which endpoints are used and attempt to exploit them by performing a basic HTTP POST operation to it.

Basic defense against CSRF attacks

If you are using modern frameworks or packages, the good news is that you can easily protect against such attacks by turning on or making use of CSRF protection. For example, for server.py, you can turn on xsrf_cookie by setting it to True, as shown in the following code:

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/api/todos", Todos),
            (r"/todo", TodoApp)

        ]
        conn = pymongo.Connection("localhost")
        self.db = conn["todos"]
        settings = dict(
            xsrf_cookies=True, 
            debug=True,
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static")
        )
        tornado.web.Application.__init__(self, handlers, **settings)

Note the highlighted line, where we set xsrf_cookies=True.

For the version of the node server, you can refer to chp4/node/server_secure.js, where we require csrf. Have a look at the following code snippet:

var express    = require('express'),
var bodyParser = require('body-parser'),
var app        = express();
var session    = require('cookie-session'),
var csrf    = require('csrf'),

app.use(csrf());
app.use(bodyParser());

The highlighted lines are the new lines (compared to server.js) to add in CSRF protection.

Now that both backends are equipped with CSRF protection, you can try to make the same post from external.html. You will not be able to make any post from external.html. For example, you can open Chrome's developer tool and go to Network. You will see the following:

Basic defense against CSRF attacks

POST forbidden

On the terminal, you will see a 403 error from our Python server, which is shown in the following screenshot:

Basic defense against CSRF attacks

POST forbidden from the server side

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.28.107