示例 - 存在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 {
@Resource
private 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