=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
=-=-=-=-=- New Benchmark alternative or effective blind SQL-injection =-=-=-=-=-=-
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
Title: New Benchmark alternative or effective blind SQL-injection
Author: Elekt
Translate: NeMiNeM
Website: www.antichat.ru
Email: elektronic@antichat.ru
IRC: irc.antichat.ru:7771 #antichat
Original article: http://forum.antichat.ru/thread35207.html
Translate article: http://forum.antichat.ru/thread37726.html
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
In this article we describe a new and universal way to work without
benchmark in blind sql-inj in so-called "unusable" bugged queries like
UPDATE, DELETE, REPLACE, UPDATE etc.
Using this new alternative method we can exactly get required
information from database, not just simply modify entries.
Here we describe all features of well-known methods of sql-inj attacks,
which are used towards above-mentioned operators.
We'll also more comprehensively study the aspects of practical usage of
BENCHMARK during exploits writing.
Note: we provide examples for mysql in this article, however the
description will practically work on all databases (considering the
queries syntax of course).
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
-[1]- INTRO =-=-=-=-=-=-=-=-==-=-=-=-=-=-
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
Programmers become cleverer, there are less and less bugs in
select-queries, but the problem of injections in
INSERT,UPDATE,REPLACE,DELETE and others remains important.
I often see such questions in the forums: "...please, help what to do if
I see - 'mysql error INSERT INTO table_name VALUES(...'" When a newbie
sees such an error he'll probably close his browser and the amateur will
post the same 100th question in the forums. He won't probably receive an
answer or the answers will be too difficult for him, because the
promotion of blind sql, considering the ammount of queries, demands the
implementation of automatization, i.e. the ability to write exploits.
The methods have been known long ago and described in details by
1dt.w0lf. on November 14, 2004 and only lazy-bones didn't read it -
http://www.securitylab.ru/contest/212099.php Our article can be a
continuation to it.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
-[2]- INSERT and others =-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
(known attacks on instert/update etc are described, it can be omitted if you know this)
What's the benefit?
-[A]-
(general case)Data modification without a possibility to watch results
Ideal case - sql-inj in table name. Here is possible everything:
Êîä:
INSERT INTO [SQL] VALUES ('stat','stat2');
New user adding:
INSERT INTO [mysql.user (user, host, password) VALUES ('newadmin', 'localhost', PASSWORD('passwd'))/*] VALUES ('stat');
-[B]-
DoS-attack
But similar sql-injections exist in most cases in column name and it
doesn't allow us to change the upgradable table to the one we need.
INSERT INTO table VALUES ('stat','[SQL]');
So besides database breaking\littering\dos we won't get anything with data modifying.
SQL:
INSERT INTO table VALUES ('stat','bla['),('test', 'demo]');
DoS:
INSERT INTO table VALUES ('stat','bla[' and BENCHMARK(10000000,BENCHMARK(10000000,md5(now()))) ) /*]');
-[C]-
Queries separating in MSSQL, PostgreSql, Oracle
But what does combine these three popular DBMS?
Such wonderful thing as queries separating support, using semicolon, carriage return etc.
Thus we can add absolutely ANY sql-query, using ";","%0A","%0D" to separate it from the main.
What useful can we add? - Search in google for concrete db.
-[D]-
Data modification with a possibility to watch results.
It's not important here where the injection is - in table or in column
name. We can see the result of query, though marginally. So it's not a
problem to make an attack - purely technical details of result
clarification. Example: let web-application OPENLY conduct the
attendance statistics and there is a vulnerability in a column with
User-Agent. Then, the result of sql-inj realization will be the
attendance statistics output on a page.
-[E]-
BENCHMARK use
We use BENCHMARK, which helps us to determine the result of query
execution depending on the server response time. This query will be
positive for if and server response will come at once.
INSERT INTO table VALUES ('stat','1' and 1=if(ascii(lower(substring((select users from mysql.user limit 1),1,1)))>=1,1,benchmark(999999,md5(now()))) )/* ,'stat2');
And this one is negative and a lot of time will pass for BENCHMARK execution, thus we'll not get the server's response at once:
INSERT INTO table VALUES ('stat','1' and 1=if(ascii(lower(substring((select users from mysql.user limit 1),1,1)))>=254,1,benchmark(999999,md5(now()))) )/* ,'stat2');
It's obvious that instead of INSERT we can put any other operator,
including SELECT, because there are also some complicated cases of
injections in it.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
-[3]- Bencmark for hackers =-=-=-=-=-=-=-
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
(benchmark operation features, it can be omitted if you know this)
The use of BENCHMARK is like a moving to another dimension. From
received information difference measuring to the measuring of query
execution time difference.
If anyone has any doubts if exploits for BENCHMARK are written, please,
look through the bugtraqs and make sure in the opposite - there are some
exploits really.
BENCHMARK exploits realization is more complicated than simple
character-oriented bruteforce.
Benchmark features:
-[A]- perhaps the most important detail is that benchmark creates a
serious load on server's processor. And this load lasts during the whole
time of exploit working. The administator may not look through the
access\error logs, but he could be quite interested why the server is
lagging and in top->P "mysqld" takes the first place...
-[B]- action period of exploit is bigger depending on the record length
we want to get. (more length = more action period) In my practice I
needed more than an hour for 32-symbols hash searching. Sometimes more
hours - it depends, the conditions are listed below.
-[C]- A hacker and a server will need a wide and reliable channel. These
things are important for bruteforcing quality and stability. I don't say
that everything will fail if you use dial-up connection, but there will
be much more lags, especially if you decide to save time and choose too
small parameter.
-[D]- performance measurement parameter, i.e. the ammount of iterations,
in our example - 999999 benchmark(999999,md5(user()) From my first-hand
experience, since 1dt.w0lf''s article this number has changed together
with the growth of performance of modern servers. It's recommended to
make self-tuning of this parameter for universality, trying to get the
acceptable response time.
-[E]- and accordingly, having found the number in benchmark we must set
the response timeout. This will be arithmetic mean value from the time
of true\false execution query.
-[F]- Note: while making an exploit take into account that according to
the statistics the number of false queries is bigger than a number of
true, that means you should set benchmark delay in the way it works when
the response is correct. This way: if( ?, true, false ) 1 = if( 1=1 ,
benchmark(999999,md5(user()), 1 )
Thus we save our time and reduce the load on the server.
Don't forget that server needs rest after each benchmark, to recover so
to say. Otherwise the next query may have an unexpectable execution time
and will give us wrong data. Many people forget about this small detail,
because they either test locally or don't think at all, releasing their
code without former testing. I was really surprised and didn't know why
during the bruteforce the first symbol was correct, but then I got
garbage - the server was just overload with benchmark. It's recommended
to set the delay time 1-1,5 more than benchmark execution time. Yes, it
will essentially slow down bruteforce but the effect will be better.
If we look at the code we can easily modify 1dt.w0lf's
character-oriented bruteforcer, taking into account benchmark. We need..
-[A]-
change sql according to benchmark
$http_query = $path."?Cat=&page=1&like=".$username."' AND 1=if(ascii(substring(CONCAT(U_LoginName,CHAR(58),U _Password),".$s_num.",1))".$ccheck.",benchmark(999999,md5(user()),1)/*";
-[B]-
timeout
But sub check($) should return the result depending on whether the server has given the response in time or not.
Êîä:
$mcb_reguest = LWP::UserAgent->new(timeout=>$timeout) or die;
-[C]-
sleep()
After each false query let's give N seconds rest to the server. Let it recover.
That's it.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
-[4]- Benchmark alternative -=-=-=-=-=-=-
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
Here is, in fact, the most delicious thing!
Dealing with benchmark I wished to find a substitution to this
troublemaking, but the only method. And I've found it!
Actually the difference of output data and time aren't the only factors.
Let's look at the beginning again and remember how each sql-inj starts.
Certainly from the quotation mark in request! ... and error message of
course. But let's think logically - we put quotation mark, mysql checks
our query, finds a mistake in it and tells us.
Follow my thought: mysql first checks if it's correct, then either makes
a query and shows a result or an error message.
And now let's think if there is another way. Certainly, maybe that's
just the point. There may be such case when the query will successfully
pass verification, execute,.. but in result we'll get an error message.
So our task is simply to PROVOKE such query + we should join parameteres
in our request in the way we are be able to manipulate with a result of
query and get a useful data.
Here is a task: Query failure frustration and as a result - intentional
error call which will help to distinguish true\false query.
I realized it and began to remember different db errors.
First, I tried to wreck the request with a help of IF, trying to put
false table\column\datatype names:
select if(1=1,null,blaaaah);
But damn mysql is clever and checks datatype before execution. So it has
failed. "You have an error in your SQL syntax"
An attempt to change not column but table didn't work out as well.
select null from if(1=1,users,blaaaah);
By the way, the algorithm of query parsing in mysql is probably
expecting the name of a table to be a constant and here it's obviously
not a constant. It checks the existance of a column in already known
table and if the table is not defined, e.g. I specify it through if,
mysql will just send me away.
I didn't check verification principle in other databases, so maybe such
simple but universal tricks will work out there.
What other mistakes can occur during the query execution? The most
popular after "You have an error in your SQL syntax" is perhaps "The
used SELECT statements have a different number of columns". But here
verification also passes before executing.
"Operand should contain 1 column(s)" - fails because of the same reason.
"warning: mysql_fetch_array..." - it may be, but php-error is specific
according to the engine.
.. the next thing in my errors' chart is "Subquery returns more than 1
row"... Yes yes, that ubiquitous limit!
Here is what we need! MySQL checks data correctness, but can't check the
number of returned responses, haven't made a response itself.
The question is how to formulate a query to be sure to get such error?
You'll need to provoke two conditions: when you are 100% sure that
you'll get an error and 100% sure that there won't be any errors.
Let's say we know beforehand table and column names in vulnerable
application. Let the password hash with md5. Then the length of any
password = 32 symbols. ID and login length will probably be shorter,
won't it? length(id)=(1-5..) and length(password)=(32) Then our exploit
will be like this:
false:
...123' and 1=(select null from users where length(if(ascii(substring((select password from users where uid=1),1,1))>254,password,uid))>5)/*
First password symbol is probably smaller than ascii(254).. It means if
will return length(id)>5 and so there are not so many users (though we
can set a bigger number), SELECT will return NULL. In the result we
won't see anything as if there is no injection at all.
true:
...123' and 1=(select null from users where length(if(ascii(substring((select password from users where uid=1),1,1))>1,password,uid))>5)/*
As a first password symbol is probably bigger than ascii(1), the condition is true.
So if will return length(password)>5 which will cause the N results output in SELECT query.
But in condition only one result 1=(*) can be compared... which will provoke "Subquery returns more than 1 row" !!!
It's so simple, isn't it? =)
I'm sure that more similar mistakes, shown right after query execution,
can be found.
"more than 1 row" features:
1) the main: the standard speed of characters bruteforce with a full
benchmark substitution, time saved and no server load.
2) At the cost of this performance - a lot of errors in mysql logs,
which can attract administrator's attention.
3)The only thing you should know is some data, like table and column
names in order to provoke "more than 1 row" error.
Maybe you'll find more perfect and universal way than mine! Good luck!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-
-[5]- UNIVERSAL "more than 1 row" EXPLOIT -=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-
My friend podkashey proposed universal version exploits:
EXPLOIT:
true: 1=if(ascii(substring((select users from mysql.user limit 1),1,1))>1,1,(select 1 union select 5))
false: 1=if(ascii(substring((select users from mysql.user limit 1),1,1))>254,1,(select 1 union select 5))
Match: "Subquery returns more than 1 row"
INSERT INTO table VALUES ('stat','bla[' and 1=if(ascii(substring((select users from mysql.user limit 1),1,1))>1,1,(select 1 union select 5)) ) /*]');
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-[6]- Mybb <= 1.2.2 (CLIENT_IP) Remote SQL Injecton Exploit EXPLOIT -=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Date: 23.01.2007
backup: http://www.milw0rm.com/exploits/3719
Enjoy!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
-[the end]=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
Translation by NeMiNeM -
Please, feel free to show and correct my mistakes in the translation. No flame please.
Thank you.
(c) for www.antichat.ru
=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-
# milw0rm.com [2007-04-12]