diving into php
DESCRIPTION
Course lecture for Fast, Easy, Complicated, and Powerful Webhttp://fecpw.phiffer.org/TRANSCRIPT
Diving into PHPFast, Easy, Complicated, and Powerful Web
ITP, Spring 2011, section 1, session 1Dan Phiffer [email protected]
Diving into PHP
A simple content management system
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
<form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
Basic form
<?php echo $_REQUEST["query"]; ?><form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
Feedback
<?php echo $_REQUEST["query"]; ?><form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
Feedback
<?php echo $_REQUEST["query"]; ?><form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
What’s that ‘notice’ about?
<?phpif (isset($_REQUEST["query"])) { echo $_REQUEST["query"];}?><form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
Solution: check if it’s set
<?phpif (isset($_REQUEST['query'])) { echo "<h1>You wrote: '{$_REQUEST['query']}'</h1>";}?><form action="basic-form.php"> <input type="text" name="query" /> <input type="submit" name="button" value="Kablooey" /></form>
Dynamic strings
Try it out
<?php$query = "";if (isset($_REQUEST["query"])) { $query = $_REQUEST["query"]; echo "<h1>You wrote: '$query'</h1>";}?><form action="basic-form.php" > <input type="text" name="query" value="<?php echo $query; ?>" /> <input type="submit" name="button" value="Kablooey" /></form>
Defining a new variable
Step 1 complete!
Wait, this is bad
User types input...
Clicks away... arbitrary JavaScript execution!
We’ve been tricked into adding an ‘onblur’ attribute!
Cross-site scripting (XSS)
• A common security vulnerability
• When content is unintentionally executed as code
• We must handle user-submitted content very carefully
Dangers of XSS
• Users’ sessions could be hijacked
• Passwords could be stolen
• Your site could get spammed up
• Puppies murdered, etc.
<?php$query = "";if (isset($_REQUEST["query"])) { // htmlentities() turns " into " $query = htmlentities($_REQUEST["query"]); echo "<h1>You wrote: '$query'</h1>";}?><form action="basic-form.php" > <input type="text" name="query" value="<?php echo $query; ?>" /> <input type="submit" name="button" value="Kablooey" /></form>
Escaping user input
Before & after escaping
Now we’re really finished with step 1
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
Adding a database
Relational databases
• Tables with columns and rows of individual data cells
• SQL is the language for working with relational databases
• MySQL is the database platform used by WordPress
The four operations
• Create new rows with INSERT
• Read rows with SELECT
• Update rows with UPDATE
• Delete rows with DELETE
• MySQL documentation
MySQL clients
• Sequel Pro (Mac OS X)
• SQLWave, SQLMaestro (Windows)
• phpMyAdmin (web-based)
• Or from the command-line: ‘mysql’
$ mysql -u root
mysql> CREATE DATABASE
-> tinydb CHARACTER SET utf8;
mysql> USE tinydb;
mysql> CREATE TABLE tinytable
-> (id INTEGER PRIMARY KEY AUTO_INCREMENT);
mysql> ALTER TABLE tinytable ADD COLUMN
-> content TEXT;
mysql> INSERT INTO tinytable
-> (id, content)
-> VALUES (1, 'Hello, world!');
mysql> SELECT * FROM tinytable;
Let’s build a tiny wiki!
A simple content management system
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
A simple content management system
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
<!DOCTYPE html><html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>Tiny wiki</title> </head> <body> <?php $content = ""; // We need to load the content! ?> <form action="tiny-wiki.php" method="post"> <input type="text" name="content" value="<?php echo $content; ?>" /> <input type="submit" value="Update" /> </form> </body></html>
Basic form
<?php
$content = load_content();
function load_content() { // Load content from the database return "";}
?>
Add a load function
<?php
$db = connect_to_database();$content = load_content($db);
function load_content($db) { // Load content from the database return "";}
function connect_to_database() { // Connect to the database}
?>
Add a database function
function connect_to_database() { $host = "127.0.0.1"; $port = 8889; $user = "root"; $pass = "root"; $name = "tinydb"; $dsn = "mysql:host=$host;port=$port;dbname=$name"; return new PDO($dsn, $user, $pass);}
Connecting to the database
function load_content($db) { $sql = "SELECT * FROM tinytable ORDER BY id DESC"; $query = $db->query($sql); $results = $query->fetchAll(); $row = $results[0]; return $row["content"];}
Querying the database
<?php
$db = connect_to_database();$content = load_content($db);
function load_content($db) { $sql = "SELECT * FROM tinytable ORDER BY id DESC"; $query = $db->query($sql); $results = $query->fetchAll(); $row = $results[0]; return $row['content'];}
function connect_to_database() { $host = "127.0.0.1"; $port = 8889; $user = "root"; $pass = "root"; $name = "tinydb"; $dsn = "mysql:host=$host;port=$port;dbname=$name"; return new PDO($dsn, $user, $pass);}
?><form action="tiny-wiki.php" method="post"> <input type="text" name="content" value="<?php echo $content; ?>" /> <input type="submit" value="Update" /></form>
tiny-wiki.php
Result
A simple content management system
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
<?php
$db = connect_to_database();$content = load_content($db);
if (!empty($_REQUEST["content"])) { save_content($db, $_REQUEST["content"]); $content = htmlentities($_REQUEST["content"]);}
?>
Core logic
function save_content($content) { $sql = "INSERT INTO tinytable (content) VALUES ('$content')"; $db->query($sql);}
Saving the content
Save the content
A simple content management system
1. Build a form for user input
2. Store submissions in a database
3. Retrieve submission data
Wait, this is bad
$content = "'); drop table tinytable; --";$sql = "INSERT INTO tinytable (content) VALUES ('$content')";
How does it work?
$content = "'); drop table tinytable; --";$sql = "INSERT INTO tinytable (content) VALUES ('$content')";
// Result: (-- is a comment in SQL)// "INSERT INTO tinytable (content)// VALUES (''); drop table tinytable; --')
How does it work?
SQL injection
• Another security vulnerability, similar to cross site scripting
• When user data is unintentionally executed as SQL
• Escaping works here also (also, prepared statements)
function save_content($db, $content) { $content = $db->quote($content); $sql = "INSERT INTO tinytable (content) VALUES ($content)"; // no more single quotes $db->query($sql, array($content));}
Escape the user input
Done!
• Download the files
• Try running the tiny wiki on your own local Apache/MySQL/PHP
• Get familiar with the PHP manual