JavaWeb之会话技术&会话固定攻击

什么是会话跟踪技术

客户向某一个服务器发出第一个请求时,会话就开始了,直到客户关闭了浏览器,会话结束。在这个会话的多个请求中共享数据,这就是会话跟踪技术

类似于你今天拿着银行卡去银行办理业务,今天没有办理完,你明天拿着银行卡(sessionID)过去,银行那边能继续给你办理没有完成的业务,不至于重新开始办理。

起源&发展

HTTP是一种不保存用户状态,即无状态(stateless)的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。(这是为了更快地处理大量事务,确保协议的可伸缩性)
可随着Web的不断发展,因为这种无状态而导致业务处理变得棘手的情况也增多了。比如登录一家购物网站,然后跳转到该站的其他页面,也需要能继续保持登录状态。针对这个问题,为了保存用户的状态,因此引入了Cookie和Session技术。

什么是Cookie

Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器

特性:

1.如果服务器端发送重复的Cookie那么会覆盖原有的Cookie
2.Cookie保存在客户端,用户可以随意修改,并不安全,所以一般用来存放一些不敏感的数据
3.不是每次请求都会带上所有Cookies,只有请求路径包含Cookie Path的Cookie才会被带上

什么是Session

HttpSession 是一个服务端的概念,服务端生成的 HttpSession 都会有一个对应的 sessionid,这个 sessionid 会通过 cookie 传递给前端,前端以后每次发送请求的时候,都会带上这个 sessionid 参数。服务端看到这个 sessionid 就会把这个前端请求和服务端的某一个 HttpSession 对象对应起来,形成“会话”的感觉。

特性:

1.Session 数据存在了服务端,用户不能进行修改

会话过程在这里插入图片描述

会话固定攻击

1.URL重写
因为Cookies存在风险,所以有些浏览器不支持Cookie。也有可能客户阻止了所有的Cookies。为了兼容这种情况的存在,有些服务支持重写URL来识别身份。
例如:http://yyg.com;jsessionid=xxx。

URL重写是一种位于服务器端的操作,URL重写不需要往返服务器。重写的URL不会被返回客户端,也不会出现在浏览器地址栏。比如/resource 重写到 /different-resource 时,客户端会请求 /resource ,而服务器会在内部提取 /different-resource 处的资源。客户端能够检索到已重写的URL处的资源,但是客户端发出请求并收到响应时,并不会知道已重写URL处存在的资源

图示:
在这里插入图片描述
2什么是会话固定攻击
黑客只需访问一次系统,将系统生成的sessionld提取并拼凑在URL上,然后将该URL发给一些取得信任的用户。只要用户在session有效期内通过此URL进行登录,该sessionld就会绑定到用户的身份,黑客便可以轻松享有同样的会话状态,完全不需要用户名和密码,这就是典型的会话固定攻击。

举例(通过重写URL):
1.攻击者自己可以正常访问淘宝网站,在访问的过程中,淘宝网站给攻击者分配了一个 sessionid;
2.攻击者利用自己拿到的 sessionid 构造一个淘宝网站的链接,并把该链接发送给受害者;
3.受害者使用该链接登录淘宝网站(该链接中含有 sessionid),登录成功后,一个合法的会话就成功建立;
4.攻击者利用手里的 sessionid 冒充受害者。

反射型xss攻击流程
(图片来源于https://www.cnblogs.com/csnd/p/11807592.html)
在这里插入图片描述
反射型xss攻击主要用来窃取Cookie信息,需要欺骗用户点击链接。
(还有存储型XSS:代码是存储在服务器中的)

测试小案例
(通过浏览器模拟实现会话攻击,跳过代码实现,我这里url重写有些问题实现不了)

模拟一个钓鱼网站
在这里插入图片描述
后台登录代码

package com.feisi.web;

import com.feisi.Utils.BeanFactory;
import com.feisi.pojo.Admin;
import com.feisi.service.AdminService;


import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.编码处理
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //获取验证码
        String verifycode = request.getParameter("verifycode");
        //得到session对象
        HttpSession session = request.getSession();


        //测试URL重写成功没有
        Object admin1 = session.getAttribute("admin");
        if (admin1!=null){
            System.out.println(admin1.toString());
        }






        //取消验证功能
//        String checkcode = session.getAttribute("CHECKCODE_SERVER").toString();
        String error ="";

//        if(!checkcode.equalsIgnoreCase(verifycode)){ //不相等
//            error="验证码输入错误";
//            request.setAttribute("error",error);
//            request.getRequestDispatcher("/login.jsp").forward(request,response);
//            return;
//        }

        //2.获取请求参数
        String user = request.getParameter("user");
        String password = request.getParameter("password");
        //3.数据类型转换

        //4.调用Service的方法
        AdminService adminService = BeanFactory.createBean(AdminService.class);
        Admin admin =  adminService.login(user,password);
        if(admin != null){//登录成功

            //request.setAttribute("admin",admin);

            //5.把数据保存域中, admin保存到session域
            session.setAttribute("admin",admin);

            //判断用户是否勾选记住我
            String rem = request.getParameter("rem");
            if("rem".equals(rem)){ //勾选
                //创建用户名cookie, 密码cookie (加密)
                Cookie nameCookie = new Cookie("name",user);
                Cookie pwdCookie = new Cookie("pwd",password);
                //默认7天有效
                nameCookie.setMaxAge(7*24*60*60);
                pwdCookie.setMaxAge(7*24*60*60);
                //path: 默认 /

                //保存到客户端浏览器
                response.addCookie(nameCookie);
                response.addCookie(pwdCookie);
            }else{//没有勾选, 有就删除
                //获取cookie
                Cookie[] cookies = request.getCookies();
                if(cookies != null && cookies.length > 0){
                    for (Cookie cookie : cookies) {
                        //判断使用有name的cookie 与pwd的Cookie
                        if(cookie.getName().equals("name") || cookie.getName().equals("pwd")){
                            //删除
                            cookie.setMaxAge(0);
                            response.addCookie(cookie);
                        }
                    }
                }
            }
            //6.页面跳转  重定向
            response.sendRedirect(request.getContextPath()+"/index.jsp");
            //request.getRequestDispatcher("/index.jsp").forward(request,response);
        }else{//登录失败
            //5.把数据保存域中
            error = "用户名或者密码错误";
            request.setAttribute("error",error);
            //6.页面跳转 转发: 把数据存在request域
            request.getRequestDispatcher("/login.jsp").forward(request,response);
            // 往request域存数据, 存活时候很短, 只在一次请求内有效
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

登录成功后,会将session域中的数据打印在控制台
在这里插入图片描述

前端窃取户的cookie,如何设置HttpOnly为true,则无法通过js来获取(我这里是打印在控制台)

    // 获取指定名称的cookie
      function getCookie(name){
          var strcookie = document.cookie;//获取cookie字符串
          var arrcookie = strcookie.split("; ");//分割
		  console.log(strcookie);
          //遍历匹配
          for ( var i = 0; i < arrcookie.length; i++) {
              var arr = arrcookie[i].split("=");
              if (arr[0] == name){
                  return arr[1];
              }
          }
          print();
          return "";
      }

      // 打印所有cookie
      function print() {
          var strcookie = document.cookie;//获取cookie字符串
          var arrcookie = strcookie.split(";");//分割

          //遍历匹配
          for ( var i = 0; i < arrcookie.length; i++) {
              var arr = arrcookie[i].split("=");
              console.log(arr[0] +":" + arr[1]);
          }
      }

然后我在另外一个浏览器中访问/LoginServlet,可以访问到session域中的内容,说明攻击成功(一个小测试)

如何防御会话攻击

通过Spring Security 可以防御,主要是从以下三个方面来完成:
1.「首先」会利用 StrictHttpFirewall 防火墙,如果发现请求地址中带有 “;”,则该请求会被直接拒绝;

2.「然后」就是响应的 Set-Cookie 字段中有 HttpOnly 属性,这种方式会避免通过 XSS 攻击来获取 Cookie 中的会话信息,进而达成会话固定攻击。

3.「最后」则是让 sessionid 改变一下。既然问题是由于 sessionid 不变导致的,那我们就让 sessionid 变一下,利用Spring Security提供的防御会话固定攻击的策略即可实现。

还不会,以后再更新

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值