Bugtraq mailing list archives

Adcycle 0.78b Authentication


From: Neil K <neilk () ALLDAS DE>
Date: Mon, 19 Feb 2001 12:04:44 -0000

|---------------------------------------------------------------------------------|
/    Product: Adcycle Banner Rotation.                                                                /
\    Vendor URL: www.adcycle.com                                                                   \
/    Tested on: v0.77 - 0.78b [Freeware] Linux                                                    /
\    Vendor Contact: Mailed on 15th January [i think]  Twice with NO reply         \
/    Other: Commericial version NOT tested                                                         /
\                                                                                                                       
  \
|-- First Off, ---------------------------------------------------------------------|
                    those who frequent www.alldas.de will know the general outlay
of the site (see credits), and possible the fact that we (don't)run this script. It
was an extreme bout of bordom and quite frankly moreover essential to check
this script since we (used to)run it. NEVER trust a script cos others use it anyway...

|-- The Problem, -----------------------------------------------------------------|
                    over the last few months a few ppl have come forward with posts
that demonstrate or exploit various vulnerabilities in Perl/PHP scripts use of SQL
based queries. Early this year some time in January when i looked at adcycle i
found many of these problems, but never really tried to exploit them probably
because i couldn't be arsed until now.....

-Overview,
                during the setup of adcycle using the ominous build.cgi, it creates several
tables by default these are:

mysql> show tables;
+-------------------+
| Tables_in_adcycle |
+-------------------+
| ad
| adconfig
| banners
| counter
| cp                           <= stores banner info etc.
| dailylog
| iplog
| login                       <= stores login info
| pools
| real_log
+-------------------+
10 rows in set (0.00 sec)

When a user logs into the script and authentication takes place successfully, their
data is entered into the login table:

$sth = $dbh->do("INSERT INTO login (remote,aid,pid,agent,stime,erase) VALUES ($log_list)");

the resulting table looks like this:

mysql> select * from login;
+-------------+-------+-----------+--------------------------------------+----------------------+
| remote          | aid       | pid            | agent                                                  | stime
+-------------+-------+-----------+-------------------------------------------------------------+
| 169.254.0.2 | ADMIN | 8983632| Mozilla/4.76 [en] (U; Linux 2.4 i686) | 2001-02-16 06:48:48|
| 169.254.0.2 | ADMIN |  816479 | Mozilla/4.76 [en] (U; Linux 2.4 i686) | 2001-02-16 06:48:47|
+-------------+-------+-----------+--------------------------------------+----------------------+
2 rows in set (0.00 sec)

-/Overview

Ok on with the problem, unfortunately there is no way to avoid the authentication
of the script, but i might be able to get around it :). Cutting the bull from the
*useful SQL queries in the script you will find:

AdLibrary.pm:
sub db_login() {
==>
        if($verify==0){
               $FOUND=0;
               $sth = $dbh->prepare("SELECT * FROM login WHERE remote='$remote' && agent='$agent' ORDER BY stime DESC");
               $sth->execute;
               while(@login = $sth->fetchrow_array){
                    if(length($login[1])>1){
                         $verify=1;
                         $whoami=$login[1];
                         $pid=$mixer;
                    }
               }
               $sth->finish();
          }
<==
}

Well as you can see this piece of code handles the fact that the user may have
already logged in using a valid username/passwd combination. And therefore
should not have to enter his/her username and password again to use the script.
Cos well that would be a total pain the arse wouldn' tit?. This clause is epecially
useful to us since we don't really know a valid user/pass combination.

Anyway whats interesting abt the above u might ask?? well the use of $agent in
the SQL query is most interesting since this data is user defined. Not *very easily
but it can be user defined given the right circumstances. Concidering that we now
literally 0wn that SQL query given a little thought we could easily get around the
authentication and do whatever we wanted :). How?? well by changing the agent
field of the http request to:

$agent = Mozilla' || aid='ADMIN

Thus changing the query to:

SELECT * FROM login WHERE (remote='127.0.0.1' && agent='Mozilla') || aid='ADMIN' ORDER BY stime DESC
                                                     ^                                                           ^      
           ^
                                                                brackets show 'logic bounds'                username 
wanted

As you can see executing that query would return all records with aid=ADMIN
very useful since from the original Perl code above would yeild $whoami=ADMIN.
Furthermore since the authentication routine is used in every call to the script
it is possible to execute any command that a normal ADMIN adcycle user would
be able to. Which is well... everything, changing banners, advertisers etc....

Of course as you've probably guessed by now, this example assumes that the admin
user is actually 'admin' as it is by default. And also the presence of a record with
aid='ADMIN' which unfortunately can only be present if the admin is either currently
logged in or has been logged in and not logged out. This is not that hard actually if
you've used this script seriously you'd know this to be true. I myself have never
logged out of a hotmail account let alone clicked the word 'logout' written in size 6-8
miniature text at the bottom of a browser.

--As an after thought, requesting:
http://www.server.com/cgi-bin/adcycle/adcenter.cgi?task=purge_log&who=user

will result in the login table having all contents with aid=user deleted from it, therefore
logging that user out of the script requiring them to log back in. Could be useful maybe?

If anyone comes up with a more efficient way to subvert authentication on this script
then mail me :),
/--

|-- Exploit, -----------------------------------------------------------------------|
                to better demostrate this problem i have included a small perl script sploit
that will alter banner images, some alteration maybe needed for it to werk but hey it
worked for me?!?.

|-- Solution, ----------------------------------------------------------------------|
                well considering that i have yet to get a response from adcycle after 4
weeks?, says quite alot if you ask me. Possible because this script is freeware it ain't
supported?. Well to say the least that sux real hard in my mind...

Anyways how to patch?? well you could parse out the following character from *all
the user defined fields: '.

Here are the alterations to the script:

AdLibrary.pm:
sub db_login    {
=>
    my $agent=$env->get_agent;

+    while($agent =~ s/'// !=0 ){}

    my $cookie=$env->get_cookie;
    my $datestamp=$env->get_datestamp;
    my $admin_user_name=$config->get_admin_user_name;

=>
    if($verify==0){
    my($trash,$mycookname,$mycookpid)=split(/\!\!/,$cookie);

+    while($mycookpid =~ s/'// !=0 ){}

=>
    $FOUND=0;
    $sth = $dbh->prepare("SELECT * FROM login WHERE pid='$mycookpid' && agent='$agent' ORDER BY stime DESC");
    $sth->execute;
        while(@login = $sth->fetchrow_array){
            if(length($login[1])>1){
                $verify=1;
                $whoami=$login[1];
                $pid=$mycookpid;
            }
        }
        $sth->finish();
    }
<=
}

Pls note this is a Hotfix and your script should be updated when (if) adcycle update
theirs.

|-- Credits, -----------------------------------------------------------------------|

        domz    -    designed and created alldas.de has mad html+PHP+infinitum
                          skillz. In process of coding a *new* banner rotation script....
        mjm     -    @gmc-online.de, long time no speak.
        Jochen Wiedmann    -  joe () ispsoft de for not allowing multiple queries
                                           on a single line, the TRUE saviour of all PHP and
                                           Perl programmers who write scripts that use MySQL.
        m8's @ werk where i finally quit after 3.5 years :-).
        all @ alldas.de, there sooo many i can't list them here!

       Thanks to rfp for a most *interesting* article abt PHP-Nuke which prompted
       me to get off me arse and write this :-).
______________________________________________________________

NeilK (neil () alldas de/neilk () alldas de)
www.alldas.de

             "I'm always Frank and Ernest with the ladies,
                    Frank in New York, Ernest in Boston"
                                --quoted from some film i watched last night

Attachment: exploit.pl
Description:


Current thread: