PHP - How To Truly Prevent Csrf
As the title says, I would like to know how exactly CSRF can be 100% (or close to it) prevented.
One of the most recommended solutions is to create a token and insert it into a hidden field, but I've tested it on another domain and you can just do a cURL request and retrieve the token then make another request with it included. Proof:
<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "URL"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); curl_close($ch); $exploded = explode('type="hidden" name="token" value="', $response); $token = substr($exploded[1], 0, 64); echo $token; // ebd9ab96d40bdb21bbaa2e1a18d657be2e413105ae86ecc14def6137f38a1571 ?>I would hate to include captcha on all my forms, so how exactly does one prevent CSRF? Similar TutorialsHow much work do you to stop CSRF? Like, I've made sure when changing passwords/e-mails (or anything related to account security) they have to confirm their own password so CSRF can't really do much. I've got a header referral check on everything but this is really easy to spoof so without putting hidden tokens in each form is there any easier way? I can't really be bothered and the worst thing they can do is get a user to post a spam post on my forum or something trivial. How far do you take it? hey guys,
i was introuduced the the world of csrf a little while ago by a member of PHP Freaks, beofore hand i had'nt a clue...so i decided to read a little more into and created a class to deal with generating tokens and ensuring the site is free from CSRF.
now my understanding is that a CSRF can be made from clicking on sponsers, images and basically anything that can cause a request to another site/domain.
now with the script allows the user to have multipule tokens and a new token is generated everytime when filling a form or whatever, allowing user to have more than one tab open. I'm just a little concerned that a CSRF attack can still be made this way as a new token is made on each form page.
when creating a form i do this:
<input name="csrf_token" type="hidden" value="12345" />then on post im able to do something like this: $token = $csrf->get_token(); // token for input if ($csrf->is_safe($post->csrf_token) && form->is_valid()) { echo "safe" } else { echo "unsafe"; }here is my class <?php namespace Security; use Session\Session as Session; use Security\SSL; class CSRF { protected $_expiration = "3600"; public function get_token($expiration = null) { $ssl = new SSL; $token = $ssl->random_string(20); $session = new Session; $session->start(); if ($expiration === null) { $expiration = $this->_expiration; } else if (!is_numeric($expiration)) { // error } if (!$session->offset_exists('csrf_token')) { $session->csrf_token = array(); } $expiration = time() + $expiration; $session->append('csrf_token', array('token' => $token, 'expiration' => $expiration )); return $csrf_token; } protected function token_exists($token) { $session = new Session; $session->start(); $csrf_token = $session->csrf_token; $result = false; foreach ($csrf_token as $key => $array) { if (time() > $array['expiration']) { $session->offset_unset('csrf_token', $key); } else if ($array['expiration'] > time()&& $array['token'] === $token) { $session->offset_unset('csrf_token', $key); $result = true; } } return $result; } public function is_safe($token) { if ($this->token_exists($token)) { return true; } return false; } }any advise would be greatful, thank you Edited by Destramic, 11 January 2015 - 04:27 PM. I have a question about Cross-Site Request Forgeries (CSRF). Somewhere in the processing of my form, I check: if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { // all other code omitted } else { // no place for bad guys here } So basically, if the token is good then the form continues to check for errors, valid data, etc... I was wondering; is there a point in checking the token again each time I check something else? For example: // above code omitted if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { // all other code omitted // check to see if there were any errors if (count($errors) >= 1) { $valid = false; } else { // all other code omitted if ($sent == $allowed) { if ($addNew == true) {// Should I be checking the token each time, or am I being redundant?? // all other code omitted } } } } else { // no place for bad guys here } Hi all, I'm writing my own MVC framework purely to improve my oo php skills and I've created a CSRF token validation class to help prevent CSRF attacks. I just need some feedback on it really, is it insecure, is there a better way to validate tokens, etc. Code: [Select] <?php // Security measure. if (!defined('BASE_PATH')) { exit(); } class CSRF { private static $tokens = array(); private static $session_name = 'csrf_data'; /** * Loads CSRF token data from session into $tokens array. * * This is called before the controller is loaded. * * @return void */ public static function init() { $session_name = self::$session_name; // Move CSRF token data from session to class field. if (isset($_SESSION[$session_name])) { self::$tokens = unserialize($_SESSION[$session_name]); unset($_SESSION[$session_name]); } } /** * Saves the CSRF data to a session. * * @static * @return void */ private static function save() { $session_name = self::$session_name; unset($_SESSION[$session_name]); $_SESSION[$session_name] = serialize(self::$tokens); } /** * Creates a new token. * * @static * @param string $name * @return string */ private static function generateToken($name) { $token = md5(uniqid(rand(), true)); self::$tokens[$name] = $token; self::save(); return $token; } /** * Validate a token by its name. * * @static * @param string $name * @param string $token The CSRF token included with the form data. * @return bool */ public static function validateToken($name, $token) { if (!isset(self::$tokens[$name])) { return false; } return ($token == self::$tokens[$name]); } } // End of CSRF class. This topic has been moved to Ajax Help. http://www.phpfreaks.com/forums/index.php?topic=323434.0 Hi - My app is built with Codeigniter and so if I turn on CSRF on CI inside the config I get the token being created on my page - good.
But I have 1 page ( "shopping cart") which uses Scriptaculous Ajax.Updater function : http://api.prototype...x/Ajax/Updater/
When I turn on CSRF my shopping cart page refuses to function in terms of updating the cart or deleting any items from the cart. These are both js functions.
I am really stuck - any help would be a God send. Thank You !!
Here is the code:
UpDate JS Function:
function jsUpdateCart(){ var parameter_string = ''; allNodes = document.getElementsByClassName("process"); for(i = 0; i < allNodes.length; i++) { var tempid = allNodes[i].id; var temp = new Array; temp = tempid.split("_"); var real_id = temp[2]; var real_value = allNodes[i].value; parameter_string += real_id +':'+real_value+','; } var params = 'ids='+parameter_string; var ajax = new Ajax.Updater( 'ajax_msg','http://localhost/mysite/index.php/welcome/ajax_cart', {method:'post',parameters:params,onComplete:showMessage} ); } I know, csrf token is like a random string. Does every form need a csrf token? Does every form need to have a different csrf token or all forms have a same csrf token for one logged in user? When an user logged in, I set $_SESSION['key']=$useremail; is it ok to set email for a logged in session? Do I have to set or add another $_SESSION with csrf token? How does csrf token add security for form submission? After form submission, what would PHP do with the hidden input field or with the csrf token? Someone parses the html login form and gets the csrf token from hidden field. Now can he request with that csrf token to login through jquery ajax? Hello Guys, Iam making a new ad serving script. In that site every publisher can register & they will get a url to serve ads. When a user click on that url the publisher will get earnings. But my problem is someone using something like this <iframe src="http://my-site.com/adserve.php" width = "100" height = "100"></iframe> & it will helps to get earnings without clicking on that url. I want to prevent this type of cheating & how it can be possible ?? I hope a expert will replay for me. Is this a correct approach to prevent email injection? $to: me@mydomain.com, myPartner@mydomain.com, $emailer; //then the rest of the stuff. $emailCheck = $_POST["emailer"]; if (eregi("(\r|\n)", $emailCheck)) { die("Why ?? "); } mail($to, $subject, "", $headers); Hi is there any way we can prevent suppose <textarea></textarea> when page reload it refresh and set default text i wanted to know is there any way to prevent certain things not to get refreshed is there any method in php which prevent to reload this ! <?php echo "<textarea > Enter your favorite quote!</textarea> \n" ; Code: [Select] if (isset($_GET['edit']) && $_GET['edit'] == 'textupdate'){ } <a href= \"{$_SERVER['PHP_SELF']}?page=1&edit=textupdate \" >Click</a>?> Will this prevent a SQL injection? I am guessing the answer is no because it is too simple. // retrieve form data ========================================== $ama = $_POST['ama']; // Check for alphanumeric characters ===================================== $string = "$ama"; $new_string = preg_replace("/[^a-zA-Z0-9\s]/", "", $string); // echo $new_string; // Send query =========================================================== $query = "SELECT * FROM members WHERE ama='$new_string'"; if (!mysql_query($query)){ die('Error :' .mysql_error()); } I am loading a link with ajax. When the link pops on the screen and I click it, I get redirected to my 404 page and my lightbox doesn't load. If the link pops in and I refresh my browser, then I click the link my lightbox will show up. How can I do a prevent default on the <a href> in pure JS? No frameworks please. Based on the comments on my previous question, took some tutorials on how to avoid injections on query. Does the code below prevents against it in any way.? Secondly, can you recommend a good article that writes well in how to secure input data by users. Please be kind with your comments.😉😉. Thankks in advance.
The code works fine. <?php include 'db.php'; error_reporting(E_ALL | E_WARNING | E_NOTICE); ini_set('display_errors', TRUE);  if(isset($_POST['submit']))  {     $username = $_POST['username']; $password =  ($_POST['password']); $sql = "SELECT * FROM customer WHERE username = ?"; $stmt = $connection->prepare($sql); $stmt->bind_param('s', $username); $stmt->execute(); $result = $stmt->get_result(); $count =  $result->num_rows;   if($count == 1)              { while ($row = $result->fetch_assoc())  {   if ($row['status'] == 'blocked')  {  echo'your account is suspended'   session_destroy();   exit();  }  else if($row['status'] == 'active') { if($username !== $row['username'])  { echo '<script>swal.fire("ERROR!!", " Username is not correct. Check Again", "error");</script>'; } if($password !== $row['password']) {  echo'<script>swal.fire("ERROR!!!", "Your Password is Incorrect. Check Again.", "error");</script>';     } if($username == $row['username'] && $password == $row['password']) { header('Location:cpanel/'); else { } }//if count }//while loop }//submit ?>  $_POST['user_name'] = "CLUEL3SS"; $_POST['user_pass'] = "test123"; $_POST['confirm_pass'] = "test123"; $_POST['user_email'] = "user@email.com"; $_POST['confirm_pass'] = 'user@email.com'; function testFunc($inputVars){ foreach($inputVars as $key=>$value){ $escapeData[$key] = mysql_real_escape_string($value); } return $escapeData; } var_dump(testFunc($_POST)); I'm trying to make a user system for my site and I want to make sure its secure enough to void off injection attackers. Any useful advice and and suggestions would be greatly appreciated! Thanks! Hi All, I was wondering if someone maybe knows a nice way to prevent double posting or posting within a certain time without using javascript. Or maybe even echoing an error if someone posts the exact same ase the previous post. I found this little snippet: Code: [Select] onClick="disabled=true;this.form.submit();return true;" Which prevents double clicking. But its javascript and I rather have something besides that to cover all situations. Would love to hear what you guys use or reccomend. Thanks! Our admin panel for a gaming community was recently hit by a successful MySQL injection attack. Here are the parameters they entered into forms to gain access. Code: [Select] ${99319+100354} Code: [Select] <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE acunetix [ <!ENTITY acunetixent SYSTEM "http://testphp.vulnweb.com/dot.gif"> ]> <xxx>&acunetixent;</xxx> Not sure which one worked, or how they even managed to POST to that page. But how do these two strings work? What do they do? How can I prevent the less than and greater than signs in the username field, and message on the post? As well as slashes. / \. Code: [Select] <form method="post" action="" id="reply"> <script type="text/javascript"> function hi(id){ var val = id.options[id.selectedIndex].value; var text = id.options[id.selectedIndex].text; if (val.length != 0){document.getElementById('user').value = text;hide('passrow');} else { document.getElementById('user').value = ''; document.getElementById('passrow').style.cssText = ''; } } </script> <div id="userpass" style="background: #000;"> <table style="border: 2px solid #252564; background: #1F1F5D;" width="100%" cellpadding="0" class="quick_userpass"> <tr> <td background="/images/bg3.jpg" height="26px"><font face=arial size=2 color="white"> <b>Your Name or Nickname</b></td> </tr> <tr> <td><input size=50 name="user" id="user" value="" style="margin-left: 10px;"></td> </tr> <tr><td background="/images/bg3.jpg" height=26px></td></tr> </table> <div id="passrow" style=""> <p> <table width=100% cellpadding=0 class="quick_userpass" style="border: 2px solid #252564; background: #1F1F5D;"> <tr><td background="/images/bg3.jpg" height=26px style=""><font face=arial size=2 color="white"> <b>Password (optional)</b></td></tr> <tr><td style=""><input size=50 name="pass" id="pass" type="password" style="margin-left: 10px;" value=""></td></tr> <tr><td background="/images/bg3.jpg" height=26px></td></tr> </table> </p> </div> <p> <table width=100% cellspacing=0 cellpadding=4 class="quick_userpass" style="border: 2px solid #252564; background: #1F1F5D;"> <tr bgcolor="#121236"><td><font face=arial size=2 color="white"><b>Enter your message here</b></font></td></tr> <tr><td><center><textarea id="quickreply" name="message" rows=10 cols=50 wrap="VIRTUAL" ></textarea></center></td></tr> </table> <div id="preview" style="display: none;"></div> </p> <br /> <center> <font face=arial size=2>When you're happy with your message, click:</font> <div id="javano"><input type="submit" value=" Post Message "></div> </center> <input type="hidden" name="tid" value="<?php echo $_GET["tid"];?>" /> </div> </form> That is the code I'm using for User/Pass/message fields. I am having problems with a search feature I am using for a website I am building. Everything was working fine when I was testing on my local machine using EasyPHP 3.0. The issue I am having is that once I uploaded the site to a "live" server and tested it, my search function wouldn't work. The issue resides in the two lines with the magic quotes and the real escape string, for some reason those lines worked fine while testing using EasyPHP 3.0, but now I must delete those lines in order for my search function to work. The problem is that deleting those lines makes me vulnerable to an SQL injection. I have tried deleting just the magic quotes line and everything works properly, but then I am not seeing any kind of strip slashing/sanitizing when I enter in a statement like this into my search: a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't. Any help on this issue would be greatly appreciated! //get data $button = $_GET['submit']; if (get_magic_quotes_gpc() == 0){ $search = mysql_real_escape_string($_GET['search']); // clean up the search string } else { $search = $_GET['search']; $limit = 9; $page = $_GET['page']; if($page) $start = ($page - 1) * $limit; I also tried using the mysql_real_escape_string on my construct, but I get syntax errors because of the | being used before and after the $search_each. That | character must remain in place in order for my search to work the way I want it to. $x++; if ($x==1) $construct .= "keywords LIKE '%".mysql_real_escape_string(|$search_each|)."%'"; else $construct .= "AND keywords LIKE '%|$search_each|%'"; } Hello all, A simple question: I have a HTML application from which a php script is executed. 'GET' method is used and no form is submitted. I was wondering if there is a way to prevent users from run this php script directly in the browser. Thank you all for your suggestions, Mamer |