adding breakthenet xss web vulnerability -- Now registers the mysql db + allows www-data to connect with password 'example', change this! register.php claims that registration was successful but logging in does not work... investigate further.

This commit is contained in:
thomashaw
2017-03-30 11:21:33 +01:00
parent 9f41e42381
commit fa10962295
20 changed files with 428 additions and 0 deletions

View File

@@ -0,0 +1 @@
require btn_xss_challenge

View File

@@ -0,0 +1,13 @@
# XSS Cookie Stealing Challenge
Challenge: See if you can become logged in as the "admin" user.
Note that to do so, you'll need to create your own account and create an XSS attack on your user profile.
For purposes of this challenge, anything you successfully "alert()" in the admin's browser will be passed along to you. (Admin browser is simulated using phantomjs)
Deploy to your own Heroku instance with this button below, or try out our live demo [HERE](https://ctf-xss-challenge.herokuapp.com/) (not guaranteed to be up).
[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)
Note that useful information for testing and debugging will be logged to the Papertrail app in your heroku instance. Open papertrail to view those streaming logs.

View File

@@ -0,0 +1,21 @@
{
"env": {
"CTF_FLAG": "PUT-FLAG-HERE"
},
"addons": [
"papertrail",
"cleardb"
],
"success_url": "/index.php",
"scripts": {
"postdeploy": "php setup_mysql.php"
},
"buildpacks": [
{
"url": "https://github.com/heroku/heroku-buildpack-php"
},
{
"url": "https://github.com/stomita/heroku-buildpack-phantomjs"
}
]
}

View File

@@ -0,0 +1,19 @@
<?php
session_start();
include "mysql.php";
$username = mysql_real_escape_string($_POST['username']);
$password = md5($_POST['password']);
$uq = mysql_query("SELECT `id`, `password` FROM `users` WHERE `username` = '$username' AND `password` = '$password'", $c);
if (mysql_num_rows($uq) == 0)
{
die("Invalid username or password!<br /><a href='login.php'>&gt; Back</a>");
}
else
{
$mem = mysql_fetch_assoc($uq);
$_SESSION['id'] = $mem['id'];
setcookie("hint", 'use-these-cookies-to-login-as-admin', time()+36000);
header("Location: /index.php");
exit;
}

View File

@@ -0,0 +1,6 @@
{
"require": {
"ext-mysql": "*",
"ext-mbstring":"*"
}
}

View File

@@ -0,0 +1,21 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "4032f9a7678ad10ae1a13e7369f85d34",
"content-hash": "a243a4e7654fee2a753e9fd9e0f4aec1",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"ext-mysql": "*",
"ext-mbstring": "*"
},
"platform-dev": []
}

View File

@@ -0,0 +1,8 @@
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`profile_desc` longtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

View File

@@ -0,0 +1,41 @@
// Locally: phantomjs fake_admin_browser.js --url test.com
// Heroku: /app/vendor/phantomjs/bin/phantomjs fake_admin_browser.js --url test.com
var system = require('system');
var base_url = "http://localhost:8888/";
var password = "";
var profileid = 0;
if (system.args.length === 1) {
console.log('Try to pass some args when invoking this script!');
} else {
system.args.forEach(function (arg, i) {
if (i == 2) {
base_url = arg;
}
if (i == 4) {
password = arg;
}
if (i == 6) {
profileid = arg;
}
});
}
function open_target_profile(profileid) {
var userprofilepage = require('webpage').create();
userprofilepage.onAlert = function(alertmsg) {
console.log(alertmsg);
}
userprofilepage.open(base_url+"index.php?id="+profileid, function (status) {
setTimeout(function(){
phantom.exit(0);
}, 3000);
});
}
var loginpage = require('webpage').create();
loginpage.open(base_url+'authenticate.php', 'post', 'username=admin&password='+password+'&save=OFF', function (status) {
open_target_profile(profileid);
});

View File

@@ -0,0 +1,82 @@
<?php
session_start();
$id = $_SESSION['id'];
if (!$id) {
header("Location: login.php");
exit;
}
header('X-XSS-Protection: 0');
include "mysql.php";
if($_POST['profile_desc']) {
$profile_desc = mysql_real_escape_string($_POST['profile_desc']);
mysql_query("UPDATE users SET profile_desc='$profile_desc' WHERE id=$id");
}
if($_GET['id'] && $id == 1) {
//Admin uses this to browse to other people's profiles.
$id = $_GET['id'];
}
$is = mysql_query("SELECT * FROM users WHERE id='{$id}'") or die(mysql_error());
$ir = mysql_fetch_array($is);
?>
<style>
textarea {
width: 300px;
height: 150px;
}
</style>
<table border=0>
<tr><td>
<fieldset>
<legend><select disabled='disabled' alt='Only admins can view all players profiles'>
<option><?=$ir['username']?></option>
</select>'s Profile</legend>
<?=$ir['profile_desc']?>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<hr>
<?
if($ir['id'] == 1) {
$ctf_flag = getenv('CTF_FLAG');
print "<font color='green'>CTF Flag: ".$ctf_flag."</font>";
}
else {
print "<font color='red'>CTF Flag: [disabled] - Must be logged in as admin to access.</font>";
}
?>
</fieldset>
</td><td>
<fieldset>
<legend>Update your Profile Description</legend>
<form action="index.php" method="post" name="login" id="login">
Current Value: <br>
<textarea id="profile_desc" name="profile_desc" rows=5 cols=10 /><?=$ir['profile_desc']?></textarea><br>
<input type="submit" value="Submit" />
</form>
</fieldset>
<br><br><br>
<script>
function trigger_admin() {
window.open('trigger_fake_admin.php?id='+<?=$id?>, 'Admin Simulation', 'status=1, height=485, width=420, left=100, top=100, resizable=0');
}
</script>
<button onclick="trigger_admin()">Lay trap for admin to visit your profile...</button>
<br><br><br>
&gt; <a href='logout.php'>LOGOUT</a>
</td></tr>
</table>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>BreakTheNet</title>
</head>
<body bgcolor="#C3C3C3">
<h3>
&gt; BreakTheNet Log-In
</h3>
<table width="80%">
<tr>
<td width="50%">
<fieldset>
<legend>About BreakTheNet</legend>
An XSS challenge - see if you can become logged in as the "admin" user.<br><br>
Note that to do so, you'll need to create your own account and create an XSS attack on your user profile.<br><br>
For purposes of this challenge, anything you successfully "alert()" in the admin's browser will be passed along to you.<br><br>
Feel free to review the source code as part of the challenge <a href='https://github.com/breakthenet/CTF-XSS-Challenge'>here</a>.
</fieldset>
</td>
<td>
<fieldset>
<legend>Login</legend>
<form action="authenticate.php" method="post" name="login" id="login">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="Submit" />
</form>
</fieldset>
</td>
</tr>
</table><br />
<h3>
<a href='register.php'>REGISTER NOW!</a>
</h3><br />
</body>
</html>

View File

@@ -0,0 +1,5 @@
<?php
session_start();
session_unset();
session_destroy();
header("Location: login.php");

View File

@@ -0,0 +1,7 @@
<?php
$mysql_string = getenv('CLEARDB_DATABASE_URL');
$mysql_url = parse_url($mysql_string);
$c = mysql_connect($mysql_url['host'], $mysql_url['user'], 'example') or die(mysql_error());
$db_name = str_replace("/", "", $mysql_url['path']);
mysql_select_db($db_name, $c);

View File

@@ -0,0 +1,46 @@
<?php
session_start();
require "mysql.php";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>breakthenet</title>
</head>
<body bgcolor="#C3C3C3">
<?
if ($_POST['username'])
{
$username = mysql_real_escape_string($_POST['username']);
$q = mysql_query("SELECT * FROM users WHERE username='$username'");
if (mysql_num_rows($q))
{
print "Username already in use. Choose another.";
}
else
{
mysql_query("INSERT INTO users (username, password) VALUES( '{$username}', md5('{$_POST['password']}'))");
print "You have signed up, enjoy the game.<br />&gt; <a href='login.php'>Login</a>";
}
}
else
{
?>
<h3>
Register
</h3>
<form action="register.php" method="post">
Username: <input type="text" name="username" maxlength="20" /><br />
<!-- Username max length of 20 enforced at the database level. Not sure if it actually throws an error though, so stop them on frontend. -->
Password: <input type="password" name="password" /><br />
<input type="submit" value="Submit" />
</form><br />
&gt; <a href='login.php'>Go Back</a>
<?
}
?>
</body>
</html>

View File

@@ -0,0 +1,34 @@
<?php
session_start();
include "mysql.php";
$is = mysql_query("SELECT * FROM users", $c) or die(set_mysql());
function set_mysql() {
//Only executed if table does not exist
$c = mysql_connect($db_hostname, $db_username, 'example');
mysql_select_db($db_database, $c);
$e_db_hostname = addslashes($db_hostname);
$e_db_username = addslashes($db_username);
$e_db_password = addslashes('example');
$e_db_database = addslashes($db_database);
$fo = fopen("dbdata.sql", "r");
$query = '';
$lines = explode("\n", fread($fo, 1024768));
fclose($fo);
foreach ($lines as $line)
{
if (!(strpos($line, "--") === 0) && trim($line) != '')
{
$query .= $line;
if (!(strpos($line, ";") === FALSE))
{
mysql_query($query);
$query = '';
}
}
}
$adminpassword = md5(getenv('CTF_FLAG'));
mysql_query("INSERT INTO `users` VALUES (1,'admin','{$adminpassword}', '')");
}

View File

@@ -0,0 +1,6 @@
The trap is laid! Waiting for an admin to visit your profile...
<br><br>
<script>
window.location.href="trigger_fake_admin_2.php?id=<?=$_GET['id']?>";
</script>

View File

@@ -0,0 +1,10 @@
<?php
$base_url = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}/";
$results = shell_exec('phantomjs fake_admin_browser.js --url '.$base_url.' --password '.getenv('CTF_FLAG').' --profileid '.$_GET['id']);
print "<br><br>";
print "We caught an admin! Our XSS caught this information via alert():";
print "<hr>";
print nl2br($results);
print "<hr>";

View File

@@ -0,0 +1,13 @@
class btn_xss_challenge::configure {
$json_inputs = base64('decode', $::base64_inputs)
$secgen_parameters = parsejson($json_inputs)
# Create www-data user in mysql
::mysql::db { 'mydb':
user => 'www-data',
password => 'example',
host => 'localhost',
grant => ['SELECT', 'UPDATE'],
}
}

View File

@@ -0,0 +1,4 @@
class btn_xss_challenge{
require btn_xss_challenge::install
require btn_xss_challenge::configure
}

View File

@@ -0,0 +1,14 @@
class btn_xss_challenge::install {
Exec { path => ['/bin', '/usr/bin', '/usr/local/bin', '/sbin', '/usr/sbin'] }
package { ['php5','php5-mysql']:
ensure => installed,
}
file { 'btn_xss-copy_files':
path => '/var/www/challenge_dir',
source => "puppet:///modules/btn_xss_challenge",
recurse => true,
}
}

View File

@@ -0,0 +1,39 @@
<?xml version="1.0"?>
<vulnerability xmlns="http://www.github/cliffe/SecGen/vulnerability"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/vulnerability">
<name>XSS Cookie Stealing Challenge</name>
<author>emeth-</author>
<author>Thomas Shaw</author>
<module_license>MIT</module_license>
<description>BreakTheNet - XSS Cookie Stealing Challenge. Try become the 'admin' user.For purposes of this challenge,
anything you successfully "alert()" in the admin's browser will be passed along to you. (Admin browser is simulated
using phantomjs).
</description>
<type>webapp</type>
<type>xss_challenge</type>
<privilege>none</privilege>
<access>remote</access>
<platform>linux</platform>
<read_fact>strings_to_leak</read_fact>
<!--ctf flag-->
<default_input into="strings_to_leak">
<generator type="message_generator"/>
</default_input>
<!--optional hints-->
<hint>Create your own account and perform an XSS attack on your own user profile.</hint>
<conflict>
<type>webapp</type>
</conflict>
<requires>
<module_path>modules/services/unix/http/lamp</module_path>
</requires>
</vulnerability>