Hello everyone, I am Bucai Chen~
1. XSS cross-site scripting attack
① Introduction to XSS vulnerabilities
Cross-site scripting attack (XSS) refers to an attacker inserting malicious script code into a web page. When a user browses the page, the script code embedded in the web page will be parsed and executed, thereby achieving the purpose of maliciously attacking the user. XSS attacks are aimed at user-level attacks!
② Classification of XSS vulnerabilities
Stored XSS: Stored XSS, persistence, code is stored in the server, such as in personal information or published articles, insert code, if there is no filtering or filtering is not strict, then these codes will be stored in the server, users Trigger code execution when the page is accessed. This kind of XSS is more dangerous, it is easy to cause worms and steal cookies
Reflective XSS: Non-persistent, need to deceive users to click on the link to trigger XSS code (there is no such page and content in the server), generally easy to appear on the search page
DOM-type XSS: DOM-XSS vulnerability is a vulnerability based on the Document Object Model (Document Objeet Model
, DOM) without going through the backend. DOM-XSS is triggered by passing parameters through url , In fact, it is also a reflected XSS.
③ Protection suggestions
-
Restrict user input, form data specifies the value type, for example, age can only be int, and name is a combination of letters and numbers.
-
Perform html encode processing on the data.
-
Filter or remove special html tags.
-
Tags to filter javascript events.
2. SQL injection attack
① SQL injection vulnerability introduction
SQL Injection (SQLi) is an injection attack that executes malicious SQL statements. It gives an attacker full control over the database server behind a web application by inserting arbitrary SQL code into database queries. Attackers can use SQL injection vulnerabilities to bypass application security measures; they can bypass authentication and authorization of web pages or web applications, and retrieve the contents of the entire SQL database; they can also use SQL injection to add, modify, and delete entries in the database. Record; pay attention to the official account: code ape technology column, reply keywords: 1111 Get Ali’s internal Java performance optimization manual!
SQL injection vulnerabilities can affect any website or web application that uses a SQL database such as MySQL, Oracle, SQL Server or others. Criminals may use it to gain unauthorized access to users’ sensitive data: customer information, personal data, trade secrets, intellectual property, etc. SQL injection attacks are one of the oldest, most popular, and most dangerous web application vulnerabilities.
②Protection advice
Using #{}
in mybatis can effectively prevent sql injection.
When using #{}
:
<select id="getBlogById" resultType="Blog" parameterType="int"> select id, title, author, content from blog where id=#{id} </select>
Print out the executed sql statement, and you will see that sql looks like this:
select id,title,author,content from blog where id = ?
No matter what parameters are entered, the printed sql is like this. This is because mybatis has enabled the pre-compilation function. Before the sql is executed, the above sql will be sent to the database for compilation. When executing, directly use the compiled sql and replace the placeholder “?”. Because sql injection can only work on the compilation process, so it is precompiled like #{}? The way to avoid the problem of sql injection is very good.
How does mybatis achieve sql precompilation?
In fact, at the bottom of the framework, the PreparedStatement
class in jdbc works. PreparedStatement
is a subclass of Statement that we are very familiar with. Its objects contain compiled SQL statements . This “ready” method can not only improve security, but also improve efficiency when executing a sql multiple times, because the sql has been compiled and there is no need to recompile it when it is executed again.
When using ${}
<select id="orderBlog" resultType="Blog" parameterType="map"> select id, title, author, content from blog order by ${orderParam} </select>
Observe carefully, the format of the inline parameter has changed from “#{xxx}
” to ${xxx}
. If we assign “id” to the parameter “orderParam
“, the sql will be printed out like this:
select id,title,author,contet from blog order by id
Obviously, SQL injection cannot be prevented in this way, and parameters will directly participate in SQL compilation, so injection attacks cannot be avoided. But when it comes to dynamic table names and column names, only the parameter format “${}
” can be used. Therefore, such parameters need to be processed manually in the code to prevent injection.
In fact, these are all answered in the Java interview library applet. If you are planning to change jobs in the near future, it is recommended to write questions on it, covering 2000+ Java interview questions, covering almost all mainstream technical interview questions.
3. How to prevent XSS attacks and sql injection in SpringBoot
For Xss attacks and Sql injections, we can handle them through filters, which can exclude some requests according to business needs
① Create Xss request filter class XssHttpServletRequestWraper
code show as below:
public class XssHttpServletRequestWraper extends HttpServletRequestWrapper { Logger log = LoggerFactory. getLogger(this. getClass()); public XssHttpServletRequestWraper() { super(null); } public XssHttpServletRequestWraper(HttpServletRequest httpsservletrequest) { super(httpservletrequest); } //Filter the parameters in the @RequestParam annotation in springmvc public String[] getParameterValues(String s) { String str[] = super. getParameterValues(s); if (str == null) { return null; } int i = str. length; String as1[] = new String[i]; for (int j = 0; j < i; j ++ ) { //System.out.println("getParameterValues:" + str[j]); as1[j] = cleanXSS(cleanSQLInject(str[j])); } log.info("XssHttpServletRequestWraper purified request: ==========" + as1); return as1; } //Filter the parameters of request.getParameter public String getParameter(String s) { String s1 = super. getParameter(s); if (s1 == null) { return null; } else { String s2 = cleanXSS(cleanSQLInject(s1)); log.info("XssHttpServletRequestWraper purified request: ==========" + s2); return s2; } } //Filter the request body in json format @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super. getInputStream ()). getBytes ()); return new ServletInputStream() { @Override public int read() throws IOException { return bais. read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } public String inputHandlers(ServletInputStream servletInputStream){ StringBuilder sb = new StringBuilder(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset. forName("UTF-8"))); String line = ""; while ((line = reader. readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (servletInputStream != null) { try { servletInputStream. close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader. close(); } catch (IOException e) { e.printStackTrace(); } } } return cleanXSS(sb.toString()); } public String cleanXSS(String src) { String temp = src; src = src.replaceAll("<", "<").replaceAll(">", ">"); src = src. replaceAll("\(", "("). replaceAll("\)", ")"); src = src. replaceAll("'", "'"); src = src.replaceAll(";", ";"); //bgh 2018/05/30 Added /**-----------------------start----------------------- ---*/ src = src. replaceAll("<", " & amp; lt;"). replaceAll(">", " & amp; gt;"); src = src. replaceAll("\(", " & amp; #40;"). replaceAll("\)", " & amp; #41"); src = src.replaceAll("eval\((.*)\)", ""); src = src.replaceAll("["\'][\s]*javascript:(.*)["\']", """"); src = src. replaceAll("script", ""); src = src. replaceAll("link", ""); src = src. replaceAll("frame", ""); /**-----------------------end----------------------- ---*/ Pattern pattern = Pattern.compile("(eval\((.*)\)|script)", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern. matcher(src); src = matcher. replaceAll(""); pattern = Pattern.compile("["'][\s]*javascript:(.*)["']", Pattern.CASE_INSENSITIVE); matcher = pattern. matcher(src); src = matcher. replaceAll(""""); // add script src = src.replaceAll("script", "").replaceAll(";", "") /*.replaceAll(""", "").replaceAll("@", "")*/ .replaceAll("0x0d", "").replaceAll("0x0a", ""); if (!temp. equals(src)) { // System.out.println("There is an xss attack in the input information!"); // System.out.println("Original input information -->" + temp); // System.out.println("Processed information -->" + src); log.error("xss attack check: the parameter contains illegal attack characters, further access is prohibited!!"); log.error("Original input information -->" + temp); throw new CustomerException("xss attack check: the parameter contains illegal attack characters, further access is prohibited!!"); } return src; } // output public void outputMsgByOutputStream(HttpServletResponse response, String msg) throws IOException { ServletOutputStream outputStream = response.getOutputStream(); //Get the output stream response.setHeader("content-type", "text/html;charset=UTF-8"); //Control the browser to display data in UTF-8 encoding by setting the response header. If you do not add this sentence, then browse The display will be garbled byte[] dataByteArr = msg.getBytes("UTF-8");// Convert characters into byte arrays, specifying UTF-8 encoding for conversion outputStream.write(dataByteArr);//Use the OutputStream stream to output the byte array to the client } // Need to add wildcards to filter case combinations public String cleanSQLInject(String src) { String lowSrc = src.toLowerCase(); String temp = src; String lowSrcAfter = lowSrc. replaceAll("insert", "forbidI") .replaceAll("select", "forbidS") .replaceAll("update", "forbidU") .replaceAll("delete", "forbidD").replaceAll("and", "forbidA") .replaceAll("or", "forbidO"); if (!lowSrcAfter. equals(lowSrc)) { log.error("sql injection check: there is a SQL attack in the input information!"); log.error("Original input information -->" + temp); log.error("Post-processing information -->" + lowSrc); throw new CustomerException("sql injection check: the parameter contains illegal attack characters, further access has been prohibited!!"); } return src; } }
② Add the request filter class XssHttpServletRequestWraper
to Filter and inject it into the container
@Component public class XssFilter implements Filter { Logger log = LoggerFactory. getLogger(this. getClass()); // The url address that ignores the permission check private final String[] excludeUrls = new String[]{ "null" }; public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; String pathInfo = req. getPathInfo() == null ? "" : req. getPathInfo(); // Get the last two layers of the request url String url = req. getServletPath() + pathInfo; // Get all the paths after requesting your ip String uri = req. getRequestURI(); //Inject xss filter instance XssHttpServletRequestWraper reqW = new XssHttpServletRequestWraper(req); //Filter out the addresses of unnecessary Xss checks for (String str : excludeUrls) { if (uri. indexOf(str) >= 0) { arg2. doFilter(arg0, response); return; } } //filter arg2. doFilter(reqW, response); } public void destroy() { } public void init(FilterConfig filterconfig1) throws ServletException { } }
The above code can already complete the filtering of request parameters and JSON request body, but there are other ways to realize the JSON request body. If you are interested, please see the extension below!
Extension: You can also rewrite the MappingJackson2HttpMessageConverter
in spring to filter the Json request body
Because the request body will go through a conversion of MappingJackson2HttpMessageConverter
when it enters and exits Contoroller to convert the request body into the json format we need, so you can make some modifications here!
@Configuration public class MyConfiguration { @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){ //custom converter MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); //converter date format setting ObjectMapper objectMapper = new ObjectMapper(); SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); objectMapper.setDateFormat(smt); converter.setObjectMapper(objectMapper); //The converter adds a custom Module extension, mainly for XSS filtering here! ! , the others are other businesses, don’t look at them SimpleModule simpleModule = new SimpleModule(); //Add filtering logic class! simpleModule. addDeserializer(String. class, new StringDeserializer()); converter.getObjectMapper().registerModule(simpleModule); //Set the Chinese encoding format List<MediaType> list = new ArrayList<>(); list.add(MediaType.APPLICATION_JSON_UTF8); converter.setSupportedMediaTypes(list); return converter; } }
The real filtering logic class StringDeserializer
:
//Check the parameters of the request body @Component public class StringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { String str = jsonParser.getText().trim(); //sql injection interception if (sqlInject(str)) { throw new CustomerException("The parameter contains illegal attack characters, and further access is prohibited!"); } return xssClean(str); } public boolean sqlInject(String str) { if (StringUtils. isEmpty(str)) { return false; } //Remove the '|"|;|\ character str = org.apache.commons.lang3.StringUtils.replace(str, "'", ""); str = org.apache.commons.lang3.StringUtils.replace(str, """, ""); str = org.apache.commons.lang3.StringUtils.replace(str, ";", ""); str = org.apache.commons.lang3.StringUtils.replace(str, "", ""); // convert to lowercase str = str.toLowerCase(); //Invaild symbol String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alert", "alter", "drop"}; //Check if it contains illegal characters for (String keyword : keywords) { if (str. indexOf(keyword) != -1) { return true; } } return false; } //xss attack interception public String xssClean(String value) { if (value == null || "".equals(value)) { return value; } //Invaild symbol String[] keywords = {"<", ">", "<>", "()", ")", "(", "javascript:", "script", "alter", "''", "'"}; //Check if it contains illegal characters for (String keyword : keywords) { if (value. indexOf(keyword) != -1) { throw new CustomerException("The parameter contains illegal attack characters, and further access is prohibited!"); } } return value; } }
Using this form can also complete the filtering of the json request body, but personally recommend using the form of XssHttpServletRequestWraper
to complete the xss filtering! !
One last sentence (don’t prostitute, please pay attention)
Every article by Chen is carefully output. If this article is helpful or inspiring to you, please like, watch, repost, and bookmark. Your support is the biggest motivation for me to persevere!
In addition, Chen’s Knowledge Planet has been opened, and the official account replies to the key words: Knowledge Planet is limited to 30 yuan coupons to join, only 89 yuan, a meal, but the value of the planet’s feedback is huge. Currently, the Spring Family Bucket has been updated. Series, 100 million-level data sub-database sub-table actual combat, DDD micro-service actual combat column, I want to enter the big factory, Spring, Mybatis and other framework source code, architecture actual combat 22 lectures, etc. The price will increase by 20 yuan for each additional column
Follow the official account: [Code Ape Technology Column], there are awesome fan benefits in the official account, reply: join the group, you can join the technical discussion group, discuss technology with everyone, and brag!