52 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			52 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Cross Site Request Forgery
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								## Cross Site Request Forgery
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Cross Site Request Forgery is a vulnerability in the application caused by the programmer not checking where a request was sent from - this attack is sent to a high privilege level user to gain higher level access to the application.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Example Cross Site Request Forgery Attack
							 | 
						||
| 
								 | 
							
								An online blog allows users to submit comments and include an image in the comment, the blog's admin panel allows the blog's author to delete a comment by loading the URL `/admin/deletecomment.php?id=123`. A malicious user could make an image tag that loads the delete comment url for example `<img src="/admin/deletecomment.php?id=123" />` so next time an admin views the comment, the admin's computer will load the url and delete comment number 123.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Defending your website from cross site request forgery attacks in PHP
							 | 
						||
| 
								 | 
							
								To defend against a cross site request forgery attack, you should check against a regularly changed token. The url `/admin/deletecomment.php?id=123` would change to `/admin/deletecomment.php?id=123&csrf-token=random-per-user-unique-string-here`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```PHP
							 | 
						||
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								// Checking a request's CSRF Token (if true the comment is deleted, if false the comment remains.)
							 | 
						||
| 
								 | 
							
								session_start();
							 | 
						||
| 
								 | 
							
								if ($_GET['csrf-token'] == $_SESSION['csrf-token']){
							 | 
						||
| 
								 | 
							
								  return true;
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
								  return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								**Tips:**
							 | 
						||
| 
								 | 
							
								* Keep a CSRF Token completely random and change per session (the openssl functions can help with this)
							 | 
						||
| 
								 | 
							
								* PHP sessions are useful for storing a CSRF Token accessible to both the user and the server, you could also make this process database driven if you are so inclined.
							 | 
						||
| 
								 | 
							
								* Change the CSRF Token on a session every 24 hours. On a high risk application you might want to change it upon every successful request however that will cause issues with users using multiple tabs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Securely generating a Token
							 | 
						||
| 
								 | 
							
								When setting a CSRF Token it is important that it is impossible to guess the key. The OpenSSL functions in PHP can generate a randomized key for you and store as a session variable.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```PHP
							 | 
						||
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								session_start();
							 | 
						||
| 
								 | 
							
								$_SESSION['csrf-token'] = bin2hex(openssl_random_pseudo_bytes(16));
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Using a CSRF Token to complete legitimate requests
							 | 
						||
| 
								 | 
							
								You can include the session variable you saved earlier with your CSRF token in the URL make sure a legitimate administrator is allowed to delete comments. Without the correct token the request will be blocked.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```PHP
							 | 
						||
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								session_start();
							 | 
						||
| 
								 | 
							
								echo '<a href="/admin/?id=123&csrf-token='.$_SESSION['csrf-token'].'">Delete Comment</a>'; // Only the logged in user has access to the CSRF Token - the token isn't accessible to the attacker preventing their attack from being successful.
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### More Information:
							 | 
						||
| 
								 | 
							
								* <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)" rel="nofollow">OWASP Wiki - Cross Site Request Forgery</a>
							 | 
						||
| 
								 | 
							
								* <a href="https://secure.php.net/manual/en/function.bin2hex.php">php.net bin2hex() manual</a>
							 | 
						||
| 
								 | 
							
								* <a href="https://secure.php.net/manual/en/function.openssl-random-pseudo-bytes.php">php.net openssl_random_pseudo_bytes() manual</a> <!-- I used html special entities here due to issues displaying the underscore characters -->
							 |