闭关修炼(二十五)基础web安全

不是特别难,主要是积累经验

赶紧学springboot去了,好拖延啊。捂脸



常见的攻击有哪些?

SQL注入,XSS,CSRF(和表单重复提交是一个类型)

最基本的WEB安全防范:密码设为英文+数字+特殊符号,访问白名单

表单重复提交

表单重复提交十分常见,

表单重复提交主要原因是网络延迟

简单的处理办法是前端使用token

但是无法防止模拟http请求

先模拟问题发生

写一个form.jsp

<html>
  <head>
    <title>$form$</title>
  </head>
  <form action="${pageContext.request.contextPath}/DoFormServlet" method="post">
    用户名:<input type="text" name="userName">
    <input type="submit" value="提交" id="submit">
  </form>
  <body>
  </body>
</html>

写个servlet用于调用

@WebServlet("/DoFormServlet")
public class DoFormServlet extends HttpServlet {
    @SneakyThrows
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("userName");
        Thread.sleep(3000);
        System.out.println("插入数据..");
        resp.getWriter().println("success");
    }
}

启动页面
在这里插入图片描述
输入123提交,Thread.sleep(3000);延迟了3秒,模拟网络延迟,页面不会立即进行跳转,这时就可以多次点击点击提交按钮,造成表单重复提交

在这里插入图片描述
后台打印
在这里插入图片描述

前端解决方法

提交后,按钮变灰,多一个标识判断,这种做法可以,但是有局限性,不能防止刷新重新加载的重复提交

<html>
<head>
    <title>form</title>
</head>

<script type="text/javascript">
    let submitFlag = false // 没有点击为false
    function isNoSubmit() {
        // 还没提交返回true
        if (!submitFlag) {
            submitFlag = true
            return true
        }
        // 提交了返回false
        return false
    }

</script>
<form action="${pageContext.request.contextPath}/DoFormServlet"
      method="post"
      onsubmit="return isNoSubmit()">

    用户名:<input type="text" name="userName"/>
    <input type="submit" value="提交" id="submit"/>

</form>
<body>
</body>
</html>

使用token来解决

token身份令牌,证明有效期和身份

思路:
请求一个Sevlet生成token存放在session中,转发到form.jsp,此时jsp携带一个token并附着表单进行提交,到DoFormServlet,判断token是否有效,DoFormServlet判断步骤如下:

  1. 如果从session中获取到的token,和表单发来的一致,说明是第一次的发来请求,处理业务完毕后删除sessiom的token,表示这个token已失效。

  2. 如果seesion中没有这个token,说明token已经被用过了。

  3. 如果传来的token为空或者和session的token不一致,说明被恶意伪造了token

写ToFromServlet生成token并作转发

@WebServlet("/ToFromServlet")
public class ToFromServlet extends HttpServlet {
    @SneakyThrows
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String token = UUID.randomUUID().toString();
        System.out.println("生成Token:"+token);
        req.getSession().setAttribute("sessionToken", token);
        req.getRequestDispatcher("form.jsp").forward(req, resp);
    }
}

修改form.jsp,添加一个hidden域

<html>
<head>
    <title>form</title>
</head>

<script type="text/javascript">
    let submitFlag = false // 没有点击为false
    function isNoSubmit() {
        // 还没提交返回true
        if (!submitFlag) {
            submitFlag = true
            return true
        }
        // 提交了返回false
        return false
    }

</script>

<form action="${pageContext.request.contextPath}/DoFormServlet"
      method="post"
      onsubmit="return isNoSubmit()">
        <input type="hidden" value="${sessionToken}" name="sessionToken">
    用户名:<input type="text" name="userName"/>
    <input type="submit" value="提交" id="submit"/>

</form>
<body>
</body>
</html>

最后在doFormServlet添加session判断

@WebServlet("/DoFormServlet")
public class DoFormServlet extends HttpServlet {
    @SneakyThrows
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (!isFlag(req,resp)){
            resp.getWriter().println("fail");
            System.out.println("已经提交了...");
            return;
        }

        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("userName");
        Thread.sleep(3000);
        System.out.println("插入数据..");
        resp.getWriter().println("success");
    }

    public boolean isFlag(HttpServletRequest req, HttpServletResponse resp){
        String sessionToken = req.getParameter("sessionToken");
        String sessionToken1 = (String) req.getSession().getAttribute("sessionToken");
        if(StringUtils.isNullOrEmpty(sessionToken)){
            System.out.println("sessionToken为null");
            return false;

        }
        if (StringUtils.isNullOrEmpty(sessionToken1)){
            System.out.println("sessionToken1为null");
            return false;

        }
        if(!sessionToken1.equals(sessionToken)){
            System.out.println("伪造token");
            return false;
        }

        req.getSession().removeAttribute("sessionToken");
        return true;

    }
}

访问/ToFromServlet即可

测试,后台打印:
在这里插入图片描述

接口如何防止模拟http请求

带上token,保证唯一性,难以伪造。但是生成token方式可以破解的,还是可以模拟请求,这时如何解决呢?

使用验证码,证明自己不是机器人

token+验证码完整解决防止模拟请求

使用Filter防止XSS攻击

什么是XSS攻击?
XSS也叫脚本注入

XXSS攻击常发生在:有个表单在页面中,当提交时,参数提交,让数据展示在页面时,突然弹窗或者页面发生了跳转

如我注入的内容是location.href,当你访问一个页面立马跳转到钓鱼网站了,用户登陆界面完全一样。(我全防去出去了啊)

模拟XSS攻击

我们写脚本进行注入
在这里插入图片描述
一点提交就弹窗
在这里插入图片描述
想想如果这个脚本是在留言区/评论区的话,别的用户点进来就被弹窗。

XSS页面跳转也写进来

<script>alert('攻击成功');window.location.href='http://www.baidu.com';</script>"

别人在一个页面访问好端端,然后突然跳转到了登陆界面,界面一模一样,这就是钓鱼网站攻击,也是XSS的一种

如何防范?

原理是XSS的标签被html解析了,我们转义标签即可。

继承HttpServletRequest重写getParameter方法

public class XssHttpServletRequest extends HttpServletRequestWrapper {
    HttpServletRequest request;

    public XssHttpServletRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    @Override
    public String getParameter(String name) {
        String value = request.getParameter(name);
        if (!StringUtils.isEmpty(value)){
            value = StringEscapeUtils.escapeHtml4(value);
        }
        return value;
    }
}

写Filter,将我们的XssHttpServletRequest传过去,这样getParameter会转义字符

@WebFilter(filterName = "XSSFilter", urlPatterns = { "/*" })
public class XSSFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        XssHttpServletRequest xssHttpServletRequest = new XssHttpServletRequest(req);
        chain.doFilter(xssHttpServletRequest, response);

    }

    public void destroy() {

    }
}

再次测试,这样<>就被转义了,破坏了标签
在这里插入图片描述

SQL注入

没啥好讲的了,

有那么几种办法防范:
1、PreparedStatement
2、使用正则表达式过滤传入的参数
3、字符串过滤
4、检查是否包函非法字符


然后他啪的一下就站起来了啊,很快啊,然后上来就是一个端口扫描,一个密码暴力破解,一个大杀四方。我全都防出去,防出去了,啊。防出去了以后自然是传统以点到为止,我大意了啊,没有闪。

后面开个新专栏吧,闭关修炼专栏这都到25了都。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值