Cuatro formas de prevenir la inyección de SQL en proyectos Java

¿Qué es la inyección SQL?

La inyección SQL significa que la aplicación web no juzga la legalidad de los datos ingresados ​​por el usuario o no los filtra estrictamente. El atacante puede agregar declaraciones SQL adicionales al final de las declaraciones de consulta predefinidas en la aplicación web sin el conocimiento del administrador. Implementar operaciones ilegales bajo ciertas condiciones, engañando así al servidor de la base de datos para que realice consultas arbitrarias no autorizadas, obteniendo así la información de datos correspondiente.

caso SQL

String sql = "delete from table1 where id = " + "id";

Esta identificación se obtiene de los parámetros de la solicitud. Si los parámetros se unen en:
1001 o 1 = 1,
la declaración más ejecutada se convierte en:

String sql = "delete from table1 where id = 1001 or 1 = 1";

En este momento, los datos de la base de datos se borrarán y las consecuencias serán muy graves.

Cómo prevenir la inyección de SQL en proyectos Java

Aquí hay 4 tipos:

  • PreparedStatement evita la inyección de SQL
  • #{} en mybatis evita la inyección de SQL
  • Filtrar palabras confidenciales en los parámetros de solicitud
  • El proxy inverso nginx evita la inyección de SQL

1. PreparedStatement previene la inyección de SQL.
PreparedStatement tiene una función de precompilación. Tomando el SQL anterior como ejemplo, el
SQL precompilado que usa PreparedStatement es:

delete from table1 where id = ?

En este momento, la estructura de la declaración SQL se ha arreglado. No importa "?" se reemplaza con cualquier parámetro, la declaración SQL solo considera que solo hay una condición después de dónde. Cuando se pasa 1001 o 1 = 1, la declaración informar un error, evitando así la inyección de SQL.
2. La expresión #{} en mybatis previene la inyección de SQL.
La expresión #{} en mybatis previene la inyección de SQL. Es similar a PreparedStatement, las cuales precompilan declaraciones SQL
. Nota:

#{}: marcador de posición de parámetro
${}: carácter de reemplazo de empalme, no puede evitar la inyección de SQL, generalmente se usa

  • Pasar objetos de la base de datos (como el nombre de la base de datos, el nombre de la tabla)
  • Las condiciones después del pedido filtran las palabras sensibles de los parámetros de solicitud.

3. Filtrar palabras confidenciales en los parámetros de solicitud.

Así es como se escribe springboot, de la siguiente manera:

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.Enumeration;
 
@WebFilter(urlPatterns = "/*",filterName = "sqlFilter")
@Configuration
public class SqlFilter implements Filter {
    
    
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    }
 
    /**
     * @description sql注入过滤
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        ServletRequest request = servletRequest;
        ServletResponse response = servletResponse;
        // 获得所有请求参数名
        Enumeration<String> names = request.getParameterNames();
        String sql = "";
        while (names.hasMoreElements()){
    
    
            // 得到参数名
            String name = names.nextElement().toString();
            // 得到参数对应值
            String[] values = request.getParameterValues(name);
            for (int i = 0; i < values.length; i++) {
    
    
                sql += values[i];
            }
        }
        if (sqlValidate(sql)) {
    
    
            //TODO 这里直接抛异常处理,前后端交互项目中,请把错误信息按前后端"数据返回的VO"对象进行封装
            throw new IOException("您发送请求中的参数中含有非法字符");
        } else {
    
    
            filterChain.doFilter(request,response);
        }
    }
 
    /**
     * @description 匹配效验
     */
    protected static boolean sqlValidate(String str){
    
    
        // 统一转为小写
        String s = str.toLowerCase();
        // 过滤掉的sql关键字,特殊字符前面需要加\\进行转义
        String badStr =
                "select|update|and|or|delete|insert|truncate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|table|"+
                        "char|declare|sitename|xp_cmdshell|like|from|grant|use|group_concat|column_name|" +
                        "information_schema.columns|table_schema|union|where|order|by|" +
                        "'\\*|\\;|\\-|\\--|\\+|\\,|\\//|\\/|\\%|\\#";
        //使用正则表达式进行匹配
        boolean matches = s.matches(badStr);
        return matches;
    }
 
    @Override
    public void destroy() {
    
    }
}

4. El proxy inverso nginx evita la inyección de SQL.
Cada vez más sitios web utilizan nginx para el proxy inverso. También podemos configurar esta capa para evitar la inyección de SQL.

Coloque el siguiente código del archivo de configuración de Nginx en el bloque del servidor y luego reinicie Nginx.

.

```sql
if ($request_method !~* GET|POST) {
    
     return 444; }
 #使用444错误代码可以更加减轻服务器负载压力。
 #防止SQL注入
 if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) {
    
     return 555; }
 if ($uri ~* (/~).*) {
    
     return 501; }
 if ($uri ~* (\\x.)) {
    
     return 501; }
 #防止SQL注入 
 if ($query_string ~* "[;'<>].*") {
    
     return 509; }
 if ($request_uri ~ " ") {
    
     return 509; }
 if ($request_uri ~ (\/\.+)) {
    
     return 509; }
 if ($request_uri ~ (\.+\/)) {
    
     return 509; }
 #if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) {
    
     return 503; }
 #防止SQL注入
 if ($request_uri ~* "(cost\()|(concat\()") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]union[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]and[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]select[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]or[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]update[+|(%20)]") {
    
     return 504; }
 if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") {
    
     return 504; }
 if ($query_string ~ "(<|%3C).*script.*(>|%3E)") {
    
     return 505; }
 if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") {
    
     return 505; }
 if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") {
    
     return 505; }
 if ($query_string ~ "proc/self/environ") {
    
     return 505; }
 if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") {
    
     return 505; }
 if ($query_string ~ "base64_(en|de)code\(.*\)") {
    
     return 505; }
 if ($query_string ~ "[a-zA-Z0-9_]=http://") {
    
     return 506; }
 if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") {
    
     return 506; }
 if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") {
    
     return 506; }
 if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") {
    
     return 507; }
 if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {
    
    return 507; }
 if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") {
    
     return 507; }
 if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") {
    
     return 507; }
 #这里大家根据自己情况添加删减上述判断参数,cURL、wget这类的屏蔽有点儿极端了,但要“宁可错杀一千,不可放过一个”。
 if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) {
    
     return 508; }
 #同上,大家根据自己站点实际情况来添加删减下面的屏蔽拦截参数。
 if ($http_user_agent ~* "Go-Ahead-Got-It") {
    
     return 508; }
 if ($http_user_agent ~* "GetWeb!") {
    
     return 508; }
 if ($http_user_agent ~* "Go!Zilla") {
    
     return 508; }
 if ($http_user_agent ~* "Download Demon") {
    
     return 508; }
 if ($http_user_agent ~* "Indy Library") {
    
     return 508; }
 if ($http_user_agent ~* "libwww-perl") {
    
     return 508; }
 if ($http_user_agent ~* "Nmap Scripting Engine") {
    
     return 508; }
 if ($http_user_agent ~* "~17ce.com") {
    
     return 508; }
 if ($http_user_agent ~* "WebBench*") {
    
     return 508; }
 if ($http_user_agent ~* "spider") {
    
     return 508; } #这个会影响国内某些搜索引擎爬虫,比如:搜狗
 #拦截各恶意请求的UA,可以通过分析站点日志文件或者waf日志作为参考配置。
 if ($http_referer ~* 17ce.com) {
    
     return 509; }
 #拦截17ce.com站点测速节点的请求,所以明月一直都说这些测速网站的数据仅供参考不能当真的。
 if ($http_referer ~* WebBench*") {
    
     return 509; }
 #拦截WebBench或者类似压力测试工具,其他工具只需要更换名称即可。

Supongo que te gusta

Origin blog.csdn.net/houxian1103/article/details/132748104
Recomendado
Clasificación