xss攻击 sql注入攻击
![preventing sql injection attacks](https://i-blog.csdnimg.cn/blog_migrate/6e6981ee6101ccf1a7950be5bee55a14.webp?x-image-process=image/format,png)
Thanks to Chris Lienert and Guido Tonnaer for kindly helping to peer review this article.
感谢Chris Lienert和Guido Tonnaer的帮助, 对本文进行了同行审阅 。
Of all the attacks that can be staged against websites, SQL injection is among the most dangerous and pervasive kind, and has been used to deal real damage to businesses and organizations in the past year. The scheme has been used to target well-known organizations and firms, including TalkTalk, VTech, Wall Street Journal and the U.S. government.
在可以针对网站进行的所有攻击中, SQL注入是最危险和最普遍的攻击之一,并且在过去一年中已被用于对企业和组织造成实际损害。 该计划已被用于瞄准知名组织和公司,包括TalkTalk , VTech ,《 华尔街日报》和美国政府 。
In a nutshell, SQL injection — also referred to as SQLi — uses vulnerabilities in a website’s input channels to target the database that sits in the backend of the web application, where the most sensitive and valuable information is stored. The scheme can be used by attackers to steal or tamper with data, hamper application functionality, and, in a worst-case scenario, gain administrative access to the database server.
简而言之,SQL注入(也称为SQLi)使用网站输入通道中的漏洞来定位位于Web应用程序后端的数据库,该数据库存储了最敏感和最有价值的信息。 攻击者可以使用该方案窃取或篡改数据,妨碍应用程序功能,并在最坏的情况下获得对数据库服务器的管理访问权限。
Here’s what you need to know about SQL injection and how to protect your site against it.
这是您需要了解的有关SQL注入的知识,以及如何保护您的网站免受它的侵害。
SQL注入攻击如何工作 (How SQL Injection Attacks Work)
SQL injection attacks are staged by sending malicious SQL commands to database servers through web requests. Any input channel can be used to send the malicious commands, including <input>
elements, query strings, cookies and files.
通过通过Web请求将恶意SQL命令发送到数据库服务器来进行SQL注入攻击。 任何输入通道均可用于发送恶意命令,包括<input>
元素,查询字符串,cookie和文件。
To see how it works, suppose you have a login form that takes a username and password:
要查看其工作原理,假设您有一个使用用户名和密码的登录表单:
![A log in form ready to be filled](https://i-blog.csdnimg.cn/blog_migrate/b73b022ff9eed79edceb12ef661bffbe.webp?x-image-process=image/format,png)
When users enter their credentials and press the “log in” button, the information is posted back to your web server, where it is combined with an SQL command. For instance, in PHP, the code would look something like the following:
当用户输入其凭据并按下“登录”按钮时,该信息将被发布回您的Web服务器,并与SQL命令结合在一起。 例如,在PHP中,代码如下所示:
$sql_command = "select * from users where username = '" . $_POST['username']; $sql_command .= "' AND password = '" . $_POST['password'] . "'";
The command would then be sent to a database server, and the resulting dataset would determine whether the username and password correspond to a valid user account. An average user inputting “john” as username and “123456” as password (never use that password, by the way) would translate to the following command:
然后将命令发送到数据库服务器,结果数据集将确定用户名和密码是否对应于有效的用户帐户。 一个普通的用户输入“ john”作为用户名,输入“ 123456”作为密码(顺便说一下 , 永远不要使用该密码 )将转换为以下命令:
SELECT * FROM users WHERE username='john' AND password='123456'
But what if the user decides to try something else, such as the following:
但是,如果用户决定尝试其他操作,例如:
![Injection code in a log in field](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/09/1473304053login-form-injected.jpg)
The resulting command would be the following, which would always return a non-empty dataset:
结果命令如下所示,它将始终返回非空数据集:
SELECT * FROM users WHERE username='john' OR 1=1; -- ' AND password='123456'
The snippet would possibly allow the user to bypass the login screen without having proper credentials.
该代码段可能允许用户在没有适当凭据的情况下绕过登录屏幕。
This is one of the simplest forms of SQL injection. With a little more effort, the same user can insert new user accounts, and delete or modify existing user accounts. In pages that display results, the same scheme can be used to display records and information that would otherwise be restricted to normal visitors, or to change the contents of records.
这是SQL注入的最简单形式之一。 稍加努力,同一用户即可插入新用户帐户,并删除或修改现有用户帐户。 在显示结果的页面中,可以使用相同的方案来显示记录和信息,否则这些记录和信息将仅限于正常访问者,或者用于更改记录的内容。
In more severe cases, where the connection to the database server is made through an administrative account (such as “root” in MySQL or “sa” in MS SQL Server), the attacker can go as far as fully compromising the server’s operating system. On Windows servers, this can manifest itself in the attacker executing extended stored procedures such as xp_cmdshell
. In one case, attackers used an SQL injection vulnerability to create user accounts on the compromised server, enable the Remote Desktop feature, setup SMB shared folders and upload malware — aside from practically messing up everything that was stored in the database.
在更严重的情况下,如果通过管理帐户(例如MySQL中的“ root”或MS SQL Server中的“ sa”)建立与数据库服务器的连接,则攻击者可能会完全破坏服务器的操作系统。 在Windows服务器上,这可以在攻击者执行扩展的存储过程(例如xp_cmdshell
。 在一种情况下,攻击者使用SQL注入漏洞在受感染的服务器上创建用户帐户,启用远程桌面功能,设置SMB共享文件夹并上传恶意软件-除了实际上破坏了存储在数据库中的所有内容之外。
如何保护自己免受SQL注入攻击 (How to Protect Yourself Against SQL Injection Attacks)
With user input channels being the main vector for SQL injection attacks, most of the defensive methods involve controlling and vetting user input for attack patterns.
由于用户输入通道是SQL注入攻击的主要载体,因此大多数防御方法都涉及控制和审查用户输入的攻击模式。
Here are several measures that can ensure user input safety.
这里有一些可以确保用户输入安全的措施。
永远不要相信用户输入 (Never trust user input)
The first rule of thumb about user input is “don’t trust and verify,” which effectively means all forms of user input should be considered malicious unless proved otherwise. This accounts not only for simple input boxes such as text areas and text boxes, but for everything else as well — such as hidden inputs, query string parameters, cookies and file uploads.
关于用户输入的第一条经验法则是“ 不信任并验证 ”,这实际上意味着,除非另行证明,否则所有形式的用户输入都应视为恶意内容。 这不仅考虑了简单的输入框(例如文本区域和文本框),还考虑了其他所有内容-例如隐藏的输入,查询字符串参数,Cookie和文件上传。
Just because the browser’s user interface doesn’t allow the user to manipulate an input, it doesn’t mean that it can’t be tampered with. Simple tools such as Burp Suite enable users to capture HTTP requests and modify anything, including hidden form values, before submitting them to the server. And if you think yourself clever by Base64 encoding your data, it can easily be decoded, modified and re-encoded by malicious users.
仅仅因为浏览器的用户界面不允许用户操纵输入,并不意味着它不能被篡改。 Burp Suite等简单工具使用户能够在将HTTP请求提交到服务器之前捕获HTTP请求并对其进行任何修改,包括隐藏的表单值。 而且,如果您认为自己对Base64编码的数据很聪明,那么恶意用户可以轻松地对其进行解码,修改和重新编码。
在服务器端验证输入字符串 (Validate input strings on the server side)
Validation is the process of making sure the right type of input is provided by users and to neutralize any potential malicious commands that might be embedded in input string. For instance, in PHP, you can use the mysql\_real\_escape\_string()
to escape characters that might change the nature of the SQL command.
验证是确保用户提供了正确类型的输入并消除可能嵌入在输入字符串中的任何潜在恶意命令的过程。 例如,在PHP中,可以使用mysql\_real\_escape\_string()
来转义可能更改SQL命令性质的字符。
An altered version of the previously-mentioned login code would be as follows:
前面提到的登录代码的更改版本如下:
$con=mysqli_connect("localhost","user","password","db");
$username = mysqli_real_escape_string($con, $_POST['username']);
$password = mysqli_real_escape_string($con, $_POST['password']);
$sql_command = "select * from users where username = '" . $username; $sql_command .= "' AND password = '" . $password . "'";
This simple modification would protect your code against the attack that was presented by adding an escape character (\) in front of the single quotes that were intentionally added by the malicious user.
这个简单的修改将保护您的代码免受攻击,即在恶意用户有意添加的单引号之前添加转义字符(\)来进行攻击。
A note on validation: If you’ve added client-side validation functions, well done. But don’t rely on it as a defensive measure against SQL injection attacks. While client-side functions might make it a notch harder to send malicious input to your server, it can easily be circumvented with a few browser tweaks and tools such as the one just mentioned. Therefore, you need to complement it with server-side validation.
验证说明:如果添加了客户端验证功能,那就做得很好。 但是,请勿将其作为针对SQL注入攻击的防御措施。 尽管客户端功能可能会使向服务器发送恶意输入变得更加困难,但是可以通过一些浏览器调整和工具(如刚才提到的工具)轻松地绕开它。 因此,您需要通过服务器端验证对其进行补充。
Some programming platforms, such as ASP.NET, include built-in features that will automatically evaluate user input for malicious content on page postbacks. But they can be circumvented by hackers with enough nerves and subtlety, so you should nonetheless run user input through your own security check procedures. You can never be too cautious.
某些编程平台(例如ASP.NET)包括内置功能,这些功能将自动评估用户输入的页面回发中是否包含恶意内容。 但是,黑客可以用足够的神经和微妙的手段来规避它们,因此,您仍然应该通过自己的安全检查程序来运行用户输入。 您永远不能太谨慎。
使用命令参数 (Use command parameters)
A better alternative to escaping would be to use command parameters. Command parameters are defined by adding placeholder names in SQL commands, which will later be replaced by user input. ASP.NET has a very intuitive and easy-to-use set of APIs for this purpose.
转义的更好替代方法是使用命令参数。 通过在SQL命令中添加占位符名称来定义命令参数,稍后将其替换为用户输入。 为此,ASP.NET具有一组非常直观且易于使用的API。
The following code, written in C#, shows how you can use the command parameters to protect your website against SQL injection:
以下用C#编写的代码显示了如何使用命令参数来保护您的网站免受SQL注入:
SqlCommand cmd = new SqlCommand ("SELECT * FROM users WHERE username=@username AND password=@password",con);
SqlParameter username = new SqlParameter(); username.ParameterName = "@username"; username.value = txtUsername.Text; cmd.Parameters.Add(username);
SqlParameter password = new SqlParameter(); password.ParameterName = "@password"; password.value = txtPassword.Text; cmd.Parameters.Add(password);
You start by creating a SqlCommand
object and using the @parameter_name
paradigm in the command string where user input should be inserted.
首先创建一个SqlCommand
对象,并在命令字符串中使用@parameter_name
范式插入用户输入。
You then create instances of SqlParameter
objects, in which you insert the user input, instead of directly concatenating it with the command string.
然后,您创建SqlParameter
对象的实例,在其中插入用户输入,而不是直接将其与命令字符串连接。
Finally, you add the SqlParameter
object to the SqlCommand
object’s Parameters collection, which will replace the parameters with the provided input. ADO.net takes care of the rest.
最后,将SqlParameter
对象添加到SqlCommand
对象的Parameters集合中,该集合将使用提供的输入替换参数。 ADO.net负责其余的工作。
In PHP, the equivalent is prepared statements, which is a bit more involved than its ASP.net counterpart. You can explore it here.
在PHP中,等效的是预处理语句,它比ASP.net对应语句要复杂得多。 您可以在这里进行探索。
明确投射您的输入 (Explicitly cast your input)
This tip is for languages such as PHP, which are weakly typed, which means you do not usually define data types for variables, and the language automatically takes care of converting different data types between each other.
本技巧文章适用于弱类型的语言,例如PHP,这意味着您通常不为变量定义数据类型,并且该语言自动负责相互之间转换不同的数据类型。
Explicit casts can act as a shortcut to escaping input where non-string types are involved. So, if you’re expecting the user to input an int
for the age
parameter, you can ensure the safety of the input with the following code in PHP:
在涉及非字符串类型的情况下,显式强制转换可以用作转义输入的快捷方式。 因此,如果希望用户为age
参数输入一个int
,则可以使用PHP中的以下代码来确保输入的安全性:
$age = (int)$_POST['age'];
Take note that this snippet only validates the input’s type, not its range. So you’ll have to run other code to make sure the user doesn’t enter a negative age — or an unrealistic one such as 1300.
请注意,此代码段仅验证输入的类型,而不验证其范围。 因此,您必须运行其他代码来确保用户输入的年龄不为负数或不现实的年龄(例如1300)。
Also, another best practice is to avoid using single quotes in SQL commands where non-string input is involved. So instead of using the following code …
另外,另一种最佳实践是避免在涉及非字符串输入SQL命令中使用单引号。 因此,不要使用以下代码……
$sql_command = "select * from users where age = " . $age;
… it would be a bit safer to use the following one:
…使用以下代码会更安全:
$sql_command = "select * from users where age = '" . $age . "'";
如何消除SQL注入漏洞 (How to Root Out SQL Injection Vulnerabilities)
As a general practice, you should check the code of every page for places where you combine page contents, commands, strings, etc. with sources that might come from users. Vetting your source code for vulnerabilities and security holes should be an inherent part of your software development process.
通常,应检查每个页面的代码,以查找将页面内容,命令,字符串等与可能来自用户的源组合在一起的位置。 审查源代码中的漏洞和安全漏洞应该是软件开发过程的固有部分。
You can also use scanning tools such as sqlmap to crawl your site’s pages for potential SQL injection vulnerabilities. In fact, hackers frequently use this tool to find and exploit SQL injection attack vectors on targeted websites, so why not use it to make them more secure?
您还可以使用诸如sqlmap之类的扫描工具来爬网站点页面,以查找潜在SQL注入漏洞。 实际上,黑客经常使用此工具在目标网站上查找和利用SQL注入攻击媒介,那么为什么不使用它使它们更安全呢?
您的最后一道防线 (Your Last Line of Defense)
No matter how much you harden your website’s security, you must prepare yourself for the day when SQL injections do take place. After all, as it is widely known in the cybersecurity industry, defenders have to win every fight, but hackers only have to win once.
无论您在多大程度上加强网站的安全性 ,都必须为发生SQL注入的那一天做好准备。 毕竟,正如在网络安全行业中众所周知的那样,防御者必须赢得每场战斗,而黑客只需赢得一次。
Here are a few tips that will help you minimize the damage when you do become a SQL injection victim.
这里有一些技巧,可以帮助您在成为SQL注入受害者时最大程度地减少损害。
避免管理特权 (Avoid administrative privileges)
Using the “root” or “sa” accounts to connect your web application to your database server is one of the worst mistakes you can commit. As I’ve already mentioned, a compromised administrative account can potentially give hackers access to the entire system. Even non-administrative accounts that have access to all databases within a server can be damaging, especially if the database server is being shared among different applications and databases.
使用“ root”或“ sa”帐户将Web应用程序连接到数据库服务器是您可能犯的最严重错误之一。 正如我已经提到的那样,一个受到破坏的管理帐户可能会给黑客提供访问整个系统的权限。 甚至可以访问服务器内所有数据库的非管理帐户也可能造成破坏,尤其是在不同应用程序和数据库之间共享数据库服务器的情况下。
Therefore, it’s best to use an account that only has simple read-write permissions to the specific database that sits behind your website, so in case your site becomes hacked through SQL injection, the scope of damage remains within the boundaries of that single database.
因此,最好使用仅对位于您网站后面的特定数据库具有简单读写权限的帐户,以防万一您的站点因SQL注入而被黑客入侵,则损害范围仍在该单个数据库的范围之内。
A more advanced approach would be to use separate connections for code segments that read from or write to your database, and further cull down permissions and roles for each segment. For instance, list pages — which do not make any modifications to the database but extensively use search parameters — can be coded to use a read-only connection to the database in order to further harden your code against mishaps.
一种更高级的方法是对从数据库读取或写入数据库的代码段使用单独的连接,并进一步确定每个段的权限和角色。 例如,可以对列表页面(不对数据库进行任何修改,但广泛使用搜索参数)进行编码,以使用与数据库的只读连接,从而进一步增强代码的安全性,以防止出现意外情况。
In MySQL, improve security by limiting access to the user account to specific IP address ranges instead of the “%” model, in order to prevent compromised accounts from being accessed from remote locations.
在MySQL中,通过限制对特定IP地址范围(而不是“%”模型)的用户帐户的访问来提高安全性,以防止从远程位置访问受损帐户。
In MS SQL server, I would strongly advise you to use the Windows Authentication model, which would limit hackers’ access to the database and make sure they won’t be able to use other channels to get into your database.
在MS SQL Server中,我强烈建议您使用Windows身份验证模型,该模型将限制黑客对数据库的访问,并确保他们将无法使用其他渠道进入您的数据库。
Also, unless you’re planning on using some of the advanced features of SQL Server, it is preferable to set up the windows service to use a limited account instead of the high privilege “Local System” account. This will minimize damage in case the “sa” account becomes compromised.
另外,除非您打算使用SQL Server的某些高级功能,否则最好将Windows服务设置为使用受限帐户而不是高特权“本地系统”帐户。 万一“ sa”帐户被盗用,这将最大程度地减少损失。
加密敏感数据 (Encrypt sensitive data)
Encrypt sensitive data in your database. This includes passwords, security questions and answers, financial data, health information, and other information that might be useful to malicious actors. This will make sure that even if hackers lay hands on your data, they won’t be able to exploit it immediately, giving you time to discover the breach, plug the hole, and take other reactive measures such as enforcing password resets, which will make sure that the stolen data loses its value before the attacker deciphers it.
加密数据库中的敏感数据。 这包括密码,安全性问题和答案,财务数据,健康信息以及其他可能对恶意行为者有用的信息。 这样可以确保即使黑客将您的数据放到手,他们也将无法立即利用它,从而给您时间来发现漏洞,堵塞漏洞并采取其他应对措施,例如强制执行密码重置,这将确保在攻击者破译之前,被盗的数据会失去其价值。
If you’re hashing your passwords, use strong algorithms such as SHA-2, which will soon become the industry standard for password protection. MD5 and SHA-1 are obsolete and can be reversed.
如果您要对密码进行哈希处理,请使用强大的算法,例如SHA-2,它将很快成为密码保护的行业标准 。 MD5和SHA-1已过时,可以反转。
For other forms of encryption, take care where you store the keys, and never put all your eggs in one basket. There would be no point in using encryption if the keys are right next to the encrypted data and hackers will easily gain access to them as soon as they compromise the server.
对于其他形式的加密,请注意将密钥存储在何处,切勿将所有鸡蛋都放在一个篮子里。 如果密钥位于加密数据旁边,则使用加密将毫无意义,一旦黑客破坏了服务器,黑客将很容易获得对它们的访问权限。
如果不需要,不要存储敏感数据 (Don’t store sensitive data if you don’t need it)
Whenever you store information in your database, consider how damaging it can become if it falls into the wrong hands, and decide whether you really need to store it or not. The Ashley Madison hack, which spilled the dark secrets and most intimate information of some 37 million people on the internet and dealt some serious damage, partly owed its success to the fact that the provider had refrained from wiping sensitive information from its databases.
每当您将信息存储在数据库中时,请考虑一下如果信息落入错误的人手中会对其造成多大破坏,并确定您是否真的需要存储它。 阿什利·麦迪逊 ( Ashley Madison)骇客在互联网上泄露了约3700万人的暗中秘密和最亲密的信息,并造成了严重破坏,部分原因是其成功的原因是提供商避免从数据库中清除敏感信息。
So the bottom line is, don’t store sensitive information in your database unless you really have to. And even then, delete the information when it’s no longer of use.
因此,最重要的是,除非确实需要,否则不要在数据库中存储敏感信息。 即使这样,也可以在不再使用该信息时将其删除。
最后的想法 (Final Thoughts)
SQL injection has been around for decades and will likely continue to top the vulnerability charts for years to come. It takes a few easy — but well-calculated — steps to protect yourself and your users against it, and it should be among your top priorities when auditing your source code for security holes.
SQL注入已经存在了数十年,并且可能会在未来几年继续保持漏洞图表的首位。 采取一些简单但经过精心计算的步骤来保护自己和您的用户免受它的侵害,在审核源代码中的安全漏洞时,它应该是您的头等大事。
The key to avoid being the victim of the next huge SQL injection data breach is first, to control and validate user input, and second, to prepare yourself for the “when,” not the “if.”
避免成为下一个巨大SQL注入数据泄露事件的受害者的关键是,首先是控制和验证用户输入,其次是为“何时”(而不是“如果”)做好准备。
翻译自: https://www.sitepoint.com/how-to-protect-your-website-against-sql-injection-attacks/
xss攻击 sql注入攻击