Diving into php

Post on 21-May-2015

7.941 views 8 download

Tags:

description

Course lecture for Fast, Easy, Complicated, and Powerful Webhttp://fecpw.phiffer.org/

Transcript of Diving into php

Diving into PHPFast, Easy, Complicated, and Powerful Web

ITP, Spring 2011, section 1, session 1Dan Phiffer dan@phiffer.org

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

<?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 &quot; $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 -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