频道栏目
首页 > 资讯 > 网站安全 > 正文

国外的MYSQL注入教程

04-11-15        来源:[db:作者]  
收藏   我要投稿

(来自Projectmoose第4月杂志)
[] - [ 1 - Simple SQL Security by Netjester. ] - []

Contact: netjester@zoite.net / irc.zoite.net

I dont know about you, oh most knowledgable of SQL users, but when I learnt how to build a database driven website from various tutorials around the Internet, I never came across the phrase "SQL Injection"... in fact, I never came across any SQL security concepts at all. The purpose of this article is to inform the SQL programmer of the dangers of SQL injection, and ways to potentially minimize the severity of any exploits in your code.

All the examples in this article are going to be using PHP. The reason for this choice is that PHP seems to be the server-side solution of choice - its free and powerful. Im also using MySQL, as its all Ive ever used. I think all the examples here should be applicable across different database servers, but I have mentioned the particular database servers affected where necessary. I assume knowledge of PHP database functions

To start with, Ill create a database and a couple of tables, so I can demonstrate how a certain security risk could be exploited, and to what means. Rather than make a graphical representation of these tables, Ill write it in insertion SQL statements, so you can stick them on your own server and test it yourself. After all, the best way to learn is to get stuck in.

######################
# Database structure #
######################
CREATE DATABASE sqlsecdemo;

CREATE TABLE Users (INT UserID NOT NULL AUTO_INCREMENT PRIMARY KEY, TEXT Username NOT NULL, TEXT Password NOT NULL);
INSERT INTO Users SET Username="netjester", Password="blahblah123";
INSERT INTO Users SET Username="someoneelse", Password="letmein";
INSERT INTO Users SET Username="MrsThePlague", Password="God";

CREATE TABLE Messages (INT MessageID NOT NULL AUTO_INCREMENT PRIMARY KEY, INT RelUserID NOT NULL, TEXT Message);
INSERT INTO Messages SET RelUserID=1, Message="Hi everybody.";
INSERT INTO Messages SET RelUserID=2, Message="What account number shall I have this large amount of money sent to?";
INSERT INTO Messages SET RelUserID=3, Message="B825KM32-F please ";

CREATE TABLE SomeMoreInfo (INT InfoID NOT NULL AUTO_INCREMENT PRIMARY KEY, TEXT Info);
INSERT INTO SomeMoreInfo SET Info="Some info here";
INSERT INTO SomeMoreInfo SET Info="Even more information.";
INSERT INTO SomeMoreInfo SET Info="Information overload.";


Now we have this foundation, I can start off by showing you the most basic of attacks. Consider this PHP statement:


$result=pg_query($db,"SELECT Message FROM Messages WHERE RelUserID=".$_GET[uid]." ORDER BY MessageID");


This may appear in a script that displays all messages posted by a certain user, reached from a page with a list of users to choose from. The URL for a page which displays all of someoneelses posted messages would be something like sqlinjection.com/postedby.php?uid=2 so the full SQL statement" target=http://www.sqlinjection.com/postedby.php?uid=2 so the full SQL statement, with substituted variables would be:


SELECT Message FROM Messages WHERE RelUserID=2 ORDER BY MessageID


Now consider this URL: sqlinjection.com/postedb...20Messages%20--" target=http://www.sqlinjection.com/postedb...20Messages%20--

If you were to replace the %20s with spaces, as %20 is simply a URL-encoded space, you would see that the SQL statement sent to the server now reads like this:

SELECT Message FROM Messages WHERE RelUserID=2; DELETE * FROM Messages -- ORDER BY MessageID

The semicolon ends the first SQL statement, and the server is now ready for another... which we provide. The -- is the SQL comment syntax - all text following that will be ignored by the server. This would be included by an attacker in case there are more search clauses or ordering directives and such following "WHERE RelUserID=2", which there are. If it was left out, the attackers injected SQL statement would probably be invalid.

MySQL is not vulnerable to this attack, as it only allows 1 statement per query, for exactly this reason. PostgreSQL is vulnerable however, and probably others too, as they allow multiple SQL statements per query.

Protecting against this type of attack is fairly simple, and can be done in two ways. Ideally, both ways should be implemented. The first step is to add quote marks around the user-defined variable being comapared to RelUserID, like this:

$result=pg_query($db,"SELECT Message FROM Messages WHERE RelUserID=".$_GET[uid]." ORDER BY MessageID");

So, when our attacker tries the URL above, the SQL statements becomes:

SELECT Message FROM Messages WHERE RelUserID=2; DELETE * FROM Messages -- ORDER BY MessageID

The result of this is to put all the users input into a string, which will then be compared against RelUserID. However, an attacker still has a way around this. Consider the effect of an attacker simply adding a to his input, thus unquoting the string, and then again we are at his or her mercy. This is quote possible:

sqlinjection.com/postedby.php?uid=2;%20DELETE%20" target=http://www.sqlinjection.com/postedby.php?uid=2;%20DELETE%20*%20FROM%20Messages%20--

Our SQL statement then becomes:

SELECT Message FROM Messages WHERE RelUserID=2; DELETE * FROM Messages -- ORDER BY MessageID

So it looks like weve made absolutely no progress at all. They key is to add backslashes to the users input before each occcurrence of or ". This way, a user can no longer open or close a string. With this implemented, the above URL generates the SQL statement below:

SELECT Message FROM Messages WHERE RelUserID=2; DELETE * FROM Messages -- ORDER BY MessageID

Because of the escaping of the quote, the string compared to the RelUserID is now "2; DELETE * FROM Messages --", and the attack is now neutralised once again.

Another precaution that can be taken against this kind of attack is simple data validation. As RelUserID is defined in the database as being an INT, comparing text to it seems illogical. So first of all, check that the value of $_GET[uid] is in fact a number, and doesnt contain anything except digits. If it does, you can promptly stop execution and inform the user he or she is trying to do things that perhaps they shouldnt be doing. Heres a PHP function which will help you do that, and the way Id implement it in the above example.


function nj_isInteger($checkString) {
if($checkString!= && ereg("^[0-9]*$",$checkString)) {
return true;
} else {
return false;
}
}

if(!nj_isInteger($_GET[uid]))
exit(User inputted UID was not an integer.);


So there we have a good basis for some slightly more advanced SQL injection attacks.

Now, imagine you wanted a page to select and display everything from a particular table. Which table it is the user decides. So it might look like this:

mysql_query($db,"SELECT * FROM ".$_GET[table]);

Here, injection can be achieved in much the same way. If the user gave the script the value "users WHERE Username=netjester", they would be presented with my password. Which is bad.

The way to protect against injection further than the table to select from, you again, add quotes around the value youre adding, and escape all quotes input by the user.

However, an important lesson is to be learnt here. If you wish to give a user a choice such as which table will be queried, decide which tables you want to allow the user to access, and then, for example, put them in a PHP array, and use the particular array element required using a number provided by the user. That way, a user can only indirectly insert those table names you specify in the

相关TAG标签
上一篇:PHP注射一路小跑..
下一篇:老婆上网手册
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站