这段代码中可以进行 SQL 注入吗?
简介
我接手了一个非常混乱的PHP页面的维护,这是一个度假公寓的预订平台,但这并不重要。该代码最初是由设计师(而不是编码员)完成的,而且非常糟糕。通过“true”和“false”字符串传递布尔变量是小问题之一。我想说服页面的所有者,给我时间(当然还有金钱)来清理代码(或重写它)。
显然最初的“开发人员”从未听说过 SQL 注入,因为他直接在 SQL 语句中使用 POST 和 GET 变量。为了说服所有者,我想通过在不使用密码的情况下以管理员身份登录来让他感到震惊。
tl;dr(或:实际问题)
此语句(其中 $p_username 是一个 POST 变量,其中包含“用户名”输入字段的内容):
"SELECT password FROM user WHERE username = '$p_username'"
返回的字符串(这是存储的密码的未加盐的 MD5 哈希值)然后将其与输入到“密码”字段中的(也是散列的)字符串进行比较,如果两个字符串都匹配,则用户将以输入的用户身份登录。是否可以在用户名字段中输入一些内容以“假”管理员身份登录?
注意:数据库服务器是 MySQL,PHP 版本为 5,并且 magic_quotes
已启用。
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 convince 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
正如 Shrapnel 上校所指出的,
magic_quotes
确实使它变得不可能,除非您在某些 非常特殊的情况。然而,如果你说的是真的,那么最初的开发人员很可能对 magic_quotes 不太了解,所以如果他曾经将 GET/POST/COOKIE 值存储在 SQL 语句之外的其他地方,他很可能会搞砸。简而言之,寻找
'
和"
合法的地方,并检查它们是否不会搞乱。另外 - 他知道
htmlspecialchars( )
,或者 HTML/Javascript 注入仍然可能吗?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.
如果这是完整的查询并且密码检查是在 PHP 端完成的,您将无法以管理员身份登录(即使 magic_quotes 已关闭),因为您仍然必须匹配密码哈希。
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.
正如其他人所指出的,让单引号超过魔术引号是很棘手的,但如果可以做到,查询就完事了。考虑一下我们是否可以注入以下内容:
这会将字符串“foo”作为密码返回给 PHP,因此我们需要做的就是确保我们的表单发送 $username 的注入,以及 $password 的“foo”。
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:
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.
编辑
addslashes()
有多种攻击向量。我在下面选择的第一个是基于之前在答案中链接的文章,该文章引用它来支持相反的主张。至少还有一种情况是使用不少于 UTF-8 编码的超长字符串。http://www.erich-kachel.de/?tag=addslashes
可以构造如下类似的技术。总而言之,MySQL 团队认为淘汰
magic_quotes
是合适的,并且强烈建议不要假装 addslashes() 是一种真正的保护形式。 也许 MySQL 团队会更清楚?就其价值而言,mysql_real_escape_string 也有一些边缘情况漏洞,但由于它是 MySQL 特定的而不仅仅是 PHP 特定的,所以它确实会存在更进一步。更好的解决方案是使用查询参数。原始答案如下是
的,可以以管理员身份登录。不是一次性的,而是两次就可以了。
参考 - http://shiflett.org/blog/ 2006/jan/addslashes-versus-mysql-real-escape-string
(是的,这是来自另一个答案的相同链接,但相反,我的解释是,除了 utf8 之外,在任何多字节字符集上通常都可以)
您没有说明您的系统是否是多字节的,但由于问题是开放的,我会假设是这样。
我已经更改了“admin”用户的用户名和密码
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.
I have changed the user name AND password of the "admin" user
我认为验证所有输入变量并转义所有特殊字符很重要,即使启用了 magic_quotes 也是如此。
当然,您可以使用 sqlmap 测试您的代码。
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.