Is that all I need to do to prevent csrf attacks with php and ajax?

I am using Codeigniter and I have enabled CSRF through its config.php ...

 $config['csrf_protection'] = TRUE; $config['csrf_token_name'] = 'csrf_token_name'; $config['csrf_cookie_name'] = 'csrf_cookie_name'; 

then for my ajax requests i get cookie name

 var cct = $.cookie('csrf_cookie_name'); 

and parameters :

 csrf_token_name : cct 

My question is: do I need to do something or something else?

+4
source share
2 answers

Well, most common cases (or the easiest to implement) CSRF looks something like this:

 <img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=Fred" /> 

So, if you assume that you are logged into bank.example.com , you are cookies "alive" and will be sent with a request, so the request will do what the attacker wants, therefore:

Cookies Won't Protect You From CSRF

What can you do:

Send as many requests through POST as you can (without disturbing the user), especially editing, creating and deleting. It’s easier to hide security in input type='hidden' than in URL.

Check referrer (yes, this little thing bothers you almost every CSRF attack from external sites):

 $url = parse_url( isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''); if( isset( $url['host']) && ($url['host'] == $_SERVER['SERVER_NAME'])){ // Request have a go } 

Add temporary security tokens to URLs like this /article/delete/25/axdefm ...

If you spent some time creating good URLs, you will be sent because it just messes them up and it will cause some problems, such as:

  • several actions at a time
  • request flow for new security token
  • how much time should be indicated in the token

Decision

You can create a table for security tokens, for example:

 tokens ( id INT, user_id INT, created DATETIME, expires DATETIME, -- One of those two should be enough value CHAR(30), PRIMARY (id), FOREIGN KEY (user_id) ... ); 

And when an authorization token is required for any action, you download the last from the database or create a new one, say, you will create a new token only if all available currents are older than 15 minutes:

 function getToken( $userId, $eventIdentificator){ // Hope this is self explanatory :) $db->deleteExpiredTokens(); // Try to load token newer than 15 minutes $row = $db->fetchRow( 'SELECT value FROM tokens WHERE created >= ADD_INTERVAL( NOW(), -15 MINUTES) AND user_id = ?', array( $userId)); // createToken will return `value` directly if( !$row){ $row = createNewToken( $userId); } else { $row = $row['value']; } // Real token will be created as sha1( 'abacd' . 'delete_article_8'); return sha1( $row . $eventIdentificator); } echo 'url?token=' . getToken( $userId, 'delete_article_' . $article['id']); 

How it will work:

  • if you request a security token for the same action within 15 minutes, you will receive the same token
  • you will receive a unique token for each action
  • if you set the expiration of the token within 4 hours, the token will be active from 3:45 to 4:00.
  • if an attacker tries to send you 200,000 token requests in one minute, you will still only have one row in the database
  • each user will have a maximum of 16 entries in the table at once

How to check a token?

 function checkToken( $userId, $eventIdentificator, $token){ $db->deleteExpiredTokens(); // Just find matching token with brute force $rs = $db->fetch_rowset( 'SELECT value FROM tokens WHERE created >= ADD_INTERVAL( NOW(), -15 MINUTES) AND user_id = ?', array( $userId)); while( $row = $rs->fetch_row){ if( $token == sha1( $row['value'] . $eventIdentificator)){ return true; } } return false; } 

If you have not made sure that the action does not happen twice (for example, an editing article, this is great for deletion) just add revision_number or something similar to your $eventIdentificator ).

Try to think about what happens if:

  • MANY tokens intruder requests
  • user will write an article in a few hours
  • If you have a table with delete buttons for hundreds of articles

I would go with the mentioned token system, it feels like a balanced solution between user comfort / implementation complexity and security, comments on ideas and notes are expected :)

+7
source

The most common Cross-Site Request Forgery (CSRF) attack prevention method is to add unpredictable tokens for each request and associate them with a user session.

The CSRF protection in CodeIgniter does this for you, so I think this is normal; -)

+4
source

Source: https://habr.com/ru/post/1399647/


All Articles