开发者

Is a SQL Injection possible in this code?

Introduction

I have taken over maintenance of a really messy PHP page, which is a booking platform for holiday apartments, but this isn't important. The code was originally done by a designer (not a coder) and it's really bad. Passing boolean variables by "true" and "false" strings is one of the minor WTFs. I want to convi开发者_StackOverflow社区nce the owner of the page, to give me the time (and money, of course) to clean it up the code (or rewrite it).

Apparently original "developer" had never heard of SQL-injection because he's using POST and GET variables directly in his SQL statements. To convince the owner I want to shock him a littel by logging in as admin without using his password.

tl;dr (or: The actual question)

This statement (where $p_username is a POST variable which contains the content of the "Username" input field):

"SELECT password FROM user WHERE username = '$p_username'"

The returned string (which is an unsalted MD5-Hash of the password that was stored in the database) is then compared against the (also hashed) string which was entered into the "Password" field and if both strings match the user is logged in as the entered user. Is it possible to put something into the username field to log in as "fake" admin?

Note: DB Server is MySQL, PHP is in Version 5 and magic_quotes is enabled.


As noted by Col. Shrapnel, magic_quotes does make it impossible, unless you are running under some very special circumstances.

However, if what you say is true, it's quite likely that the original developer didn't know much about magic_quotes, so it's likely he messed up if he ever stored the GET/POST/COOKIE values anywhere else except SQL statements. In short, look for places where ' and " would be legal, and check if they don't get messed up.

Also - did he know about htmlspecialchars(), or is HTML/Javascript injection still possible? :)


With magic quotes enabled it would be impossible.


If that is the full query and the password check is done on the PHP side, you won't be able to login as admin (even if magic_quotes is turned off), because you would still have to match the password hash.


As others have noted, getting the single quote past magic quotes is tricky, but if it could be done, the query is toast. Consider if we could inject the following:

SELECT password FROM user WHERE username = 'unlikely' 
UNION ALL SELECT CHAR(102,111,111); #'

This will return the string 'foo' to PHP as the password, so all we need to do is ensure our form sends our injection for $username, and 'foo' for the $password.


EDIT

There are multiple attack vectors with addslashes(). The first one I chose below was based on the article previously linked in an answer that quoted it to support the opposite claim. At least another one is with overlong strings using no less than the UTF-8 encoding.

http://www.erich-kachel.de/?tag=addslashes

A similar technique as the below could be constructed. The long and short is, the MySQL team has seen fit to retire magic_quotes and also strongly advised against pretending addslashes() is a real form of protection. Maybe, you know, the MySQL team would know better? For what its worth, mysql_real_escape_string has some edge case vulnerabilities as well, but since it is MySQL-specific instead of just PHP-specific, it does go one step further. A better solution would be to use query parameters.

Original answer follows

Yes it is possible to log in as admin. Not in one go, but two passes will do it.

Ref - http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string (Yes this is the same link from another answer, but instead, my interpretation is that it IS commonly possible on any multibyte character set except utf8)

You have not stated if you system is multi-byte, but since the question is open, I will assume it is.

$p_username = chr(0xbf) . chr(0x27) . ';' .
    "update user set password='password', '.
    "username='" . chr(0xbf) . "' where username='admin' /*';

"SELECT password FROM user WHERE username = '$p_username'"

I have changed the user name AND password of the "admin" user

This type of attack is possible with any character encoding where there is a valid multi-byte character that ends in 0x5c


I think It's important to validate all input variables and escape all special characters, even if magic_quotes is enabled.

To be sure, you can test your code with sqlmap.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜