精华内容
下载资源
问答
  • SpringBoot 防止XSS攻击和SQL攻击拦截器(Filter)
    千次阅读
    2021-03-24 10:42:09

    什么是SQL攻击、什么是XSS攻击

    SQL 攻击:把SQL命令插入到Web表单并提交,欺骗服务器执行恶意的SQL命令。

    XSS 攻击:向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的。

    创建拦截器第一步:

    创建XssAndSqlHttpServletRequestWrapper包装器,这是实现XSS和SQL过滤的关键,在其内重写了getParameter,getParameterValues,getHeader等方法,对http请求内的参数进行了过滤。

    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.Vector;
    import java.util.regex.Pattern;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    import org.springframework.util.StreamUtils;
    
    public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
    	HttpServletRequest orgRequest = null;
    	private Map<String, String[]> parameterMap;
    	private final byte[] body; // 用于保存读取body中数据
    
    	public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    		super(request);
    		orgRequest = request;
    		parameterMap = request.getParameterMap();
    		body = StreamUtils.copyToByteArray(request.getInputStream());
    	}
    	
    	// 重写几个HttpServletRequestWrapper中的方法
        /**
         * 获取所有参数名
         *
         * @return 返回所有参数名
         */
        @Override
        public Enumeration<String> getParameterNames() {
            Vector<String> vector = new Vector<String>(parameterMap.keySet());
            return vector.elements();
        }
    
        /**
         * 覆盖getParameter方法,将参数名和参数值都做xss & sql过滤。<br/>
         * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
         * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
         */
        @Override
        public String getParameter(String name) {
            String[] results = parameterMap.get(name);
            if (results == null || results.length <= 0)
                return null;
            else {
                String value = results[0];
                if (value != null) {
                    value = xssEncode(value);
                }
                return value;
            }
        }
    
        /**
         * 获取指定参数名的所有值的数组,如:checkbox的所有数据 接收数组变量 ,如checkobx类型
         */
        @Override
        public String[] getParameterValues(String name) {
            String[] results = parameterMap.get(name);
            if (results == null || results.length <= 0)
                return null;
            else {
                int length = results.length;
                for (int i = 0; i < length; i++) {
                    results[i] = xssEncode(results[i]);
                }
                return results;
            }
        }
    
        /**
         * 覆盖getHeader方法,将参数名和参数值都做xss & sql过滤。<br/>
         * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
         * getHeaderNames 也可能需要覆盖
         */
        @Override
        public String getHeader(String name) {
    
            String value = super.getHeader(xssEncode(name));
            if (value != null) {
                value = xssEncode(value);
            }
            return value;
        }
        
        /**
         * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
         *
         * @param s
         * @return
         */
        private static String xssEncode(String s) {
            if (s == null || s.isEmpty()) {
                return s;
            } else {
                s = stripXSSAndSql(s);
            }
            StringBuilder sb = new StringBuilder(s.length() + 16);
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                switch (c) {
                    case '>':
                        sb.append(">");// 转义大于号
                        break;
                    case '<':
                        sb.append("<");// 转义小于号
                        break;
                    // case '\'':
                    // sb.append("'");// 转义单引号
                    // break;
                    // case '\"':
                    // sb.append(""");// 转义双引号
                    // break;
                    case '&':
                        sb.append("&");// 转义&
                        break;
                    case '#':
                        sb.append("#");// 转义#
                        break;
                    default:
                        sb.append(c);
                        break;
                }
            }
            return sb.toString();
        }
        
        /**
         * 获取最原始的request
         *
         * @return
         */
        public HttpServletRequest getOrgRequest() {
            return orgRequest;
        }
        
        /**
         * 审查参数的具体方法
         * @param value
         * @return
         */
        public static boolean checkXSSAndSql(String value) {
            boolean flag = false;
            if (value != null) {
                // NOTE: It's highly recommended to use the ESAPI library and
                // uncomment the following line to
                // avoid encoded attacks.
                // value = ESAPI.encoder().canonicalize(value);
                // Avoid null characters
                /** value = value.replaceAll("", ""); ***/
                // Avoid anything between script tags
                Pattern scriptPattern = Pattern.compile(
                        "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid anything in a
                // src="http://www.yihaomen.com/article/java/..." type of
                // e-xpression
                scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Remove any lonesome </script> tag
                scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid e-xpression(...) expressions
                scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid οnlοad= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                scriptPattern = Pattern.compile("\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr|mid|master|truncate|char|declare|or)\\b|(\\*|;|\\+|'|%)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
            }
            return flag;
        }
    
        /**
         * 检查参数方法
         * @return
         */
        public final boolean checkParameter() {
            Map<String, String[]> submitParams = new HashMap(parameterMap);
            Set<String> submitNames = submitParams.keySet();
            for (String submitName : submitNames) {
                Object submitValues = submitParams.get(submitName);
                if ((submitValues instanceof String)) {
                    if (checkXSSAndSql((String) submitValues)) {
                        return true;
                    }
                } else if ((submitValues instanceof String[])) {
                    for (String submitValue : (String[])submitValues){
                        if (checkXSSAndSql(submitValue)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    
        /**
         * 获取最原始的request的静态方法
         *
         * @return
         */
        public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
            if (req instanceof XssAndSqlHttpServletRequestWrapper) {
                return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();
            }
            return req;
        }
    
        /**
         *
         * 防止xss跨脚本攻击(替换,根据实际情况调整)
         */
    
        public static String stripXSSAndSql(String value) {
            if (value != null) {
                // NOTE: It's highly recommended to use the ESAPI library and
                // uncomment the following line to
                // avoid encoded attacks.
                // value = ESAPI.encoder().canonicalize(value);
                // Avoid null characters
                /** value = value.replaceAll("", ""); ***/
                // Avoid anything between script tags
                Pattern scriptPattern = Pattern.compile(
                        "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid anything in a
                // src="http://www.yihaomen.com/article/java/..." type of
                // e-xpression
                scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Remove any lonesome </script> tag
                scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid e-xpression(...) expressions
                scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid οnlοad= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
            }
            return value;
        }
        
        /**
         **application/x- www-form-urlencoded是Post请求默认的请求体内容类型,也是form表单默认的类型。
         * Servlet API规范中对该类型的请求内容提供了request.getParameter()方法来获取请求参数值。
         * 但当请求内容不是该类型时,需要调用request.getInputStream()或request.getReader()方法来获取请求内容值。
         */
        /**
         * 获取请求内容
         * @return
         * @throws IOException
         */
        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }
    
        /**
         * 返回请求内容字节流,多用于文件上传,
         * request.getReader()是对前者返回内容的封装,可以让调用者更方便字符内容的处理(不用自己先获取字节流再做字符流的转换操作)
         * @return
         * @throws IOException
         */
        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
            return new ServletInputStream() {
    
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
    
                @Override
                public boolean isFinished() {
                    // TODO Auto-generated method stub
                    return false;
                }
    
                @Override
                public boolean isReady() {
                    // TODO Auto-generated method stub
                    return false;
                }
    
                @Override
                public void setReadListener(ReadListener arg0) {
                    // TODO Auto-generated method stub
    
                }
            };
        }
    
    }
    

    创建拦截器第二步:

    编写过滤器

    
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.alibaba.fastjson.JSONObject;
    import com.digipower.common.entity.Result;
    import com.digipower.http.servlet.request.wrapper.XssAndSqlHttpServletRequestWrapper;
    
    /**
     * 防止XSS 攻击和SQL注入攻击的Filter
     * @ClassName:  XssAndSqlFilter   
     * @Description:TODO(这里用一句话描述这个类的作用)   
     * @author:
     * @date:   2021年3月22日 下午2:29:12   
     *     
     * @Copyright: 2021 www.digipower.cn 
     * 注意:
     */
    public class XssAndSqlFilter implements Filter {
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		 String method = "GET";//设置初始值
    	        String param = "";
    	        XssAndSqlHttpServletRequestWrapper xssRequest = null;
    	        if (request instanceof HttpServletRequest) {//判断左边的对象是否是它右边对象的实例
    	            method = ((HttpServletRequest) request).getMethod();//得到请求URL地址时使用的方法
    	            xssRequest = new XssAndSqlHttpServletRequestWrapper((HttpServletRequest) request);//创建对象
    	        }
    	        if ("POST".equalsIgnoreCase(method)) {//判断是否为post
    	            param = this.getBodyString(xssRequest.getReader());//获取参数
    	            if(StringUtils.isNotBlank(param)){//等价于 str != null && str.length > 0 && str.trim().length > 0
    	                if(xssRequest.checkXSSAndSql(param)){//进行参数审查
    	                    response.setCharacterEncoding("UTF-8");
    	                    response.setContentType("application/json;charset=UTF-8");
    	                    PrintWriter out = response.getWriter();
    	                    out.write(JSONObject.toJSONString(Result.error("401", "您所访问的页面请求中有违反安全规则元素存在,拒绝访问!")));
    	                    return;
    	                }
    	            }
    	        }
    
    	        /**
    	         * 检查参数的时候 同时检查请求的方法
    	         * 只检查get请求方法和post请求方法的的参数的数据是否合法
    	         * 并不是所有参数都要检查,首先必须是一个get或者post,再去校验参数
    	         * 因为PUT方法在进行参数审查的时候没办法通过所以直接过滤掉
    	         */
    	        if (xssRequest.checkParameter()&&(method.equals("POST") || method.equals("GET"))){
    	            response.setCharacterEncoding("UTF-8");
    	            response.setContentType("application/json;charset=UTF-8");
    	            PrintWriter out = response.getWriter();
    	            out.write(JSONObject.toJSONString(Result.error("401", "您所访问的页面请求中有违反安全规则元素存在,拒绝访问!")));
    	            return;
    	        }
    	        chain.doFilter(xssRequest, response);
    		
    	}
    	
    	// 获取request请求body中参数
        public static String getBodyString(BufferedReader br) {
            String inputLine;
            String str = "";
            try {
                while ((inputLine = br.readLine()) != null) {
                    str += inputLine;
                }
                br.close();
            } catch (IOException e) {
                System.out.println("IOException: " + e);
            }
            return str;
        }
    
    }
    

    创建拦截器第三步

    在webconfig中注册过滤器XssAndSqlFilter

    @Configuration
    @EnableWebMvc
    public class SpringMVCConfig extends WebMvcConfigurerAdapter {
        @Bean
    	public FilterRegistrationBean xssFilterRegistrationBean() {
    		// 创建一个自定义的 Filter
    		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    		filterRegistrationBean.setFilter(new XssAndSqlFilter());
    		filterRegistrationBean.setOrder(1);
    		filterRegistrationBean.setEnabled(true);
    		filterRegistrationBean.addUrlPatterns("/*");
    		// 过滤指定请求地址
    		Map<String, String> initParameters = new HashMap<String, String>();
    		initParameters.put("excludes", "/auth/login,/auth/code,/auth/phone,/swagger-ui.html/**,/swagger-resources/**,/webjars/**,/v2/api-docs/**,/upload_file/**");
    		initParameters.put("isIncludeRichText", "true");
    		filterRegistrationBean.setInitParameters(initParameters);
    		return filterRegistrationBean;
    	}
    
    
    }

     

    备注

    • excludes用于配置不需要参数过滤的请求url。

    • isIncludeRichText默认为true,主要用于设置富文本内容是否需要过滤。

     

    更多相关内容
  • 基于约束的SQL攻击

    2020-12-14 21:43:39
     注意:本文不是讲述SQL注入攻击  背景介绍  近,我遇到了一个有趣的代码片段,开发者尝试各种方法来确保数据库的安全访问。当新用户尝试注册时,将运行以下代码: <?php // Checking whether a user ...
  • 主要介绍了php中常见的sql攻击正则表达式,实例汇总了针对各种常见的SQL语句及正则表达式原理的分析与应用,对于PHP程序设计的安全来说具有很好的参考借鉴价值,需要的朋友可以参考下
  • 基于SQL攻击的SQL Server安全性研究.pdf
  • 防SQL注入与SQL攻击

    2018-12-14 22:08:51
    SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。
  • SQL攻击数据库的防范措施.pdf
  • sql注入总结 语句精简 类型丰富 种类齐全 值得学习 欢迎借鉴
  • 甲骨文发布首款数据库防火墙 监控SQL攻击.pdf
  • 基于机器学习的SQL攻击检测技术研究.pdf
  • 基于DVWA靶场攻击软件进行SQL注入演示,结合sqlmap工具进行数据库信息获取,获取数据库列表、数据库表、数据库列名等信息
  • SQL攻击与防御

    2016-10-16 11:06:17
    SQL攻击与防御
  • 主要是关于各种SQL攻击,跨站攻击,以及常见的很多攻击方法的说明及解决方案
  • SQL攻击工具包

    2013-07-05 08:08:19
    具包 _SQL注入攻击工具包
  • SQL注入攻击与防御

    2018-07-17 15:29:47
    SQL注入是Internet上最危险、最有名的安全漏洞之一,《SQL注入攻击与防御》是目前唯一一本专门致力于讲解SQL威胁的图书。《SQL注入攻击与防御》作者均是专门研究SQL注入的安全...通过设计来避免由SQL攻击所带来的危险
  • SQL注入攻击介绍

    万次阅读 多人点赞 2022-03-20 20:00:48
    SQL注入攻击介绍 一、SQL注入攻击简介 SQL注入攻击是指,后台数据库操作时,如果拼接外部参数到SQL语句中,就可能导致欺骗服务器执行恶意的SQL语句,造成数据泄露、删库、页面篡改等严重后果。按变量类型分为:数字...

    SQL注入攻击介绍

    一、SQL注入攻击简介

    SQL注入攻击是指,后台数据库操作时,如果拼接外部参数到SQL语句中,就可能导致欺骗服务器执行恶意的SQL语句,造成数据泄露、删库、页面篡改等严重后果。按变量类型分为:数字型、字符型;按HTTP提交方式分为:GET注入、POST注入、Cookie注入;按注入方式分为:报错注入、盲注(布尔盲注、时间盲注)、堆叠注入等等。
    

    二、SQL注入分类

    按变量类型分类:如SQL语句为select *from user where param=1(数字型)、select *from user where param=”abc”(字符型)。
    按HTTP提交方式分类:通常GET注入变量在query string里、POST注入变量在body中、Cookie注入变量在Cookie中。
    按注入方式分类:报错注入是指利用数据库的某些机制,故意制造错误条件,使得查询结果出现在错误信息中;盲注是指数据不能回显到前端页面,需要利用一些方法进行判断或者尝试。返回true或flase(布尔盲注),返回延时sleep()(时间盲注);堆叠注入是指多条SQL语句一起执行。
    

    POST注入

    三、SQL注入利用

    对于循环SQL语法的数据库而言,SQL注入的原理基本相似,但由于语法、函数的不同,也存在许多细微的差异。对于不同数据库注入时,思路、方法不可能完全一样。下面SQL注入利用以MySQL 5.7.26为例。先介绍几个MySQL的特性。
    
    1:通过注释获取版本信息
    MySQL支持3种注释风格:
    #:注释从“#”字符到行尾;
    --:注释从“--”序列到行尾。
    /* */:注释从/*序列到后面的*/序列中间的字符。
    其中,“/* */”注释存在一个特点,在“/*!*/”中感叹号是有特殊意义。如果“!”后面不加入版本号,MySQL将会直接执行SQL语句;若MySQL版本号高于或等于!后的版本号,语句将会执行SQL语句。
    如:
    

    请添加图片描述

    因此对于MySQL可利用该特性进行SQL注入获取版本信息。再根据当前版本是否有安全漏洞,进一步做利用。
    2:获取元数据
    MySQL 5.0及其以上版本提供了INFORMATION_SCHEMA,INFORMATION_SCHEMA是信息数据库,它提供了访问数据库元数据的方式。如下面几个例子:
    查询用户数据库名称:
    select SCHEMA_NAME from INFORMATION_SCHEMA.SCHEMATA(show databases的结果从SCHEMATA表取)
    

    请添加图片描述

    查询当前数据库表:
    select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = database()
    

    请添加图片描述

    查询指定表的所有字段:
    select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = "user"
    

    请添加图片描述

    3:UNION查询
    即使连接的select语句的数据类型不匹配,但也能正常执行。而SQL Server、Oracle则会认为语句错误,无法执行。如下(select username, password from test_user union select 1, 2):
    

    请添加图片描述

    攻击者对数据库注入,无非是利用数据库获取更多的数据或者更大的权限,那么利用方式可以归为一下:查询数据、读写文件、执行命令
    

    1.查询数据

    在这里插入图片描述
    请添加图片描述

    注入点在user参数,传参时使用单引号闭合前一个单引号,使用#注释后面的引号。结合MySQL结合MySQL的特性2、3可以查询用户数据库名称、当前数据库表、指定表的所有字段。由于前后查询字段的编码方式不同,需要做转换后才能正常执行。
    

    请添加图片描述

    MySQL存在报错注入,通过updatexml、extractvalue、floor函数利用。Updatexml(返回替换的XML片段)、extractvalue(使用XPath表示法从XML字符串中提取值),用法如下:
    

    请添加图片描述

    两个函数的第二个参数为xpath,如果语法错误,则会从错误的语法开始报错。利用concat拼接想要获取的数据库内容到第二个参数,第一个参数为错误的语法开始,报错时则会输出内容。floor函数报错注入则是利用group by时会建立虚拟表,而插入虚拟表的前后rand都会执行,导致插入数据冲突而报错。
    

    2.读写文件

    MySQL提供了load_file()函数,可用于读取文件,文件路径可用16进制转换或char(ASCII码)的方式传入。MySQL也提供了into outfile写文件的操作,写入内容也可以使用char(ASCII码)的方式表示。
    

    请添加图片描述

    如果读不到文件,可能是因为mysql的secure_file_priv的值默认为NULL,可通过 show global variables like '%secure%' 查看,然后在mysql配置文件下的[mysqld] 下添加条目:"secure_file_priv =",并重启mysql即可。
    

    请添加图片描述

    3.执行命令

    MySQL的system函数可以执行系统命令,但这仅限本地执行。如果使用windows远程连接mysql root身份登录时,则无法执行shell。
    Linux本地:
    

    请添加图片描述

    Windows远程连接:
    

    在这里插入图片描述

    通常是通过UDF提权、MOF提权进行利用。UDF是用户自定义函数,通过文件写入,利用UDF创建一个执行命令的函数。MOF只适用在WinServer2003,原理是C:/Windows/system32/wbem/mof目录下的mof文件每隔一段时间都会被系统执行,同样也是通过文件写入进行利用。条件和场景比较复杂,此处不做展开,有兴趣可以自行了解。
    

    4.宽字节注入及长字符截断

    php配置的magic_quotes_gpc(魔术引号)启用时,接收到的“’”、“””、“\”和NULL字符都会被自动加上反斜线转义,这样就无法闭合单引号,造成字符型注入。如果mysql使用GBK编码,则会认为两个字节是一个汉子,前一个ascii要大于128,故如果输入“%df’”经过php转义为“%df\’”后,“%df\”会被mysql识别为中文,从而绕过转义。
    

    请添加图片描述

    MySQL的sql_mode选项默认值对插入超长值并不会报错,导致了一些截断问题。
    

    请添加图片描述
    请添加图片描述

    5.时间盲注及二次SQL注入

    如果SQL查询的结果并不会返回给前端页面,往往只能通过盲注,即页面无差异的注入。时间盲注则是一种盲注。在语句中使用if及sleep函数,猜测数据内容。
    

    请添加图片描述

    二次SQL注入是一种非常难以防范的SQL注入攻击。如下面的例子:在数据插入时由于php转义了单引号,故插入的SQL语句没有注入。但在查询时,直接从数据库获取数据,而数据库数据存在单引号,造成注入。
    

    请添加图片描述

    6.使用Sqlmap工具

    1.首先验证漏洞是否存在:id=2 and 1=1页面返回,id=2 and 1=2页面返回为空。
    

    请添加图片描述
    请添加图片描述

    2.使用sqlmap扫描后台数据库:sqlmap.py -u "http://www.xxx.com/xxx.php?id=2" --dbs
    返回:[*] hdm1060277_db    [*] information_schema
    

    请添加图片描述

    3.查找存储账号密码信息的表:sqlmap.py -u "http://www.xxx.com/xxx.php?id=2-1" -D hdm1060277_db --search -C user
    返回:Table: dl
    

    请添加图片描述

    4.查看表内容:sqlmap.py -u "http://www.hechemist.com/hxydetailpro.php?id=2-1" -D hdm1060277_db -T dl -C username7,password7 --dump
    返回:hxyuan    | xxx
    

    请添加图片描述

    5.登录后台:http://www.xxx.com/hy/mn.php
    

    请添加图片描述

    四、SQL注入的防御

    根据变量类型可以将SQL注入分为数字型和字符串型。对于数字型注入的防御,只要严格判断数据类型非字符串即可。对于字符串的SQL注入,主要通过预编译&参数化查询、校验白名单或正则匹配进行防御。
    预编译语句在创建时已经将SQL语句发送给DBMS,完成了解析、检查、编译等工作,我们需要做的仅仅是将变量传给SQL语句而已。预编译技术可以有效的防御SQL注入。
    

    请添加图片描述

    五、NoSQL注入

    SQL注入是由于SQL语句拼接了不可信参数导致的,而NoSQL数据库(如:Mongodb)使用JSON格式查询数据交互的方法也同样可能存在不可信参数拼接。因此,即使这些数据库没有使用传统的SQL语法,它们仍然可能的存在NoSQL注入攻击。
    

    对代码感兴趣的,关注公众号“吴花果的吴花火”,输入”sql注入“获取sql注入实例代码的下载链接。
    在这里插入图片描述

    展开全文
  • SQL 注入(SQLi)是一种可执行恶意 SQL 语句的注入攻击。这些 SQL 语句可控制网站背后的数据库服务。攻击者可利用 SQL 漏洞绕过网站已有的安全措施。他们可绕过网站的身份认证和授权并访问整个 SQL 数据库的数据。...

    SQL 注入(SQLi)是一种可执行恶意 SQL 语句的注入攻击。这些 SQL 语句可控制网站背后的数据库服务。攻击者可利用 SQL 漏洞绕过网站已有的安全措施。他们可绕过网站的身份认证和授权并访问整个 SQL 数据库的数据。他们也可利用 SQL 注入对数据进行增加、修改和删除操作。

    SQL 注入可影响任何使用了 SQL 数据库的网站或应用程序,例如常用的数据库有 MySQL、Oracle、SQL Server 等等。攻击者利用它,便能无需授权地访问你的敏感数据,比如:用户资料、个人数据、商业机密、知识产权等等。SQL 注入是一种最古老、最流行、也最危险的网站漏洞。OWASP 组织(Open Web Application Security Project)在 2017 年的 OWASP Top 10 文档中将注入漏洞列为对网站安全最具威胁的漏洞。

    SQL Injection

    发起 SQL 注入攻击的过程及原因

    为了发起 SQL 注入攻击,攻击者首先需要在网站或应用程序中找到那些易受攻击的用户输入。这些用户输入被有漏洞的网站或应用程序直接用于 SQL 查询语句中。攻击者可创建这些输入内容。这些内容往往被称为恶意载体,它们是攻击过程中的关键部分。随后攻击者将内容发送出去,恶意的 SQL 语句便会在数据库中被执行。

    SQL 是一种用于管理关系型数据库中数据的查询语言。你能使用它进行查询、修改和删除数据。很多网站或应用程序将所有数据都存储在 SQL 数据库。有时候,你也可以使用 SQL 指令运行操作系统指令。因此,一次成功的 SQL 注入攻击可能会引起非常严重的后果。

    • 攻击者可利用 SQL 注入,从数据库中得到其他用户的用户凭证。之后他们便能伪装成这些用户。这些用户中甚至有可能包括有所有数据库权限的数据库管理员。
    • SQL 可用于从数据库中选择并输出数据。SQL 注入漏洞允许攻击者访问数据库服务中的所有数据。
    • SQL 也可用于修改数据库中数据,或者添加新数据。例如,在金融产品中,攻击者能利用 SQL 注入修改余额,取消交易记录或给他们的账户转账。
    • SQL 可用于从数据库中删除记录,甚至删除数据表。即使管理员做了数据库备份,在数据库中数据恢复之前,被删除的数据仍然会影响应用的可用性。而且,备份很可能没有覆盖最近的数据。
    • 在某些数据库服务中,可通过数据库服务访问操作系统。这种设计可能是有意的,也可能是无意的。在这种情况下,攻击者将 SQL 注入作为初始手段,进而攻击防火墙背后的内网。

    SQL 注入攻击的类型有:带内 SQL 注入(使用数据库错误或 UNION 指令)、盲目 SQL 注入和带外 SQL 注入。你可在 SQL 注入的类型 和盲目 SQL 注入是什么中了解更多信息。

    为了一步步了解如何发起 SQL 注入攻击和它可能引起的严重后果,可参考运用 SQL 注入:动手实践的例子。

    简单的 SQL 注入例子

    第一个例子非常简单。它展示了攻击者如何利用 SQL 注入漏洞绕过应用安全防护和管理员认证。

    以下脚本是执行在网站服务器上的伪代码。它是通过用户名和密码进行身份认证的简单例子。该例子中数据库有一张名为users的表,该表中有两列数据:username和password。

    # 定义 POST 变量
    uname = request.POST['username']
    passwd = request.POST['password']
    
    # 存在 SQL 注入漏洞的 SQL 查询语句
    sql = “SELECT id FROM users WHERE username=’” + uname + “’ AND password=’” + passwd + “’”
    
    # 执行 SQL 语句
    database.execute(sql)

    这些输入字段是容易遭受 SQL 注入攻击的。攻击者能够在输入字段中利用 SQL 指令,修改数据库服务执行的 SQL 语句。比如,他们可使用含有单引号的把戏,将password字段设置为:

    password' OR 1=1

    因此,数据库服务将执行以下 SQL 查询:

    SELECT id FROM users WHERE username='username' AND password='password' OR 1=1'

    由于OR 1=1语句,无论username和password是什么,WHERE分句都将返回users表中第一个id。数据库中第一个用户的id通常是数据库管理员。通过这种方式,攻击者不仅绕过了身份认证,而且还获得了管理员权限。他们也可以通过注释掉 SQL 语句的后续部分,进一步控制 SQL 查询语句的执行:

    -- MySQL, MSSQL, Oracle, PostgreSQL, SQLite
    ' OR '1'='1' --
    ' OR '1'='1' /*
    -- MySQL
    ' OR '1'='1' #
    -- Access (using null characters)
    ' OR '1'='1' %00
    ' OR '1'='1' %16

    基于合并查询的 SQL 注入例子

    使用 UNION 操作符是最常见的 SQL 注入类型之一。它允许攻击者将两个或更多个 SELECT 语句的查询结果合并为一个结果。这种技术被称为基于合并查询的 SQL 注入。

    以下是这种注入攻击的一个例子。该例子在testphp.vulnweb.com网页上进行,该网页是 Acunetix 维护的故意存在漏洞的网站。(译者注:可以跟着该例子在 testphp.vulnweb.com 站点体验 SQL 注入攻击的过程。)

    以下 HTTP 请求是一位用户发送的合法正常请求:

    GET http://testphp.vulnweb.com/artists.php?artist=1 HTTP/1.1
    Host: testphp.vulnweb.com

    HTTP request a legitimate user would send

    artist参数容易受到 SQL 注入攻击。以下的载体修改了该参数,希望找到某个不存在的记录。它设置该参数的值为-1。当然,它可以是数据库中不存在的任意值。然而,负数往往是个好主意,因为数据库中的 id 很少会是负数。

    在 SQL 注入攻击中,UNION操作符通常被用于在原始查询语句中,附加恶意的 SQL 查询语句,网站服务将执行所有查询语句。注入的查询语句的结果将和原始查询语句的结果合并。这样攻击者便可以得到其他数据表中的数据。(译者注:这步是为了演示当 UNION 之后的语句为SELECT 1, 2, 3时,页面将输出 2 和 3。)

    GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1, 2, 3 HTTP/1.1
    Host: testphp.vulnweb.com

    SQL injection using the UNION operator

    接下来的例子展示了在这个存在漏洞的网站中,如何修改 SQL 注入的载体并得到有意义的数据:

    GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1,pass,cc FROM users WHERE uname='test' HTTP/1.1
    Host: testphp.vulnweb.com

    使用 UNION 运算符和 FROM 进行 SQL 注入

    如何防止 SQL 注入

    防止 SQL 注入唯一可靠的方式是验证输入和参数化查询,参数查询包括预准备的查询语句(译者注:指存储过程)。网站应用不应该在代码中直接使用用户输入。开发者必须检查所有用户输入,而不是仅检查网页表单中的输入,比如登录表单。他们必须移除潜在的恶意代码因素,比如单引号。在你的线上环境中屏蔽数据库错误也是个好主意。因为结合数据库错误,SQL 注入攻击将获得更多数据库相关信息。

    如果你使用 Acunetix 扫描器发现了 SQL 注入漏洞,你可能不能立即修复它。比如,这个漏洞可能存在开源代码中。在这种情况下,你可以临时使用网站防火墙对输入进行校验。

    参考在 PHP 应用中防止 SQL 注入漏洞并修复它们,了解在 PHP 语言中如何防止 SQL 注入攻击。参考 Bobby Tables 教你阻止 SQL 注入攻击,查找如何在其他编程语言中预防 SQL 注入攻击。

    如何预防 SQL 注入——通用技巧

    预防 SQL 注入攻击并不容易。特定的预防技术与 SQL 注入漏洞的子类型、SQL 数据库引擎和编程语言有关。尽管如此,你仍然可以遵循一些通用策略来确保网站安全。

    第一步:培养并保持安全意识

    为了保证你的网站安全,所有参与搭建该网站的人员都必须意识到 SQL 注入漏洞相关的风险。你应该为所有开发者、测试员工、运维员工和系统管理员提供适量的安全培训。你可以让他们参考这篇文章作为安全培训的开始。

    第二步:不要信任任何用户输入

    将所有用户输入都看作不可信的。任何被用作 SQL 查询的用户输入都有 SQL 注入攻击的风险。对待授权用户或内部员工的输入,也应该像对待外部用户输入一样,将其视为不可信。

    第三步:使用白名单,而不是黑名单

    不要基于黑名单过滤用户输入。因为聪明的攻击者总是能找到绕过黑名单的方法,所以应尽可能只使用严格的白名单,对用户输入进行验证和过滤。

    第四步:采用最新的技术

    更老的网站开发技术没有防止 SQL 注入攻击的保护机制。尽量使用最新版本的开发环境和开发语言,并使用与它们相关的新技术。例如,在 PHP 中应使用 PDO 而不是 MySQLi。

    第五步:采用经过验证的机制

    不要尝试从零开始建立应对 SQL 注入攻击的防护机制。大多数现代开发技术已经为你提供了预防 SQL 注入攻击的机制。你应该使用这些已有的技术,而不是尝试重新造轮子。比如,使用参数化查询和存储过程(stored procedure)。

    第六步:周期性扫描

    SQL 注入漏洞可能被开发者引入,也可能被外部库、模块或软件引入。你应该使用网站漏洞扫描器(比如 Acunetix)周期性扫描你的网站。如果你使用 Jenkins,你可以安装 Acunetix 插件,实现每次构建时进行自动扫描。

    请各位大牛以不参与,不破坏,不违法为第一原则

    展开全文
  • Sql攻击与防御

    2012-11-25 06:35:53
    经典的sql注入分析,从如何注入和如何防止注入两方面深入说明sql injection技术。
  • DVWA SQL注入攻击

    千次阅读 2022-02-28 16:41:10
    Dvwa sql注入实现

    SQL注入原理

    SQL注入就是通过SQL命令插入到web表单递交或输入域名页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将恶意的SQL命令注入到后台数据库引擎执行的能力,它可以通过在WEB表单中输入恶意SQL语句得到包含漏洞的网站数据库,而不是按照设计者意图去执行。

    SQL注入类型

    按照数据提交的方式:
    GET注入、POST注入、COOKIE注入、HTTP头部注入
    按照注入点类型来分:
    数据型注入点、字符型注入点、搜索性注入点
    按照执行效果来分:
    基于布尔的盲注、基于时间的盲注、基于报错注入、联合查询注入、堆叠注入、宽字节注入

    DVWA-SQL注入-Low

    首先注入单引号'来查看是否有注入点,报错后说明有注入点

    然后判断有几个字段  ' union select 1 -- yy   报错表明字段不匹配

    ' union select 1,2 -- yy   说明有俩字段

     

     后面我们就可以在information_schema 中查看我们想看的东西了

    ' union select table_name,1 from information_schema.tables -- yy  这句话会报错,在网上查完是因为字符编码不一样导致的,可以在数据库中直接改,也可以用hex编码一下,后面再利用在线工具解码

     ' union select hex(table_name),1 from information_schema.tables -- yy

    DVWA-SQL注入-Medium

    在Medium下我们需要用burp suite抓包改包上传,先开启代理模式,点击提交让burp suite抓包

    把id那里修改后上传

    返回错误

     然后把id改成 1 or 1=1 #

    查询成功,所以为数字注入

    接下来猜有几个字段 1 order by 2 #

    1 order by 3 # 报错,说明只有2字段

     

     获取数据库

     后面就可以获取自己想要的信息

    DVWA-SQL注入-High

    high级别下跟low级别差不多,开头用1' or 1=1 #就可以

     

    展开全文
  • SQL注入攻击与防御》PDF版本下载
  • 模拟数据库Sql攻击,条件是两台机子都安装SqlServer2005,局域网最好,知道对方IP,内置JavaBean生成器。
  • SQL攻击(SQLinjection,台湾称作SQL资料隐码攻击),简称注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令...
  • SQL注入攻击详解

    千次阅读 2020-12-21 18:03:18
    SQL 注入(SQLi)是一种注入攻击,,可以执行恶意 SQL 语句。它通过将任意 SQL 代码插入数据库查询,使攻击者能够完全控制 Web 应用程序后面的数据库服务器。攻击者可以使用 SQL 注入漏洞绕过应用程序安全措施;可以...
  • 许多年以前,SQL注入攻击即将消失的消息不绝于耳,但无数个事实告诉我们,SQL注入攻击还没有离我们远去。 近几年SQL注入事件少了很多,不是开发人员意识提高,也不是预编译的推广见成效,而是各种框架的流行和推广...
  • (1)主演示就是一张t_user表,利用常见的用户登录来模拟sql注入对后台数据的侵入 (2)数据库脚本 — postgresql DROP TABLE IF EXISTS "public"."t_user"; CREATE TABLE "public"."t_user" ( "id" int8 NOT ...
  • 在所有注入类型中,SQL注入是最常见的攻击手段之一,而且是最危险的。由于Python是世界上最流行的编程语言之一,因此了解如何防止Python SQL注入对于我们来说还是比较重要的 那么在写这篇文章的时候我也是查询了国内...
  • 基于joomlad的SQL注入攻击SQL注入攻击是:黑客对数据库进行攻击的常用手段之一。随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。相当大一部分程序员在编写代码的时候,没有对用户输入...
  • SQL注入攻击与防御 第2版》PDF版本下载
  • 主要原因是程序对用户输入数据的合法性没有判断和处理,导致攻击者可以在 Web 应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权...
  • 如何有效防止SQL注入攻击

    千次阅读 2020-09-14 20:00:00
    SQL注入攻击是黑客对数据库进行攻击常用的手段之一,随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的水平及经验参差不齐,相当大一部分程序员在编写...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 116,249
精华内容 46,499
关键字:

sql攻击