#1
  1. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,688
    Rep Power
    171

    Cross-site request forgery (CSRF)


    Since Northie brought it up I was wondering what would be the best way to stop forms from being submitted from other domain names. So I read CodeIgniters documentation which I have pasted below.

    Codeigniter has a feature that if I change in config file it creates a token like
    Code:
    <input type="hidden" name="csrf_test_name" value="2fe179d1469fada94a3301d25b88ced8" />
    and adds it to the form. I applied it this page.
    It doesn't really make sense to me cause anyone can view the source and copy the hidden field to another form and submit it from another website. I did and it worked fine. Of course it does, it only makes sense! I copied the field and pasted it here in this page.


    What is the point of this hidden field then? What am I missing?

    Thanks

    From CodeIgniters documentation
    Cross-site request forgery (CSRF)

    You can enable csrf protection by opening your application/config/config.php file and setting this:
    $config['csrf_protection'] = TRUE;

    If you use the form helper the form_open() function will automatically insert a hidden csrf field in your forms.
  2. #2
  3. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Hi,

    the thing is that you can view the page source of your own requests. But you cannot request a page for somebody else and then view the source to get his token (the token is unique for every user and request). If you tried to e. g. make a GET request via JavaScript and fetch the token, you'd run into the same origin policy.

    So the tokens by somebody else are not accessible to you -- unless your page (or any page on the same domain) is vulnerable to cross-site scripting. In this case you could actually make that JavaScript GET request. But with a XSS vulnerability it's too late, anyway, because you could simply fetch the session cookie.
  4. #3
  5. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,688
    Rep Power
    171
    Thank you Jaques;
    I am sure there are some good points in your response. But I need to slow you down to make sure I understand everything you said above.
    Originally Posted by Jacques1
    Hi,

    the thing is that you can view the page source of your own requests. But you cannot request a page for somebody else and then view the source to get his token (the token is unique for every user and request). If you tried to e. g. make a GET request via JavaScript and fetch the token, you'd run into the same origin policy.
    Does this mean my page is secure as it does generate the token?
    Originally Posted by Jacques1
    So the tokens by somebody else are not accessible to you -- unless your page (or any page on the same domain) is vulnerable to cross-site scripting. In this case you could actually make that JavaScript GET request. But with a XSS vulnerability it's too late, anyway, because you could simply fetch the session cookie.
    Would you please explain what you meant up there?

    Thank you.
  6. #4
  7. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by zxcvbnm
    Does this mean my page is secure as it does generate the token?
    If you're using the feature correctly and CodeIgniter implemented it correctly: yes.

    The token must be different for every user, and it must not be possible to perform the action without the correct token. You can simply test this.



    Originally Posted by zxcvbnm
    Would you please explain what you meant up there?
    If any page on the domain is vulnerable to cross-site scripting (that is, an attacker can embed JavaScript), then it's possible to "steal" the secret token by making an AJAX request from within the site and fetching the page where the form is at. So an XSS vulnerability will break the whole CSRF protection.

    That's pretty much what you described in the original question: viewing the page source to get the token. Under normal circumstances you cannot do that from within other people's browsers (because cross-domain AJAX requests are now allowed). But in case of an XSS vulnerability you actually can.

    So it's important to make the page secure in every aspect (but I guess you already knew that).
  8. #5
  9. Mad Scientist
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2007
    Location
    North Yorkshire, UK
    Posts
    3,661
    Rep Power
    4124
    here's the basics of the logic, hopefully you'll see where the protection comes from


    PHP Code:
    //on the way in

    if(count($_POST) > 0) {
        if(
    $_POST['token'] == $_SESSION['token']) {
            
    //allowed to proceed
        
    } else {
            
    //not allowed to proceed
        
    }
    } else {
        
    //allowed to proceed
    }


    //on the way out

    $_SESSION['token'] = sha1(microtime()).sha1($_SESSION['user']['id']); 



    html Code:
    //in the html
     
    <form action='?' method='post'>
     
    	<!--
     
    		UI here
     
    	-->
     
    	<input type='hidden' name='token' value='<?php echo $_SESSION['token']; ?>' />
     
    </post>


    as you can see the token is linked to the session and is varying with time.

    for a forger to get the token they would have to have some way of inspecting the html that arrives in the user's browser and present a forged request back to them in some application or other.

    The naive thing to do is to put the token into a cookie - this negates the process entirely as even forged requests send the appropriate cookie's

    Generating a unique token for every user for every session is a must.

    Generating a unique token for every request is a little more secure but you can come unstuck if you use ajax in-between - as the value of the token in the form falls out of sync with the value in the session.
    I said I didn't like ORM!!! <?php $this->model->update($this->request->resources[0])->set($this->request->getData())->getData('count'); ?>

    PDO vs mysql_* functions: Find a Migration Guide Here

    [ Xeneco - T'interweb Development ] - [ Are you a Help Vampire? ] - [ Read The manual! ] - [ W3 methods - GET, POST, etc ] - [ Web Design Hell ]

IMN logo majestic logo threadwatch logo seochat tools logo