"Hiding" the URL from the user
Moderator: General Moderators
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
"Hiding" the URL from the user
I need to pass variables from one PHP script to another, but I don't want the user to see them. That rules out using the URL to pass the variable as the user can see them in the address bar. POSTing them to the next form would prevent them from showing in the address bar, but if the user looks at the source code of the previous page then they will see the variables in the form. Is there another way of passing variables between pages?
Thanks
Mark
Thanks
Mark
- CoderGoblin
- DevNet Resident
- Posts: 1425
- Joined: Tue Mar 16, 2004 10:03 am
- Location: Aachen, Germany
You could try saving them in a session variable.
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
Thanks for that. I had considered using a session, but the problem is that the user needs to click a link in order to initiate the storage of the variable. This means I will have to POST or GET the variable to another script which then stores the variable.
It has just occurred to me that it doesn't matter whether the user can see the variable, only that they can't change it. So POSTing it from a hidden form element would be ok. Even if the user can see the variable in the HTML source, the following script will only get the variable from the POST data, so the user cannot change it.
*goes and changes every link in web app*
It has just occurred to me that it doesn't matter whether the user can see the variable, only that they can't change it. So POSTing it from a hidden form element would be ok. Even if the user can see the variable in the HTML source, the following script will only get the variable from the POST data, so the user cannot change it.
*goes and changes every link in web app*
You could try Mode rewrite rule
Hi Mark,
You could use mode rewrite rule for url rewriting, for it you have to write mode rule in .htaccess file.
Example: If you want to pass variable like -- http://yourdomain.com/page.php?id=1234
then you could change the url like - http://yourdomain.com/page1234.html
or http://yourdomain.com/page12separator34.html etc
Thanks
Souvit.
You could use mode rewrite rule for url rewriting, for it you have to write mode rule in .htaccess file.
Example: If you want to pass variable like -- http://yourdomain.com/page.php?id=1234
then you could change the url like - http://yourdomain.com/page1234.html
or http://yourdomain.com/page12separator34.html etc
Thanks
Souvit.
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
This is not necessarily as secure as you think. The user could easily view source, copy source, change data on their local machine and post it to your server.MarkAshley wrote:It has just occurred to me that it doesn't matter whether the user can see the variable, only that they can't change it. So POSTing it from a hidden form element would be ok. Even if the user can see the variable in the HTML source, the following script will only get the variable from the POST data, so the user cannot change it.
Sessions are the best way to go for this, I would guess.
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
Let me explain the setup from the beginning, as this may help someone explain the best way
I have a menu from which the user can select one of several options. Each option takes the user to a different page. Initially, the variables the page needed were in the URL, and I used GET to retrieve them. Obviously the user could copy the URL, modify the variables, and paste it in to the address bar to modify the data in a way I don't want them to.
I then created hidden form elements. Clicking the links runs Javascript which populates the form elements with the variables, then posts them to the following page. This has the advantage that the user can't just modify the URL to change the data. It hadn't occurred to me that somebody could post data to my web server with a customised document. Is there a setting in the PHP server to prevent this, so it will only accept POST data from documents running on the server?
If I go with the session method, I don't see how this will help me. If the user clicks a link, it has to go to a page which stores the variables in the session. So I still have to get the variables securely to that page. Back to square one
I have a menu from which the user can select one of several options. Each option takes the user to a different page. Initially, the variables the page needed were in the URL, and I used GET to retrieve them. Obviously the user could copy the URL, modify the variables, and paste it in to the address bar to modify the data in a way I don't want them to.
I then created hidden form elements. Clicking the links runs Javascript which populates the form elements with the variables, then posts them to the following page. This has the advantage that the user can't just modify the URL to change the data. It hadn't occurred to me that somebody could post data to my web server with a customised document. Is there a setting in the PHP server to prevent this, so it will only accept POST data from documents running on the server?
If I go with the session method, I don't see how this will help me. If the user clicks a link, it has to go to a page which stores the variables in the session. So I still have to get the variables securely to that page. Back to square one
-
nickvd
- DevNet Resident
- Posts: 1027
- Joined: Thu Mar 10, 2005 5:27 pm
- Location: Southern Ontario
- Contact:
What variables don't you want your users to see? (post examples pls)
If you need to pass variables from page to page, the user WILL be able to see them... I can't really see any other way to do it other than perhaps sessions (as was mentioned)
A little more detail as to what you're passing from page to page would help!
If you need to pass variables from page to page, the user WILL be able to see them... I can't really see any other way to do it other than perhaps sessions (as was mentioned)
A little more detail as to what you're passing from page to page would help!
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
the only suggestion I can offer is validate, validate, validate. Then authenticate. In order to capture information from a user, a user has to give that information to you. This is most commonly handled by a form. That means that the data is a) Open to hijack; and b) Viewable/changeable. If your script knows what the values are supposed to be, and the required security level of the script is such that people should not be able to post anything they want, then I would suggest you do some serious white-list type validation of the passed information before doing anything with it.
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
Ok here's what I'm doing. I'm writing a space combat/trading game in PHP. If the player wants to travel from one planet to another, they click a link which lists all of the planets within their range, then then click another link which takes them there. This link would go to a page something like "traveltoplanet.php?session=$session&planet_id=$planet_id", where $planet_id is the planet's primary key in the database.
If the user changes the planet_id, they could potentially travel to a planet on the other side of the universe, even if it's not within their range. I have put in checks to make sure the user doesn't do this, but as the game gets more and more complex I have to put in more and more checks in to more and more pages. For example, there are certain things the user can't do while they're in "Hyperspace" or when docked with another vessel. That means I have to go back through every single script and put in checks. This is laborious, and potentially I might miss something allowing the user to cheat. Rather than checking everything the user is doing, I would rather design the code so the user can't go to pages they're not supposed to.
I had an idea today. When the page is created by the PHP script, each link is given a unique URL ID. This is stored in a table along with the user_id, and the actual URL. When the user clicks the link, it takes them to "gotopage.php?url_id=$url_id". gotopage.php then retrieves the actual URL from the database using the URL ID and the user ID, includes the page specified in the URL, and then deletes all of the URL IDs for that user (so they are only valid once). If the URL ID is long enough, then the user won't be able to guess it. Because the actual URL will only be visible to the script, the user will never see it and won't be able to modify it.
Any thoughts?
If the user changes the planet_id, they could potentially travel to a planet on the other side of the universe, even if it's not within their range. I have put in checks to make sure the user doesn't do this, but as the game gets more and more complex I have to put in more and more checks in to more and more pages. For example, there are certain things the user can't do while they're in "Hyperspace" or when docked with another vessel. That means I have to go back through every single script and put in checks. This is laborious, and potentially I might miss something allowing the user to cheat. Rather than checking everything the user is doing, I would rather design the code so the user can't go to pages they're not supposed to.
I had an idea today. When the page is created by the PHP script, each link is given a unique URL ID. This is stored in a table along with the user_id, and the actual URL. When the user clicks the link, it takes them to "gotopage.php?url_id=$url_id". gotopage.php then retrieves the actual URL from the database using the URL ID and the user ID, includes the page specified in the URL, and then deletes all of the URL IDs for that user (so they are only valid once). If the URL ID is long enough, then the user won't be able to guess it. Because the actual URL will only be visible to the script, the user will never see it and won't be able to modify it.
Any thoughts?
You have no other choice. Everything vital has to be checked server-side, there's no way around that.MarkAshley wrote:I have put in checks to make sure the user doesn't do this, but as the game gets more and more complex I have to put in more and more checks in to more and more pages.
But you have to check that, too.MarkAshley wrote:Rather than checking everything the user is doing, I would rather design the code so the user can't go to pages they're not supposed to.
In your example you test wether the url_id is in the database or not, that's at least one INSERT and one SELECT statement.
How is this list computed? Isn't it easy to derive a function that tells you wether a player can travel from A to B?MarkAshley wrote:they click a link which lists all of the planets within their range
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
Yes, that example is simple. It just checks how far away the planet is, and whether they can travel that far. If they can't then it errors. But there are so many permutations of actions that I'm worried I won't be able to check for all of them. For example, the user's vessel can be in one of several states, including orbiting a planet, landed on a planet, docked with another vessel, in hyperspace..... The links available to the user change depending on their state, but if the user can force the site to go to a different page then they can do whatever they want regardless of their state. Adding checks to every page to make sure the user's status allows them to be on that page could potentially leave holes in the checks which would allow users to cheat.
Wouldn't the idea I had of using a URL ID instead of an actual URL prevent the user from modifying the URL in any way or passing different variables to the page?
Wouldn't the idea I had of using a URL ID instead of an actual URL prevent the user from modifying the URL in any way or passing different variables to the page?
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
Here's an example of using the URL ID:
The result is a menu with one item which passes the randomly generated url_id back to the index, which then feeds this in to the database to get the actual url back, and then includes it. Because the url_ids are all deleted each time the page loads and are then re-generated, it will be impossible for the user to visit a page using the url_id (unless they can guess a 128 character url_id).
What do you think?
--EDIT
Made the URL adding routine a function to make it easier to add more URLs to the page.
Code: Select all
<?
//index.php
function addurl($url, $text){
$url_id="";
for ( $i=0; $i<=128; $i+=1 ){
$url_id=$url_id.rand(0,9);
}
mysql_query("INSERT INTO urls VALUES('$user_id','$url_id','$url')");
echo "<a href=\"index.php?url_id=$url_id\">$text</a>";
}
require('connect.php');
mysql_query("DELETE FROM urls WHERE user_id='$user_id'");
$url_id=$_GET[url_id];
$result=mysql_query("SELECT url FROM urls WHERE url_id='$url_id' AND user_id='$user_id'");
@$url=mysql_result($result,0,"url");
if ( $url == "" ){
$url="mainmenu.php";
}
require($url);
?>Code: Select all
<?
//mainmenu.php
addurl("menuitem1.php","Menu Item 1");
addurl("menuitem2.php","Menu Item 2");
?>The result is a menu with one item which passes the randomly generated url_id back to the index, which then feeds this in to the database to get the actual url back, and then includes it. Because the url_ids are all deleted each time the page loads and are then re-generated, it will be impossible for the user to visit a page using the url_id (unless they can guess a 128 character url_id).
What do you think?
--EDIT
Made the URL adding routine a function to make it easier to add more URLs to the page.
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
I'll reitterate what volka said... there is no way around it. There is absolutely no way to prevent users from throwing anything into the address bar that they want. There is nothing preventing a user from copying your forms to their local machine and processing their own data. The only way to make sure everything works the way you need it to is to take the text I just quoted and make it code. Then, as the game grows, your code grows.MarkAshley wrote:Yes, that example is simple. It just checks how far away the planet is, and whether they can travel that far. If they can't then it errors. But there are so many permutations of actions that I'm worried I won't be able to check for all of them. For example, the user's vessel can be in one of several states, including orbiting a planet, landed on a planet, docked with another vessel, in hyperspace..... The links available to the user change depending on their state, but if the user can force the site to go to a different page then they can do whatever they want regardless of their state. Adding checks to every page to make sure the user's status allows them to be on that page could potentially leave holes in the checks which would allow users to cheat.
I would suggest looking into modularizing your code a bit. When it comes to checking/validating/authenticating, this should all come from a single include file so as things change, you make one edit in one file and it affects all pages dependent on that group of tasks. That is the easiest way to ensure that you do not have to edit every page should there be a change later on.
-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
It works
Here's the final code I used:
All of the child pages from mainmenu.php have their URLs added in the same manner. This is secure because the actual URL is only known to the PHP scripts and the database. It is never echoed in a link. The only thing the user can see in the HTML is the URL ID, which means nothing without seeing the corresponding record in the database. The DELETE command ensure that the URL ID can't be re-used even if the user knows what it is.
Code: Select all
//index.php
function addurl($url, $text, $session, $user_id){
$url_id="";
for ( $i=0; $i<=127; $i+=1 ){
$url_id=$url_id.rand(0,9);
}
mysql_query("INSERT INTO urls VALUES('$user_id','$url_id','$url')");
echo "<a href=\"index.php?session=$session&url_id=$url_id\">$text</a>";
}
$url_id=$_GET[url_id];
$result=mysql_query("SELECT url FROM urls WHERE url_id='$url_id' AND user_id='$user_id'");
@url=mysql_result($result,0,"url");
if ( $url == "" ){
echo "<script>location.href='login.php'</script>"
exit;
}
mysql_query("DELETE FROM urls WHERE user_id='$user_id'");
require($url);Code: Select all
//mainmenu.php
addurl("land.php", "Land on $planetname", $session, $user_id);
addurl("traveltoplanets.php", "Travel to planets in the $system system", $session, $user_id);
//More menu entries here.....-
MarkAshley
- Forum Commoner
- Posts: 34
- Joined: Fri Nov 18, 2005 1:36 am
You replied while I was transcribing the code I used
The method I have used seems to work very well and it stops the user from accessing any page they are not supposed to (unless they can guess the 128 digit URL ID - and if they can do that, then they can guess someone else's session ID and /really/ screw things up
)
I see your point about having to check everything server side. But I feel given the complexity of the game this is the best way to ensure people don't do things they're not supposed to do.
I see your point about having to check everything server side. But I feel given the complexity of the game this is the best way to ensure people don't do things they're not supposed to do.