Accepting user input through GET
Your smart PHP application should be able to accept user input and serve different pages, depending on the user request. This is really powerful, let's see how you can achieve it.
There are different ways for a web page to accept input from the user, the most common being through GET and POST requests.
What's in a request
When a user clicks on a link or types in the address bar, he/she requests a page (a file, a resource) from a remote server. This is done through the use of the HTTP protocol, so we say that the user makes an HTTP request. The resources out there are identifiable by their URL.
Let's take a URL:
http://www.w3clubs.com/w3clubs-examples/ragtime2/index.php
What we have here:
- The whole thing is a URL
httpidentifies the protocolwww.w3clubs.comis the host name/w3clubs-examples/ragtime2/index.phpidentifies where the resource is located
Just for information, here's how an HTTP request may look like:
GET /w3clubs-examples/ragtime2/index.php HTTP/1.1 Host: www.w3clubs.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://www.w3clubs.com/w3clubs-examples/ragtime2/ Cache-Control: max-age=0
To see the HTTP headers being exchanged when you request and receive pages, I'd recommend using the Firefox extensions LiveHTTPHeaders or the Net panel of Firebug. For IE and other browsers on Windows you can also use Fiddler.
GET
Notice the word GET in the request above? It specifies the request method.
Now let's check this URL:
http://www.w3clubs.com/w3clubs-examples/ragtime2/index.php?key=value
The part after the question mark is called a query string, it allows you to pass parameters when making a request. You can have several query parameters, divided by an &
http://www.w3clubs.com/w3clubs-examples/ragtime2/index.php?key=value&something=else
The cool thing is that in your PHP script you have access to those parameters and can do different things, for example branch the page execution, based on different values being passed in the query string.
You can access the query string parameters (let's call them GET parameters) through the array $_GET which PHP defines for you. Let's see an example.
Example
Create the script C:\mywebstuff\htdocs\php-tutorial\get.php (how to setup here) with the following contents:
<pre> <?php print_r($_GET); ?> </pre>
Now load this script in the browser, like http://localhost/php-tutorial/get.php
The result might be slightly disappointing, but it does illustrate something important - that the $_GET array is always defined. The result is:
Array ( )
Now let's change the URL of the request to:
http://localhost/php-tutorial/get.php?key=value
The result:
Array
(
[key] => value
)
And how about http://localhost/php-tutorial/get.php?key=value&something=else
Array
(
[key] => value
[something] => else
)
Never trust user input
You just learned how to get user input and now I'm telling you not to trust it. What gives?
Not trusting user input is an important lesson (that many have learned the hard way) and cannot be over-emphasized.
Let's say you have the following script:
<?php echo 'Hello ', $_GET['user'], '!'; ?>
When you request is like http://localhost/php-tutorial/user.php?user=stoyan, this is a friendly little page that greats me:
Hello stoyan!
But as a malicious user I can try adding HTML tags in my username and nothing in the script will stop me:
http://localhost/php-tutorial/user.php?user=<b>stoyan</b>
This will result in:
Hello stoyan!
So what? So far, not so bad. But why stop here? I can also pass javascript as a parameter.
http://localhost/php-tutorial/user.php?user=<script>location='http://www.phpied.com'</script>
What will happen? As soon as you load the page, you're redirected to my blog at http://www.phpied.com, because the script printed whatever was passed as 'user' parameter, so the HTML looks like:
Hello <script>location='http://phpied.com'</script!>
Redirecting to a page is bad enough, but could be worse. With javascript you have access to the browser cookies, so a malicious user can not only redirect to a new page, but also send your cookies to this page and this way steal your session. Imagine PayPal doing such a mistake. A hacker can get your session ID and put it in his browser cookies, this way logging in as you and making some payments. Scary stuff.
The take-home message here is:
When you accept user input, expect the unexpected. If you ask for example for a phone number from the user, don't assume you'll only be receiving numbers, be also prepared to deal with all kinds of characters, HTML and JavaScript strings.
What's the fix to the vulnerability above? Surprisingly simple, just use function htmlspecialchars(), it will make all > and < into > and < and the script will never be executed.
<?php
if (!empty($_GET['user'])) {
echo 'Hello ', htmlspecialchars($_GET['user']), '!';
}
?>
The result displayed in the browser will be:
Hello <script>location='http://phpied.com'</script>!
because the HTML code generated will be:
Hello <script>location='http://phpied.com'</script>!