前置知识

node.js

koa框架常用目录,文件

js弱类型语言,空数组与整数1比较时,返回turue

jwt令牌

博客讲解:

关于jwt的讲解: http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

https://www.cnblogs.com/z-sm/p/9125995.html

https://www.jianshu.com/p/1ce08a374bb5

jwt攻击手段:https://www.freebuf.com/articles/web/181261.html

个人总结

形式:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.(这里有一个点)eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.(这里也有一个点)TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

第一个点前为header,第二个点前为payload,第二个点后为signture

一个攻击点:当header中的alg为none时,后端将不执行签名验证。将alg更改为none后,从JWT中删除签名数据(仅标题+’.'+ payload +’.')并将其提交给服务器。

解题思路

点开发现是登陆框,源码什么的没有啥问题

审查元素

f12审查元素,发现app.js,发现是node.js写的后端。框架用的是koa

之后主要的逻辑代码我没找到,看wp才知道是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();
}
};

这里有注册、登陆、flag、登出四个路由,可以得知admin登陆后即可获得flag,此时思路,如何登陆admin用户

jwt令牌

const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});

关键代码就是这一句,发现使用的为jwt令牌,关于jwt令牌的攻击前置知识已写,所以直接运用 将加密方式改为’none’的方式。

payload:

{"alg":"none","typ":"JWT"}.{"secretid":[],"username": "admin","password": "123456","iat": 1587632063}.(分开base64)

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjogImFkbWluIiwicGFzc3dvcmQiOiAiMTIzNDU2IiwiaWF0IjogMTU4NzYzMjA2M30.

这里推荐一个网站

https://jwt.io/

可以直接帮你编码

解题

先注册一个用户,登陆界面bp抓包,并发送刚刚的payload



发包,发现登陆成功,显示welcome admin,再抓一个包,go一下,发现flag

总结思路

  • 要找到一个项目的主要逻辑代码,文件名可能为api.js
  • 代码审计发现jwt令牌,思考可以用哪个jwt攻击思路

知识点

  • jwt相关攻击
  • 代码审计(node.js)

刷题[HFCTF2020]EasyLogin的更多相关文章

  1. LeetCode刷题系列

    LeetCode 我们工作面试和提高自身数据结构和算法能力的时候往往需要刷刷题,我选择LeetCode是通过一个留学论坛了解的.专业,覆盖语种全面. 提前说说刷题的心得: 尽量手写代码,少使用IDE的 ...

  2. ife任务刷题总结(一)-css reset与清除浮动

    本文同时发布于本人的个人网站www.yaoxiaowen.com 百度创办的前端技术学院,是一个面向大学生的前端技术学习平台.虽然只有大学生才有资格报名,提交代码进行比赛排名.但是这并不妨碍我们这些初 ...

  3. 刷题ING...

    我用codeVS刷题.. 努力准备!!

  4. XidianOJ 1020 ACMer去刷题吧

    题目描述 刷题是每个ACMer必由之路,已知某oj上有n个题目,第i个题目小X能做对的概率为Pi(0<=Pi<=1,1<=i<=n) 求小X至少做对k道题的概率 输入 第一行输 ...

  5. 【BZOJ-4590】自动刷题机 二分 + 判定

    4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 156  Solved: 63[Submit][Status ...

  6. NOI题库分治算法刷题记录

    今天晚自习机房刷题,有一道题最终WA掉两组,极其不爽,晚上回家补完作业欣然搞定它,特意来写篇博文来记录下 (最想吐槽的是这个叫做分治的分类,里面的题目真的需要分治吗...) 先来说下分治法 分治法的设 ...

  7. NOI题库刷题日志 (贪心篇题解)

    这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制:  1000ms  内存限制:  65536kB 描述 在一个平面上,如果有两个点( ...

  8. 用js刷题的一些坑

    leecode可以用js刷题了,我大js越来越被认可了是吧.但是刷题中会因为忽略js的一些特性掉入坑里.我这里总结一下我掉过的坑. 坑1:js中数组对象是引用对象 js中除了object还有数组对象也 ...

  9. BZOJ4590 自动刷题机

    Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写 ...

随机推荐

  1. .NET ORM 分表分库【到底】怎么做?

    理论知识 分表 - 从表面意思上看呢,就是把一张表分成N多个小表,每一个小表都是完正的一张表.分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面.分表后单表的并发能力提高了 ...

  2. spring如何创建RESTful Service

    REST REST,是指REpresentational State Transfer,有个精辟的解释什么是RESTful, 看url就知道要什么 看method就知道干什么 看status code ...

  3. 力扣Leetcode 46. 全排列

    全排列 给定一个 没有重复 数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], ...

  4. UGUI核心元素、基本控件、复合控件和高级控件

    UGUI的核心元素: Anchor(锚点):每个控件都有一个Anchor属性,控件的4个顶点,分别与Anchor的4个点保持不变的距离,不受屏幕分辨率变化的影响. 系统默认设置控件的Anchor位置在 ...

  5. Monkey and Banana(dp,求最长的下降子序列)

    A group of researchers are designing an experiment to test the IQ of a monkey. They will hang a bana ...

  6. Activiti7 流程部署

    首先先绘制一个流程图 创建bpmn文件 然后绘制好节点 然后修改节点信息 指定负责人 点击背景,修改ID和名称 保存 然后重命名成xml 使用diagram打开 导出png 然后包xml改回bpmn ...

  7. Zabbix 5.0切换中文语言小结

    最近测试Zabbix 5.0,去修改语言时发现不能选择"Chinese(zh_CN)",这个选项在下拉框中是灰色的(无法选择).提示"You are not able t ...

  8. IIS上传文件最大限制问题

    IIS服务器文件最大限制默认是30M. 自定义方法:修改配置文件,路径是:C:\Windows\System32\inetsrv\Config\applicationHost.config 在requ ...

  9. Python3 字典浅析

    Python 字典 字典(Dictionary) 字典是一个无序.可变和有索引的集合.在 Python 中,字典用花括号编写,拥有键和值. 实例 创建并打印字典: thisdict = { " ...

  10. zt:HttpUrlConnection使用详解

    下文转载自:https://www.cnblogs.com/tenWood/p/8563617.html 一,HttpURLconnection的介绍 在Android开发中网络请求是最常用的操作之一 ...