jeffz2008 Posted September 8, 2009 Share Posted September 8, 2009 --------------------------------- Frankly, it makes me feel uneasy when I have to send something using $_GET. Especially if it can influence data written to DB. Lately I have developed some workaround, but I'm unsure If it really make sense. I wonder if it won't be undone by register_globals on, or some other PHP peculiarities I haven't even heard about yet. What is your opinion? Does that make sense? What I wanted to accomplish: - hide vital variables from snooping eyes. - prevent any messing about with data sent What and how I did it: PREPARE FOR SEND: 1. prep $_GET string, eg. something like below, usually sent open text: result: $str= 'phase=3&set=2&pID=1015&oID=9309&qty=2&opi=11113&src=2&id=18' 2. create md5 hash of a string to prevent tampering with encrypted $_GET string by user result: be9ace7a810c3bf461ec5e768b63c7cf 3. passprase ecrypt string - using custom function passphrase can be stored as constant in config.php file (or similar), or stored in DBase; my projects are IonCube encrypted, so config.php file seems to be pretty well protected. length between 8-32 chars result: $str = 'zlf{d"'/bqdwh 08vs~.%,wQT""8'?jMI :,=/,bcs:)6pf`/(448%%LR7 "2!kb|+;4pa9<' ; 4. make sure that is will get unbroken through web/browser encoded by custom function using base64_encode php function (it replaces - among other things web-unsafe chars as " '+','/','=' " result: emxme2QiJy9icWR3aCAwOHZzfi4lLHdRVCIiOCc_ak1JIDosPS8sYmNzOik2cGZgLyg0NDglJX9MUjcgIjIha2J8Kzs0cGE5PA 5. combine 2. and 3. for $_GET shipment, using some joiner-string - I use: 000111000, but it can be anything result: emxme2QiJy9icWR3aCAwOHZzfi4lLHdRVCIiOCc_ak1JIDosPS8sYmNzOik2cGZgLyg0NDglJX9MUjcgIjIha2J8Kzs0cGE5PA000111000be9ace7a810c3bf461ec5e768b63c7cf 6. send 5. as one $_GET variable, eg. result: d=emxme2QiJy9icWR3aCAwOHZzfi4lLHdRVCIiOCc_ak1JIDosPS8sYmNzOik2cGZgLyg0NDglJX9MUjcgIjIha2J8Kzs0cGE5PA000111000be9ace7a810c3bf461ec5e768b63c7cf Practical side- how it looks in code (in a simplified way): $str = 'phase=3&set=2&pID=1015&oID=9309&qty=2&opi=11113&src=2&id=18'; $link = jp_encode64($str); //custom function described above. <a href="https://www.server.co.uk/admin/file.php?d=$link">[send me]</a> RECEIVING AND HANDLING STRING 1. spliting $_GET var using joiner (see: 5 above) resultes: a. emxme2QiJy9icWR3aCAwOHZzfi4lLHdRVCIiOCc_ak1JIDosPS8sYmNzOik2cGZgLyg0NDglJX9MUjcgIjIha2J8Kzs0cGE5PA b. be9ace7a810c3bf461ec5e768b63c7cf 2. decoding chunk a - using base64_decode url-safe modified version result: $str = 'zlf{d"'/bqdwh 08vs~.%,wQT""8'?jMI :,=/,bcs:)6pf`/(448%%LR7 "2!kb|+;4pa9<' ; 3. decrypting 2. using custom function (passphrase based) result: $str= 'phase=3&set=2&pID=1015&oID=9309&qty=2&opi=11113&src=2&id=18' 4. md5 hashing 3. and comparing against 1. b. , if not the same die() otherwise go. 5. retrieving variables from 3 $str if 4. is a go. how: Tt must be dynamic, otherwise its useless really. I tackled that using foreach and $$var php capacity. In other words, above $$var allows $name = 'Some_text'; $$name = 123; echo $Some_text; // outputs: 123 Variable name named after a string. All that dynamic retrieval takes some 10 lines of code. sample: $encrypted_str = $_GET['d']; if (isset($encrypted_str) && !empty($encrypted_str)) { $str = jp_decode64($encrypted_str); $outerArray = explode('&',$str); foreach ($outerArray as $key => $val) { $innerArray = explode('=', $val); $prepGETvar = $innerArray[0]; $$innerArray[0] = $innerArray[1]; } } ADDITIONAL NOTES: 1. calling variables: To call retrieved from string var just use name which was chosen when $_GET string was $str = 'phase=3&set=2&pID=1015&oID=9309&qty=2&opi=11113&src=2&id=18'; eg. $phase or $oID or $opi etc. It has nothing to do with registered_globals. Foreach loop creates dynamically these variables on top of a page, using $key for a name and $val for a value. Rest of file can use these created on top vars. 2. tampering: Tampering with any part of $_GET passed encrypted variable is impossible. a. if data chunk is tampered with - md5 check does not match b. if joiner string is changed decode function cannot properly split passed encrypted variable and gives up returning error c. if $_GET passed md5 created at the beginning is tampered with, it does not match newly created md5 resulting in error Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 8, 2009 Share Posted September 8, 2009 So what is the problem with simpy validating the parameters passed on the query string? All I see is an overcomplex method of masking the values in a query string. If these values are confidential you shouldn't be passing them through GET anyway. Personally I have no fear of passign data through GET when it suits me because I always validate user input. Quote Link to comment Share on other sites More sharing options...
Alex Posted September 8, 2009 Share Posted September 8, 2009 It's possible, of course.. But usually not necessary. You probably shouldn't be sending data that's so sensitive it can't be validated through a simple check. I've only ever done this once myself; and it was for something stupid anyway. I was creating an image water-marker, but I didn't want to save a new image, and I didn't want the url of the water-marked image to be public. So I encrypted the URL of the image within the query string for the water-marking file. Quote Link to comment Share on other sites More sharing options...
dreamwest Posted September 8, 2009 Share Posted September 8, 2009 Heres another way: say you have a normal link to download files: http://site.com/get.php?id=876 function password_gen($min=6,$max=6,$id){ /*has a default min value of 6 and maximum value of 6*/ $pwd=""; // to store generated password for($i=0;$i<rand($min,$max);$i++){ $num=rand(48,122); if(($num >= 97 && $num <= 122)) $pwd.=chr($num); else if(($num >= 65 && $num <= 90)) $pwd.=chr($num); else if(($num >=48 && $num <= 57)) $pwd.=chr($num); else $i--; } return "encrypt->".strtoupper($pwd).mt_rand()."l".$id."l".strtoupper($pwd).time(); } $file_id = password_gen(6,6,$row['id']); As you can see the link will be something like this: http://site.com/get.php?=encrypt->3EA4VTRM1875445687l876lA4VTRM1252451005 You can see in the center l876l so in get.php simply explode the "l" to get the id which is 876, because the link is always changing its almost imposible for ppl to run grabbers on your site Now someone could write a script to simply explode the "l" anyways, so pull the "salt" from a database, update the salt whenver you like Quote Link to comment Share on other sites More sharing options...
pacholo Posted September 9, 2009 Share Posted September 9, 2009 you can use md5() a function in php and then put it back to your link?the return value of the md5() function it may go something like $dir="member"; echo $a=md5($dir); echo " <a href= viewinfonotlog.php?id=$a'>sample </a>" Quote Link to comment Share on other sites More sharing options...
Garethp Posted September 9, 2009 Share Posted September 9, 2009 If you want to hide variables from peoples eyes, I'd suggest using sessions. In sessions, they can't see nor edit the data stored Quote Link to comment Share on other sites More sharing options...
jeffz2008 Posted September 9, 2009 Author Share Posted September 9, 2009 1. $_POST <form> POSTed variables to some process.file</form> What if I wan't to pass some variables elsewhere without employing form for it. Say form is dealing with some data, but user must have an option to pass variables available to that form to another form (say user has options and he just changed his mind about using this particular form and wants to switch to another keeping variables in tact) without firing up that post altogether. I could send form for processing and redirect from there to another option (form, file), but link residing within form with GET vars available to that form comes way more handy. If these vars are plain text they can be messed up with. 2. session If you have to pass literally dozens variables during use of software by user (sort of user session) , session can get swollen with them, so you have to set them and unset them constantly to keep it light. That setting/unsetting makes sessions approach much more workload costly than encrypted GET. Encrypted GET allows to hide variables from prying eyes and these vars expire automatically when page is closed. 3. testing and verifying data on arrival Quite troublesome if you have vars passed by GET interacting with each other in a specific way. example: order_id=12&order_prod_id=67 where order_id - obvious order_prod_id - id in table storing products for given order If numbers are changed, then dbase written info based on passed variable is out of whack. Testing and validating interactions between 2 or 3 vars is possible, but what if you have to test interconnections between a dozen of vars, or two dozens or more? Wouldn't it be better to use GET and just prevent anyone from messing with them? INITIAL QUESTION REMAINS: Can this way be messed up by php itself? Quote Link to comment Share on other sites More sharing options...
Adam Posted September 9, 2009 Share Posted September 9, 2009 The logic and error handling behind your code should prevent getting 'whack' results if a user were to mess with the parameters. That's like relying on "username=" to be the correct user. Also the GET parameters HAVE to be entered at some point, which would likely be the hole that those wishing to hack your GET parameters would use. Which ever way you try to dress the data up, there still has to be a user input of some form, containing clean, unencrypted data that can be manipulated by the user. Quote Link to comment Share on other sites More sharing options...
Psycho Posted September 9, 2009 Share Posted September 9, 2009 If these vars are plain text they can be messed up with. So? You should always have appropriate validation and error handling for user submitted data. That setting/unsetting makes sessions approach much more workload costly than encrypted GET. What do you base that on? I would guess the overhead of encrypting/unencrypting you are doing would be more costly. If you want to save all POST values to the session, it only takes two lines of code unset($_SESSION['post']); //remove prev. values $_SESSION['post'] = $_POST; //Add new post values 3. testing and verifying data on arrival Quite troublesome if you have vars passed by GET interacting with each other in a specific way. example: order_id=12&order_prod_id=67 where order_id - obvious order_prod_id - id in table storing products for given order If numbers are changed, then dbase written info based on passed variable is out of whack. Testing and validating interactions between 2 or 3 vars is possible, but what if you have to test interconnections between a dozen of vars, or two dozens or more? Wouldn't it be better to use GET and just prevent anyone from messing with them? Not in my opinion, you should still validate the data. If you don't want the user accessing the data, use SESSION INITIAL QUESTION REMAINS: Can this way be messed up by php itself? PHP does what you tell it - just like any programming language. The quality of the code is only as good as the logic used. This is precisely the reason I would suggest that doing all this is pointless. You are introducing more complexity into the process than you need to. If something goes wrong you won't know if it's due to the obfuscation of the GET vars or in some other logic. Quote Link to comment Share on other sites More sharing options...
jeffz2008 Posted September 9, 2009 Author Share Posted September 9, 2009 MrAdam === User can do very little to influence GET data. He can only select link or not. Rest is auto generated depending on link purpose, vars on the page etc. What I'm concerned with is that once GET arrives at its destination that auto generated collection of GET vars is put together for a reason and is someone tries to mess that reason up, results may be distorted. Testing data is not a problem, problem is in strict data correlation and that almost cannot be tested. At least not from a practical standpoint. So if GET is a winner - it has to be somehow protected against tampering. mjdamato === Actually you are right. Bulk session create/clean up is not really a problem here. Problem is that total session clean-up may (and most likely will) clean elements which are vital like login data - just to start with. In such case one have to either: a. re-set them again (I guess - not the best idea) b. elements passed using session have to be unset one by one, which can create quite a workload in case when there are several vars are SESSION passed - that's where that "session workload" came from. Another point is that system I work with relies on GET auto generated data quite often and changing that would get me into way too much free overtime:), as I would have to redo too much. BTW: do you consider string encrypt/decrypt routine - as described above - will be very costly? Practical tests show almost no strain on system as user pool is quite limited. AND Dear Readers of this thread ... please do not take me as someone "full of it" trying to show off, looking for attention or something. My php knowledge/experience is quite OK, but the more I know, the more questions I have (truism - I know). And asking is never wrong. And someone might have dealt successfully with the problem and is willing to share his/her observations. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.