示例 - 存在SQL注入漏洞的代码示例(Multipart传参方式):
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="org.apache.commons.fileupload.FileItemIterator" %><%@ page import="org.apache.commons.fileupload.FileItemStream" %><%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %><%@ page import="org.apache.commons.fileupload.util.Streams" %><%@ page import="java.io.File" %><%@ page import="java.io.FileOutputStream" %><%@ page import="org.apache.commons.fileupload.FileUploadException" %><%@ page import="java.util.Map" %><%@ page import="java.util.HashMap" %><%@ page import="java.sql.DriverManager" %><%@ page import="com.alibaba.fastjson.JSON" %><%@ page import="java.sql.Connection" %><%@ page import="java.sql.ResultSet" %><%@ page import="java.io.IOException" %><%// MYSQL sys_user示例表,测试时请先创建对应的数据库和表//// CREATE TABLE `sys_user` (// `id` int(9) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',// `username` varchar(16) NOT NULL COMMENT '用户名',// `password` varchar(32) NOT NULL COMMENT '用户密码',// `user_avatar` varchar(255) DEFAULT NULL COMMENT '用户头像',// `register_time` datetime DEFAULT NULL COMMENT '注册时间',// PRIMARY KEY (`id`),// UNIQUE KEY `idx_sys_user_username` (`username`) USING BTREE// ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='系统用户表'//// INSERT INTO `sys_user` VALUES ('1', 'admin', '123456', '/res/images/avatar/default.png', '2020-05-05 17:21:27'), ('2', 'test', '123456', '/res/images/avatar/default.png', '2020-05-06 18:27:10'), ('3', 'root', '123456', '/res/images/avatar/default.png', '2020-05-06 18:28:27'), ('4', 'user', '123456', '/res/images/avatar/default.png', '2020-05-06 18:31:34'), ('5', 'rasp', '123456', '/res/images/avatar/default.png', '2020-05-06 18:32:08');%><%!/*** 解析Multipart请求中的参数* @param request* @return*/Map<String, String> parseMultipartContent(HttpServletRequest request) {Map<String, String> dataMap = new HashMap<String, String>();try {ServletFileUpload fileUpload = new ServletFileUpload();FileItemIterator fileItemIterator = fileUpload.getItemIterator(request);while (fileItemIterator.hasNext()) {FileItemStream fileItemStream = fileItemIterator.next();if (fileItemStream.isFormField()) {// 字段名称String fieldName = fileItemStream.getFieldName();// 字段值String fieldValue = Streams.asString(fileItemStream.openStream());dataMap.put(fieldName, fieldValue);}}} catch (Exception e) {e.printStackTrace();}return dataMap;}%><%if (ServletFileUpload.isMultipartContent(request)) {Map<String, String> dataMap = parseMultipartContent(request);String username = dataMap.get("username");String password = dataMap.get("password");// 处理用户登陆逻辑if (username != null && password != null) {ResultSet rs = null;Connection connection = null;Map<String, Object> userInfo = new HashMap<String, Object>();try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaweb-bbs", "root", "root");String sql = "select * from sys_user where username = '" + username + "' and password = '" + password + "'";System.out.println(sql);rs = connection.prepareStatement(sql).executeQuery();while (rs.next()) {userInfo.put("id", rs.getString("id"));userInfo.put("username", rs.getString("username"));userInfo.put("password", rs.getString("password"));userInfo.put("user_avatar", rs.getString("user_avatar"));userInfo.put("register_time", rs.getDate("register_time"));}// 检查是否登陆成功if (userInfo.size() > 0) {// 设置用户登陆信息out.println(JSON.toJSONString(userInfo));} else {out.println("<script>alert('登陆失败,账号或密码错误!');history.back(-1)</script>");}} catch (Exception e) {e.printStackTrace();out.println("<script>alert('登陆失败,服务器异常!');history.back(-1)</script>");} finally {// 关闭数据库连接if (rs != null)rs.close();if (connection != null)connection.close();}}} else {%><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>File upload</title></head><body><form action="" enctype="multipart/form-data" method="post"><p>Username: <input name="username" type="text" value="admin" /><br/>Password: <input name="password" type="text" value="'=0#" /></p><input name="submit" type="submit" value="Submit"/></form></body></html><%}%>
访问示例中的后台登陆地址:http://localhost:8000/modules/jdbc/multipart.jsp,如下图:
提交万能密码'=0#即可绕过登陆验证获取到admin用户信息:
Spring MVC Multipart请求解析示例
import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;import java.util.HashMap;import java.util.Map;import static org.javaweb.utils.HttpServletResponseUtils.responseHTML;/*** Creator: yz* Date: 2020-05-04*/@Controller@RequestMapping("/SQLInjection/")public class SQLInjectionController {@Resourceprivate JdbcTemplate jdbcTemplate;@RequestMapping("/Login.php")public void login(String username, String password, String action, String formType,HttpServletRequest request, HttpServletResponse response,HttpSession session) throws IOException {String contentType = request.getContentType();String sessionKey = "USER_INFO";Object sessionUser = session.getAttribute(sessionKey);PrintWriter out = response.getWriter();// 退出登陆if (sessionUser != null && "exit".equals(action)) {session.removeAttribute(sessionKey);response.sendRedirect(request.getServletPath() + (formType != null ? "?formType=" + formType : ""));return;}Map<String, Object> userInfo = null;// 检查用户是否已经登陆成功if (sessionUser instanceof Map) {userInfo = (Map<String, Object>) sessionUser;responseHTML(response,"<p>欢迎回来:" + userInfo.get("username") + ",ID:" +userInfo.get("id") + " \r<a href='?action=exit" + (formType != null ? "&formType=" + formType : "") + "'>退出登陆</a></p>");return;}// 处理用户登陆逻辑if (username != null && password != null) {userInfo = new HashMap<String, Object>();try {String sql = "select id,username,password from sys_user where username = '" +username + "' and password = '" + password + "'";System.out.println(sql);userInfo = jdbcTemplate.queryForMap(sql);// 检查是否登陆成功if (userInfo.size() > 0) {// 设置用户登陆信息session.setAttribute(sessionKey, userInfo);String q = request.getQueryString();// 跳转到登陆成功页面response.sendRedirect(request.getServletPath() + (q != null ? "?" + q : ""));} else {responseHTML(response, "<script>alert('登陆失败,账号或密码错误!');history.back(-1)</script>");}} catch (Exception e) {responseHTML(response, "<script>alert('登陆失败,服务器异常!');history.back(-1)</script>");}return;}String multipartReq = "";// 如果传入formType=multipart参数就输出multipart表单,否则输出普通的表单if ("multipart".equals(formType)) {multipartReq = " enctype=\"multipart/form-data\" ";}responseHTML(response, "<html>\n" +"<head>\n" +" <title>Login Test</title>\n" +"</head>\n" +"<body>\n" +"<div style=\"margin: 30px;\">\n" +" <form action=\"#\" " + multipartReq + " method=\"POST\">\n" +" Username:<input type=\"text\" name=\"username\" value=\"admin\"/><br/>\n" +" Password:<input type=\"text\" name=\"password\" value=\"'=0#\"/><br/>\n" +" <input type=\"submit\" value=\"登陆\"/>\n" +" </form>\n" +"</div>\n" +"</body>\n" +"</html>");out.flush();out.close();}}
访问示例中的后台登陆地址:http://localhost:8000/SQLInjection/Login.php?formType=multipart,如下图:
发送Multipart请求,登陆测试Spring MVC:
使用万能密码登陆成功:
Back
