Java SQL Inject
JDBC SQL Inject
If the JDBC native query is not precompiled but directly spliced with SQL statements, then the filtering is not strict, which will cause SQL injection problems. For example, the following code is a Demo with SQL injection vulnerabilities
Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/security?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "123456"); String sql = "select * from users where id = '"+id+"'"; resp.getWriter().write("The SQL statement:" + sql + "\n"); Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(sql);
Precompiled repair
Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/security?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "123456"); String sql = "select * from users where id = ?"; PreparedStatement preparedStatement = conn.prepareStatement(sql); preparedStatement.setString(1,id); ResultSet resultSet = preparedStatement.executeQuery();
Mybatis SQL Inject
There are also two methods for Mybatis to execute SQL statements: precompile and direct splicing. If SQL statements are directly spliced and the filtering is not strict, SQL injection problems will occur. For example, the following query statement uses ${} direct splicing value
<select id="selectUserByName" resultType="com.mybatis.pojo.User"> SELECT * FROM Users WHERE username = '${username}' </select>
Using #{} for precompiling can effectively prevent SQL injection problems
<select id="selectUserByName" resultType="com.mybatis.pojo.User"> SELECT * FROM Users WHERE username = '#{username}' </select>
LIKE Query
For the Like query, the program will throw an exception if it is directly precompiled
<select id="selectUserByLikeName" resultType="com.mybatis.pojo.User"> SELECT * FROM Users WHERE username like '%#{username}#' </select>
If developers change to direct value in order to prevent error reporting and do not have enough filtering, SQL injection problems will occur
<select id="selectUserByLikeName" resultType="com.mybatis.pojo.User"> SELECT * FROM Users WHERE username like '%${username}%' </select>
Direct precompiling will report errors, so concat connection precompiling is used, which will not throw exceptions and prevent SQL injection
<select id="selectUserByLikeNameRepair" resultType="com.mybatis.pojo.User"> SELECT * FROM Users WHERE username like concat('%',#{username},'%') </select>
IN/ORDER BY Query
Similarly, the direct precompiling of IN/ORDER BY query will also cause the program to throw exceptions. If the developer constructs SQL statements in the way of direct splicing without sufficient filtering, SQL injection will be generated
JavaWeb Inject Demo : https://github.com/ky0103/JavaSecurityDemo/tree/main/SQLInject
You need to add the Myabtis/JDBC dependency to the WEB-INF/lib directory
Java XSS
In Java, XSS is generally generated by obtaining the parameter value in the Servlet and setting it in the request attribute. The value in the request can be directly referenced in the jsp file. If the parameter value is not filtered, XXS may occur. The following code sets the attribute value without filtering
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); req.setAttribute("username",username); req.getRequestDispatcher("/index.jsp").forward(req,resp); }
XSS defense can take advantage of ESAPI
ESAPI (Enterprise Security API) is a free and open source Web application API, which aims to help developers develop more secure code, and it is easy to call.
rely on
<dependency> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <version>2.2.1.1</version> </dependency>
Use ESAPI to filter before storing the value into the request
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); ESAPI.encoder().encodeForJavaScript(username); req.setAttribute("username",username); req.getRequestDispatcher("/index.jsp").forward(req,resp); }
JavaWeb Inject Demo : https://github.com/ky0103/JavaSecurityDemo/tree/main/XSS
You need to add ESAPI dependencies to the WEB-INF/lib directory
Java SSRF
The SSRF of HttpURLConnection class only supports HTTP/HTTPS protocol, not file and other protocols
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String url = req.getParameter("url"); if (url != null){ URL url1 = new URL(url); String htmlContent; URLConnection urlConnection = url1.openConnection(); HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection; BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); StringBuffer html = new StringBuffer(); while ((htmlContent = bufferedReader.readLine()) != null){ html.append(htmlContent); } bufferedReader.close(); resp.getWriter().println(html); }else { resp.getWriter().write("?url"); } }
URLConnection supports protocols such as HTTP/HTTPS/file
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String url = req.getParameter("url"); if (url != null){ URL url1 = new URL(url); String htmlContent; URLConnection urlConnection = url1.openConnection(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); StringBuffer html = new StringBuffer(); while ((htmlContent = bufferedReader.readLine()) != null){ html.append(htmlContent); } bufferedReader.close(); resp.getWriter().println(html); }else { resp.getWriter().write("?url"); } }
The file download under SSRF is actually to modify the response header
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String fileName = "secret.txt"; resp.setHeader("content-disposition","attachment;fileName="+fileName); String url = req.getParameter("url"); int length; URL u = new URL(url); InputStream inputStream = u.openStream(); byte[] bytes = new byte[1024]; while ((length = (inputStream.read(bytes))) > 0){ resp.getOutputStream().write(bytes,0,length); } }
When reading a file under SSRF, you cannot read a non picture file, but you can detect whether the file exists
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String url = req.getParameter("url"); URL u = new URL(url); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); InputStream inputStream1 = u.openStream(); ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream1); BufferedImage read = ImageIO.read(imageInputStream); ImageIO.write(read,"png",byteArrayOutputStream); InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); int length; byte[] bytes = new byte[1024]; while ((length = (inputStream.read(bytes))) > 0){ resp.getOutputStream().write(bytes,0,length); } }
JavaWeb SSRF Demo : https://github.com/ky0103/JavaSecurityDemo/tree/main/XSS