Stop direct access to a link...

Discussion in 'PHP' started by PET, Jul 14, 2008.

  1. #1
    Ok, I don't think that the title of the topic is right, however...

    I have a form. I use an ajax function that when a input value change, it sends it to PHP, and the PHP updates the new value in the database.

    The link that the AJAX function sends looks something like this:

    ?act=updstk&id=757&value=NewValue

    Now, everything works fine, however it's easy to find the exact link, and people can update any IDs with any value. That's not good.

    This is my PHP code:

    
    		case 'updstk':
    			if(isset($_GET['id']) && $_GET['id'] != '') {
    				
    				$query = "SELECT `user` FROM `cards` WHERE id=". addslashes($_GET['id']);
    				$result = mysql_query($query) or die(mysql_error());
    				$row = mysql_fetch_array($result);
    				
    				if($_SESSION['user'] == $row['user']){
    				
    					$value = addslashes($_GET['value']);
    					$id    = addslashes($_GET['id']);
    					
    					$query = "UPDATE `cards` SET stock=". $value ." WHERE id=". $id;
    					mysql_query($query) or die(mysql_error());
    				}
    			}
    
    		break;
    
    PHP:
    First I check if GET['id'] was setup.

    Then I do a query of the "card" id and check if the user's id corespons to the logged user id. Each entry has the user id. When a user login's a session with his ID is stored. So user 1 can't edit what user 2 has.

    Then I do the update.

    Well, this works ok. If you try to update something that it's not yours it will not work. If you try to update something that is yours, it WILL work.

    However I also want to limit that. Is there any function or something that, if the link is DIRECTLY typed into the browser and accessed, the script will not execute?

    -------------------

    Also, is my query safe? I have : WHERE id= $_GET. What if they time anything over GET? Is addslashes enough?


    Thanks
     
    PET, Jul 14, 2008 IP
  2. php-lover

    php-lover Active Member

    Messages:
    261
    Likes Received:
    21
    Best Answers:
    0
    Trophy Points:
    58
    #2
    I don't know any way to secure this, but here's what i always did.
    I create a session variable and send together with the link to the destination. When it's reach the destination, I compare the session variable value was send with the link to the session was created. If they are equal then continue the process your link variable. If they are not equal then it's mean someone edit the link.

    I'm trying to let you understand the idea.

    Example.

    www.mywebsite.com/save.php?a=10&b=red&smode=sef8sd9e8s77e6s5s0
    HTML:
    You apply the session variable value to smode.
    When you reach the save.php file then do the compare like this.

    if($_GET['smode'] == $_SESSION['smode']){

    //test is pass

    }else{

    //test is fail, cancel the process

    }


    Always apply new value to smode.

    I hope it will help you.
     
    php-lover, Jul 14, 2008 IP
  3. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #3
    hmm... I got your point.

    You create some random string stored in the SESSION.
    Then you check up if the string is equal with the expected session.

    Right?

    It makes sense, however... how to do this?

    Think that I have a page that it's loaded.
    That page has some inputs.
    When one of the input is changed a javascript function sends the info to PHP.
    PHP updates the new value.

    When can I create that random string and store it into SESSION?

    I think the JavaScript function should store the session. That way we knew the update was made FROM the actual form page. However I don't know if this is possibile.
     
    PET, Jul 14, 2008 IP
  4. php-lover

    php-lover Active Member

    Messages:
    261
    Likes Received:
    21
    Best Answers:
    0
    Trophy Points:
    58
    #4
    here's another example.

    Assume your file name customer.php which contain your form.

    
    
    <?php
    
    session_start();
    
    function sessionID($length=10)
    	{
    		
    		$Pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    		$Pool .= "abcdefghijklmnopqrstuvwxyz";
    		$Pool .= "12345678902366";
    
    		for($index = 0; $index < $length; $index++)
    		{
    			$sid .= substr($Pool, (rand()%(strlen($Pool))), 1);
    		}
    	
    		return(md5($sid));
    	}//sessionid
    	
    	
    $_SESSION['smode'] = sessionID();
    
    $form ='
       <form name="fname">
          <input type="text" name="customer">
          <input type="hidden" id="smode" value="'.$_SESSION['smode'].'">
          <button onclick="save()">Save</button>   
       </form>';
    
    //in your javascript do this.
    
    function save(){
    
    var smode = document.fname.getElementByID('smode').value;   //<---------here's your security mode string
    var customer = document.fname.getElementById('customer').value;
    
    var url = 'http://www.myweb.com/save.php?cust='+customer+'&smode='+smode;
    
    //<--send your url through your ajax connetion 
    
    }
    
    ?>
    
    
    PHP:
     
    php-lover, Jul 14, 2008 IP
  5. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #5
    Hmm...nice sugestion. Now I understand. Thanks

    What about unset($_SESSION['smode'])?

    The session will remain the same. What if he updates the field once. Then save the session, then simply use the same link with different ID & VALUE. Or... he can't actualy find the smode?
     
    PET, Jul 14, 2008 IP
  6. php-lover

    php-lover Active Member

    Messages:
    261
    Likes Received:
    21
    Best Answers:
    0
    Trophy Points:
    58
    #6
    Now is your turn. You can tell me how to hide that value...lol
    I don't know how to hide the smode value from the form.
    Don't worry about that. sessionID function will always provide a different smode.
     
    php-lover, Jul 14, 2008 IP
  7. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #7
    So basicly we generate a random code that we put into a hidden form.
    When we submit the form we also send that code into the link.
    PHP takes the code from the LINK and compares it with the session code.
    If OK PHP executes the requied functions.
    After PHP executes the requied functions we can unset($_SESSION['smode');

    So basicly if he tries to ... somehow use the link again, smode will be empty.

    The single problem is that... he can take the code when he "views source", and paste it into the link and run the update.

    Hmmm...what to do...what to do?

    Can't we manipulate the random strink from a javascript function and store it into Session?
     
    PET, Jul 14, 2008 IP
  8. php-lover

    php-lover Active Member

    Messages:
    261
    Likes Received:
    21
    Best Answers:
    0
    Trophy Points:
    58
    #8
    I know that JavaScript can't create session but it does create cookie. That's our option, we can create a cookie inside javascript and send to the php script. Our php script can access to that cookie and do the compare.
     
    php-lover, Jul 14, 2008 IP
  9. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #9
    Ok. I have some problems. In IE it works PERFECTLY. In Firefox NOT!

    When the button is pressed I have this:

    deletecard(this.id, smode.value).

    
    function deletecard(id, smode){
    	//var smode = document.form1.getElementByID('smode').value;
    	if (confirm("Are you sure you want do delete this card from the database?")) {
    		// fisierul php care va procesa requestul AJAX 
    		var server_uri = "index.php"; 
    		// parametrii care vor fi trimisi prin requestul AJAX 
    		var parametrii = "?act=delete-card&id="+id+"&smode="+smode;
    
    		// se creeaza(pregateste) un request asincron de tipul POST catre adresa 'server_uri' 
    		http.open("GET", server_uri + parametrii, true); 
    		// informeaza serverul ca requestul este de tip POST 
    		http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); 
    		// realizeaza conexiunea definita anterior prin functia open 
    		http.send(null);
    		
    		window.location = "index.php?act=view-card-list";
    	}
    }
    
    Code (markup):
    And this is the PHP code:

    			if(isset($_GET['id']) && $_GET['id'] != '') {
    				
    				$query = "SELECT * FROM `cards` WHERE id=". $_GET['id'];
    				$result = mysql_query($query) or die(mysql_error());
    				$row = mysql_fetch_array($result);
    				
    				// ONLY ALLOW TO DELETE A CARD THAT BELONGS TO THE LOGGED USER
    				if($_GET['smode'] == $_SESSION['smode']){			// CHECK IF SMODE == THE SESSION
    					if($_SESSION['user'] == $row['user']){
    						$id = $_GET['id'];
    						
    						$query = "DELETE FROM `cards` WHERE id=". $id;
    						mysql_query($query) or die(mysql_error());
    						
    						if(mysql_affected_rows() == '0'){
    							$_SESSION['mesaj'] = '<b><font color="red">Card could NOT be DELETED!</font></b>';	
    						}else{
    							$_SESSION['mesaj'] = '<b><font color="green">Card has been DELETED!</font></b>';
    						}
    					}
    				}
    				
    				unset($_SESSION['smode']); // UNSETS SMODE SO IT CAN"T BE USED AGAIN
    			}
    PHP:
    IE simply deletes, get's the redirect and dispaly the message.

    All FIREFOX does is ... redirects. NO MESSAGE , NO DELETE.

    I tested several variants. NOTHING. I don't know what is wrong.

    I tried on the CONFIRM to display smode and it works. So SMODE is taken corectly.

    If I take out if($_GET['smode'] == $_SESSION['smode']){ it works. But what's the problem? IE working fine, Firefox working fine.

    --------------------------------

    After some testing I decided to delete the whole PHP function and I simply put:

    $_SESSION['mesaj'] = $_GET['id'] . " ++ " . $_GET['smode'];

    In IE I see the message containg the ID + SMODE. In firefox NOT. So it's clearly a SESSION problem. I have session_start(); at the begining of every file so that's not the problem. Again, IE ok ... firefox notok.

    Any sugestions? This is driving me crazy.
     
    PET, Jul 23, 2008 IP
  10. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #10
    Nevermind... now Firefox shows the session message. I'm going to take a break to clear my mind :)
     
    PET, Jul 23, 2008 IP
  11. CarcaBot

    CarcaBot Active Member

    Messages:
    389
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    58
    #11
    Hello,

    first of all

    why you use
    
    if(isset($_GET['id']) && $_GET['id'] != '') {
    
    PHP:
    instead of
    
    if(isset($_GET['id'])) {
    
    PHP:
    you have there same thing in one line
    it's normal if isset ID it must have a value

    in the rest, all php code is valid.
    The problem with browsers is from Firefox

    Check if your firefox have javascript enabled .
    if is, try to make another javascript which do same thing but other codes.

    /CarcaBot
     
    CarcaBot, Jul 23, 2008 IP
  12. ToddMicheau

    ToddMicheau Active Member

    Messages:
    183
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    58
    #12
    Just a quick suggestion that, skimming through the topic, I don't think anyone suggested- referrers? When you use ajax the referrer is always your site, but if someone tried to do what you were saying- updating any id with any value, then the referrer would be blank. I think, lol. Just a thought, might be more simpler to check the referrer than anything else. . .

    (Yes, some people know how to change their referrer.)
     
    ToddMicheau, Jul 23, 2008 IP
  13. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #13
    Yea but then what if ID is set but it's empty? It would be the same thing, just that it's empty.
     
    PET, Jul 24, 2008 IP
  14. VideoGirls

    VideoGirls Member

    Messages:
    74
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    41
    #14
    Use $_SERVER['HTTP_REFERER'] to check if the url was accessed from the website or another way:

    
    $server_name=$_SERVER[SERVER_NAME];
    if (substr($server_name,0,4)=="www.") $server_name=substr($server_name,4);
    
    if (!strstr($_SERVER['HTTP_REFERER'], $server_name)) echo "This was not accessed from this website!";
    
    PHP:
     
    VideoGirls, Jul 25, 2008 IP
  15. PET

    PET Member

    Messages:
    86
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    43
    #15
    Back to the old problem. I have rewritten the "card delete" code in PHP. This is how it looks:

    
    			if(isset($_GET['id']) && $_GET['id'] != '') {
    				$id = addslashes($_GET['id']);
    				
    				// Query the user ID from the card that needs to be deleted
    				// If the session user ID == cards user's id then the card can be deleted
    				$query = "SELECT `user` from `cards` where id=". $id;
    				$result = mysql_query($query) or die(mysql_error());
    				$row = mysql_fetch_assoc($result);
    				$userid = $row['user'];
    				
    				if($_GET['smode'] == $_SESSION['smode'] && $_SESSION['user'] == $userid){
                        // Deleting the card
                        $query = "DELETE FROM `cards` WHERE id=". $id;
                        mysql_query($query) or die(mysql_error());
                        
                        // Set up session message
                    	if(mysql_affected_rows() == '1'){
                    		$_SESSION['mesaj'] = '<b><font color="green">Card was deleted from the database!</font></b>';
                    	}
    			    }else{
                    	$_SESSION['mesaj'] = '<b><font color="red">Card could NOT be deleted!</font></b>';
                    }
                    
    			    unset($_SESSION['smode']);
    		    }
    
    PHP:
    This is the JavaScript code:

    
    function deletecard(id, smode){
    	//var smode = document.form1.getElementByID('smode').value;
    	if (confirm("Are you sure you want do delete this card from the database?")) {
    		// fisierul php care va procesa requestul AJAX 
    		var server_uri = "index.php"; 
    		// parametrii care vor fi trimisi prin requestul AJAX 
    		var parametrii = "?act=delete-card&id="+id+"&smode="+smode;
    
    		// se creeaza(pregateste) un request asincron de tipul POST catre adresa 'server_uri' 
    		http.open("GET", server_uri + parametrii, true); 
    		// informeaza serverul ca requestul este de tip POST 
    		http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); 
    		// realizeaza conexiunea definita anterior prin functia open 
    		http.send(null);
    		
    		window.location = "index.php?act=view-card-list";
    	}
    }
    
    
    Code (markup):

    Please tell me what is wrong with the javascript code? In Internet Explorer it works PERFECTLY. The card get's deleted and i get an OK message. In Firefox, nothing happens. I just get "redirected" by the last line of code. All other Ajax stuff works ok.
     
    PET, Aug 1, 2008 IP