(一) 安全问题描述
发送了两次合法的登录尝试,并且在其间发送了几次错误的登录尝试。最后一个响应与第一个响应相同。这表明存在未充分实施帐户封锁的情况,从而使登录页面可能受到蛮力攻击
解决方案
效果,当用户登录错误3次,则提醒30分钟后才可再次登录
if(!checkLock(session, username)) {
System.out.println("该账号已经被锁定");
return "该账号已经被锁定";
}
if (username=="小一"&&password=="1234"){
//登录成功
System.out.println("登录成功");
User user=new User();
user.setUsername(username);
user.setPassword(password);
System.out.println("登录成功");
cleanFailNum(request.getSession(),username);//清空该用户之前登录的错误信息
return "登录成功";
}else {
addFailNum(session,username);//错误信息加一
return "用户名或者密码错误";
}
/**
* 校验用户登录失败次数
* @param session
* @param username
* @return
*/
public boolean checkLock(HttpSession session,String username) {
Object o = session.getServletContext().getAttribute(username);
if(o==null) {
return true;
}
HashMap
int num = (int) map.get("num");
Date date = (Date) map.get("lastDate");
long timeDifference = ((new Date().getTime()-date.getTime())/60/1000);
if(num>&#61;3&&timeDifference<30) {
return false;
}
return true;
}
/**
* 新增用户登录失败次数
* &#64;param session
* &#64;param username
*/
public void addFailNum(HttpSession session, String username) {
Object o &#61; session.getServletContext().getAttribute(username);
HashMap
int num&#61; 0;
if(o&#61;&#61;null) {
map &#61; new HashMap
}else {
map &#61; (HashMap
num &#61; (int) map.get("num");
Date date &#61; (Date) map.get("lastDate");
long timeDifference &#61; ((new Date().getTime()-date.getTime())/60/1000);
if(timeDifference>&#61;30) {
num&#61;0;
}
}
map.put("num", num&#43;1);
map.put("lastDate", new Date());
session.getServletContext().setAttribute(username, map);
}
/**
* 清理用户登录失败的记录
* &#64;param session
* &#64;param username
*/
public void cleanFailNum(HttpSession session, String username) {
session.getServletContext().removeAttribute(username);
}
2.会话标识未更新
安全规范要求
COOKIE中的登陆前JSESSIONID与登陆后JESSIONID不能相同。&#xff08;只有J2EE应用服务器为JESSIONID,其他应用服务器可能不同&#xff09;
简单理解就是登录前和登录后的sessionId要更新
方式一&#xff1a;在登录页面操作
<%
//登录之后更改会话标识符
request.getSession().invalidate();//清空session
COOKIE COOKIE &#61; request.getCOOKIEs()[0];//获取COOKIE
COOKIE.setMaxAge(0);//s让COOKIE过期
%>
方式二&#xff1a;登录方法中头加入操作
session.invalidate();
3.跨站点请求伪造
import org.apache.logging.log4j.core.config.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* &#64;author lhl
* &#64;version 1.0
* &#64;date 2020/5/6 16:47
* &#64;description TODO 拦截跨站点请求伪造
*/
&#64;Order(1)
&#64;WebFilter(filterName &#61; "CSRFFilter", urlPatterns &#61; "/*")
public class CSRFFilter implements Filter {
&#64;Override
public void init(FilterConfig filterConfig) throws ServletException {
}
&#64;Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;CSRFFilter&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");
HttpServletRequest req &#61; (HttpServletRequest) request;
HttpServletResponse resp &#61; (HttpServletResponse) response;
if (checkReferer(req, resp)) {
// 拦截
response.setContentType("text/html;charset&#61;utf-8");
// resp.sendRedirect("/login.jsp");
throw new ServletException("非法请求&#xff01;");
// return;
}
// 放行
chain.doFilter(req, resp);
}
private boolean checkReferer(HttpServletRequest request, HttpServletResponse response) {
String referer &#61; request.getHeader("referer");
String serviceName &#61; request.getServerName();
if (null &#61;&#61; referer) {
return false;
}
if (referer !&#61; null && referer.matches("^(http|https)&#43;://(" &#43; serviceName &#43; ")(.*)")) {
// 本系统的访问 直接放行
return false;
}
if (referer !&#61; null && referer
.matches("^[(http)|(https)]&#43;://(localhost|10\\.|172\\.|127\\.0\\.0\\.1)&#43;(.*)")) {
// 内网的访问 直接放行
return false;
}
return true;
}
&#64;Override
public void destroy() {
}
}
4.“Content-Security-Policy”头缺失或不安全
解决方案1
中间件为IIS&#xff0c;网站根目录下找到“web.cofig”文件&#xff0c;没有则新建该文件。复制以下代码&#xff0c;粘贴到web.cofig文件中&#xff08;新建全部复制&#xff0c;已有复制system.webserver&#xff09;
解决方案2
HTML前端解决方法&#xff1a;
解决方案1.
中间件为IIS&#xff0c;网站根目录下找到“web.cofig”文件&#xff0c;没有则新建该文件。复制以下代码&#xff0c;粘贴到web.cofig文件中&#xff08;新建全部复制&#xff0c;已有复制system.webserver&#xff09;
解决方案2.
HTML前端解决方法&#xff1a;
6.“X-XSS-Protection”头缺失或不安全
解决方案1.
中间件为IIS&#xff0c;网站根目录下找到“web.cofig”文件&#xff0c;没有则新建该文件。复制以下代码&#xff0c;粘贴到web.cofig文件中&#xff08;新建全部复制&#xff0c;已有复制system.webserver&#xff09;
HTML前端解决方法&#xff1a;
检测到目标URL存在电子邮件地址模式
Spambot 搜寻因特网站点&#xff0c;开始查找电子邮件地址来构建发送自发电子邮件&#xff08;垃圾邮件&#xff09;的邮件列表。
如果检测到含有一或多个电子邮件地址的响应&#xff0c;可供利用以发送垃圾邮件。
而且&#xff0c;找到的电子邮件地址也可能是专用电子邮件地址&#xff0c;对于一般大众应是不可访问的。
解决方案
从 Web 站点中除去任何电子邮件地址&#xff0c;使恶意的用户无从利用。
项目扫描遇到“内部IP暴露”漏洞&#xff0c;关于该漏洞的含义大家自行百度。
考虑的解决方法就是限制IP直接访问项目本身。具体做法如下&#xff1a;
项目是部署在Tomcat中&#xff0c;直接通过修改Tomcat配置文件中的server.xml实现。
初始配置为&#xff1a;
xmlValidation&#61;"false" xmlNamespaceAware&#61;"false">
修改为
xmlValidation&#61;"false" xmlNamespaceAware&#61;"false">
defaultHost是默认的&#xff0c;随便写点都行&#xff0c;应该是在域名无法发生作用的时候访问的。
通过上述配置&#xff0c;就可以实现禁止IP直接访问项目。
若完善一些&#xff0c;可以再配置一个Host&#xff0c;将IP访问指向特定的页面进行说明。
文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器上&#xff0c;当开发者没有对该文件进行合理的校验及处理的时候&#xff0c;很有可能让程序执行这个上传文件导致安全漏洞。大部分网站都会有文件上传的功能&#xff0c;例如头像、图片、视频等&#xff0c;这块的逻辑如果处理不当&#xff0c;很容易触发服务器漏洞
防御方法
防范文件上传漏洞常见的几种方法。
1、文件上传的目录设置为不可执行
2、判断文件类型
在判断文件类型时&#xff0c;可以结合使用MIME Type、后缀检查等方式。在文件类型检查中&#xff0c;强烈推荐白名单方式&#xff0c;黑名单的方式已经无数次被证明是不可靠的。此外&#xff0c;对于图片的处理&#xff0c;可以使用压缩函数或者resize函数&#xff0c;在处理图片的同时破坏图片中可能包含的HTML代码。
3、使用随机数改写文件名和文件路径
文件上传如果要执行代码&#xff0c;则需要用户能够访问到这个文件。在某些环境中&#xff0c;用户能上传&#xff0c;但不能访问。如果应用了随机数改写了文件名和路径&#xff0c;将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件&#xff0c;都将因为重命名而无法攻击。
4、单独设置文件服务器的域名
由于浏览器同源策略的关系&#xff0c;一系列客户端攻击将失效&#xff0c;比如上传crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决。
已解密的登录请求
【原因】
经过实验测试&#xff0c;认为是页面input 标签type&#61;"password" 导致的&#xff0c;
如果 改成type&#61;"text"是可以绕过漏洞扫描的&#xff0c;但是密码框的内容要自己隐藏&#xff0c;出现诸多业务bugs。
【解决】在原来的上面加多一个
&#96;
可能会在 Web 服务器上运行远程命令。这通常意味着完全破坏服务器及其内容
原因&#xff1a;未对用户输入正确执行危险字符清理
XSS跨站脚本攻击&#xff1a;两种情况。一种通过外部输入然后直接在浏览器端触发&#xff0c;即反射型XSS&#xff1b;还有一种则是先把利用代码保存在数据库或文件中&#xff0c;当web程序读取利用代码并输出在页面上时触发漏洞&#xff0c;即存储型XSS。DOM型XSS是一种特殊的反射型XSS。
危害&#xff1a;前端页面能做的事它都能做。&#xff08;不仅仅盗取COOKIE、修改页面等&#xff09;
&#xff08;1&#xff09; 特殊字符HTML实体转码。最好的过滤方式是在输出和二次调用的时候进行加HTML实体一类的转码&#xff0c;防止脚本注入。
&#xff08;2&#xff09; 标签事件属性黑名单。特殊字符容易被绕过&#xff0c;所以还得加标签事件得黑名单或者白名单&#xff0c;这里推荐使用白名单的方式&#xff0c;实现规则可以直接使用正则表达式来匹配&#xff0c;如果匹配到的事件不在白名单列表&#xff0c;就可以直接拦截&#xff0c;而不是过滤为空。
在过滤器中&#xff0c;Http所有请求参数&#xff0c;过滤&#xff0c;去除特殊字符对系统的影响&#xff1b;
&#xff08;1&#xff09;sql注入
&#xff08;2&#xff09;文件参数注入
private String cleanXSS(String value) {
//You&#39;ll need to remove the spaces from the html entities below
value &#61; value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
value &#61; value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
value &#61; value.replaceAll("&#39;", "& #39;");
value &#61; value.replaceAll("eval\\((.*)\\)", "");
value &#61; value.replaceAll("e-xpression\\\\((.*?)\\\\)\"", "");
value &#61; value.replaceAll("[\\\"\\\&#39;][\\s]*Javascript:(.*)[\\\"\\\&#39;]", "\"\"");
value &#61; value.replaceAll("script", "");
//防止sql语句字符注入
String[] sqlStr &#61; {"and", "exec", "execute", "insert", "select", "delete", "update", "count", "drop", "chr", "mid", "master", "truncate", "char", "declare", "sitename", "net user", "xp_cmdshell", "like", "and", "exec", "execute", "insert", "create", "drop", "table", "from", "grant", "use", "group_concat", "column_name", "information_schema.columns", "table_schema", "union", "where", "select", "delete", "update", "order", "by", "count", "chr", "mid", "master", "truncate", "char", "declare", "or"};
for (int i &#61; 0; i
}
//文件参数注入
String[]cmdParameters&#61;{
"cmd.exe","/k","bin","sh",".sh","shell","sleep"
};
for (int i &#61; 0; i
}
return value;
}
更多博客和源码请到微信公众号&#xff1a;源码plus 探索和领取。