picoCTF-Web Exploitation-Java Code Analysis!?!

Description

BookShelf Pico, my premium online book-reading service.I believe that
my website is super secure. I challenge you to prove me wrong by
reading the ‘Flag’ book!Here are the credentials to get you started:

  • Username: “user”
  • Password: “user”

Source code can be downloaded

here

.Website can be accessed

here!

Hints

Maybe try to find the JWT Signing Key (“secret key”) in the source
code? Maybe it’s hardcoded somewhere? Or maybe try to crack it?

The ‘role’ and ‘userId’ fields in the JWT can be of interest to you!

The ‘controllers’, ‘services’ and ‘security’ java packages in the
given source code might need your attention. We’ve provided a
README.md file that contains some documentation.

Upgrade your ‘role’ with the new (cracked) JWT. And re-login for the
new role to get reflected in browser’s localStorage.

通过介绍我们可以得到以下信息:

  • 尝试破解JWT 签名密钥
  • JWT中的role和userId字段可能会对我们有帮助
  • 重点关注源码中的controllers, services, security包。
  • README.md文件可能对我们有所帮助
  • 在JWT中提升role并刷新cookie存储?

1. 分析代码

首先,我们下载源码,使用是gradle管理包,先看README.md,里面说明了项目的架构以及各个包的功能。访问here!网站,使用username:user, password:user用户登录,发现图片有Flag,点击提示有锁,需要用户拥有role为Admin的权限(user用户的role是Free

Flag
You need to have Admin role to access this special book!
This book is locked.

我们给用户user修改role为Admin试试,查看UserController找到修改role的代码

@PatchMapping("/users/role")
public Response<String> updateRole(@Valid @RequestBody UpdateUserRoleRequest userRoleRequest) throws ResourceNotFoundException, ValidationException {
    userService.updateRole(userRoleRequest);
    return new Response<String>().setPayload("Role successfully updated.")
            .setType(ResponseType.SUCCESS);
}
@Getter
@Setter
@NoArgsConstructor
public class UpdateUserRoleRequest {
    private Integer id;

    @NotNull(message = "Role cannot be Null")
    @NotEmpty(message = "Role cannot be empty")
    private String role;
}

我们需要构建RequestBody参数包含idrole ,role已知为Admin ,接下来需要找到user用户的id ,在UserController 中有一个users接口,查询所有用户信息

@GetMapping("/users")
public Response<List<UserDto>> getAll() {
    List<UserDto> userList = userService.getAllUsers();
    Response<List<UserDto>> response = new Response<>();
    response.setPayload(userList);
    response.setType(ResponseType.SUCCESS);
    return response;
}

我们进去Service看一下,发现有权限认证hasAuthority('Admin'),需要Admin权限,前面修改role的也需要这个权限认证,不过又多了一步#userRoleRequest.id != authentication.principal.grantedAuthorities[0].userId ,意思好像是userId不能是本用户,也就是自己不能修改自己的role

@PreAuthorize("hasAuthority('Admin')")
public List<UserDto> getAllUsers() {
    return UserDto.getUserDtoListFromUsers(userRepository.findAll());
}

@PreAuthorize("hasAuthority('Admin') and #userRoleRequest.id != authentication.principal.grantedAuthorities[0].userId")
public void updateRole(UpdateUserRoleRequest userRoleRequest) throws ResourceNotFoundException {
    Optional<User> userOptional = userRepository.findById(userRoleRequest.getId());
    if(!userOptional.isPresent()){
        throw new ResourceNotFoundException("user with ID: "+userRoleRequest.getId()+" not found");
    }
    User user = userOptional.get();
    Optional<Role> roleOptional = roleRepository.findById(userRoleRequest.getRole());
    if(!roleOptional.isPresent()){
        throw new ResourceNotFoundException("user with role: "+userRoleRequest.getRole()+" not found");
    }
    Role role = roleOptional.get();
    user.setRole(role);
    userRepository.save(user);
}

2. 修改JWT

所有操作需要给user用户一个Admin权限,我们知道JWT在登录后生成一个token,每次请求会在Request Header中带上这个token,以便后端程序对权限进行验证。

User登录网站,使用DevTools查看请求头,得到token

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiRnJlZSIsImlzcyI6ImJvb2tzaGVsZiIsImV4cCI6MTcxNjE5MDE1MywiaWF0IjoxNzE1NTg1MzUzLCJ1c2VySWQiOjEsImVtYWlsIjoidXNlciJ9.27h2BykhrD30xizlmoid0Wkj3OLuNPgR-XGo30UBv_0

拿到JWT官网解析,得到payload

{
  "role": "Free",
  "iss": "bookshelf",
  "exp": 1716190153,
  "iat": 1715585353,
  "userId": 1,
  "email": "user"
}

修改role为Admin重新加密,前提需要找到签名密钥(第一条提示)。继续查看权限验证JWT相关代码,发现密钥为1234

@Service
class SecretGenerator {
    private Logger logger = LoggerFactory.getLogger(SecretGenerator.class);
    private static final String SERVER_SECRET_FILENAME = "server_secret.txt";

    @Autowired
    private UserDataPaths userDataPaths;

    private String generateRandomString(int len) {
        // not so random
        return "1234";
    }

    String getServerSecret() {
        try {
            String secret = new String(FileOperation.readFile(userDataPaths.getCurrentJarPath(), SERVER_SECRET_FILENAME), Charset.defaultCharset());
            logger.info("Server secret successfully read from the filesystem. Using the same for this runtime.");
            return secret;
        }catch (IOException e){
            logger.info(SERVER_SECRET_FILENAME+" file doesn't exists or something went wrong in reading that file. Generating a new secret for the server.");
            String newSecret = generateRandomString(32);
            try {
                FileOperation.writeFile(userDataPaths.getCurrentJarPath(), SERVER_SECRET_FILENAME, newSecret.getBytes());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            logger.info("Newly generated secret is now written to the filesystem for persistence.");
            return newSecret;
        }
    }
}

修改role及密钥信息得到新得token

在这里插入图片描述

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiQWRtaW4iLCJpc3MiOiJib29rc2hlbGYiLCJleHAiOjE3MTYxOTMxNTcsImlhdCI6MTcxNTU4ODM1NywidXNlcklkIjoxLCJlbWFpbCI6InVzZXIifQ.zMJVsnlSGl2OKzBSQ_h2qIU5mB7OL7bgF6khdI31eMw

3. 修改新建用户的role为Admin

  • 网页上直接创建一个用户

    在这里插入图片描述

  • 使用postman请求用户查询接口得到hucker的userId为6

    (Header中增加Authorization,填入上面得到的新token

    在这里插入图片描述

  • 构建ResponseBody,给hucker用户修改权限为Admin

    在这里插入图片描述

  • 重新登录,发现role已经修改为Admin ,点击Flag拿到结果

    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/621150.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机发展史故事【11】

爆发超新星 IBM 号称巨人&#xff0c;竟在巨型机领域败在小小的控制数据公司CDC 手下。在小型机领域&#xff0c;“霸主”DEC 公司的“后院”也曾“起火”&#xff0c;绝非一直风平浪静。 本世纪60 年代末&#xff0c;DEC 公司因开发小型电脑迅速崛起&#xff0c;赢得“小型机…

五子棋对战(网页版)

目录 一、项目背景 用户模块 匹配模块 对战模块 二、核心技术 三、相关知识 WebSocket 原理 报文格式 代码 服务器代码 客户端代码 四、项目创建 4.1、实现用户模块 编写数据库代码 数据库设计 配置MyBatis 创建实体类 创建UserMapper 创建UserMapper接口 实现UserMapper.xml 前…

Android Studio Please select Android SDK

解决方案&#xff1a; 1、打开 SDK Manager 2、选择编辑&#xff08;Edit&#xff09; 3、 一直Next&#xff0c;直到完成&#xff0c;解决&#xff01;

科技查新中的工法查新点如何确立与提炼?案例讲解!

按《工程建设工法管理办法》( 建 质&#xff3b;2014&#xff3d;103 号) &#xff0c;工法&#xff0c;是指以工程为对象&#xff0c;以工艺为核心&#xff0c;运用系 统工程原理&#xff0c;把先进技术和科学管理结合起来&#xff0c;经过一定工程实践形成的综合配套的施工方…

redis安装与群集

项目需求&#xff1a; 1.安装redis 2.测试redis性能&#xff0c;100个并发连接&#xff0c;100000个请求测试 3.在当前数据库下创建键值对 a11,a22,a33,a44&#xff0c;a55 4.查看键值对 5.将a1改名为a11,将a2删除 5.将a3移动到1号数据库 6搭建redis集群(可选) 测试环境…

如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库

前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496…

vue3组件插槽

Index.vue: <script setup> import { ref, onMounted } from vue import Child from ./Child.vue import ./index.cssonMounted(() > {}) </script><template><div class"m-home-wrap"><Child>插槽</Child><div class&qu…

linux不小心将/etc/passwd用户文件清空或删除解决方法

大概思路&#xff1a;进入单用户模式将passwd-引子程序复制为删除的passwd用户文件&#xff0c;关闭selinux 此系统为&#xff1a;centos 7 1.在GRUB引导的时候按e进入编辑模式&#xff0c;linux16那一行的ro 修改为rw rd.break ‘ ’ 2.ctrlx执行 3.进入单用户模式后修改根…

Cocos 2048从创建到发布上线

一、制作2048小游戏过程 扫描体验2048小游戏 场景搭建&#xff0c;4X4棋盘和基础设置绘制背景板&#xff0c;包含预制体等信息考虑在棋盘中随机出现两个数字方块&#xff0c;数字为2&#xff0c;初始化操作滑动事件部分&#xff0c;让方块移动起来&#xff0c;每滑动一次就生成…

【机器学习与实现】K近邻算法

目录 一、KNN算法简介&#xff08;一&#xff09;KNN算法包括三个步骤&#xff08;二&#xff09;超参数K的影响 二、距离度量三、邻近点的搜索算法四、KNN算法的特点五、KNN常用的参数及其说明六、分类算法的性能度量&#xff08;一&#xff09;混淆矩阵及相关概念&#xff08…

从零创建一个vue2项目

标题从零创建一个vue2项目&#xff0c;项目中使用TensorFlow.js识别手写文字 npm切换到淘宝镜像 npm config set registry https://registry.npm.taobao.org安装vue/cli -g npm install -g vue/cli检查是否安装成功 vue -V创建项目 vue create 项目名安装TensorFlow npm …

韶音、南卡、倍思开放式耳机值得买吗?王牌机型对比测评

今年&#xff0c;开放式耳机市场迎来了众多新品&#xff0c;为消费者提供了丰富的选择。在这样的背景下&#xff0c;正确挑选一款既符合音质需求又兼具佩戴舒适的开放式耳机显得格外关键。作为长期使用开放式耳机的用户&#xff0c;我发现很多人在韶音、南卡、漫步者这三个品牌…

k8s v1.20二进制部署

目录 一、环境准备 二、操作系统初始化配置 2.1.关闭防火墙 ​编辑 2.2.关闭selinux 2.3.关闭swap 2.4.根据规划设置主机名 2.5在master添加hosts 2.6.调整内核参数 2.7.时间同步 三、部署 docker引擎 3.1.所有 node 节点部署docker引擎 四、部署 etcd 集群 4.1.…

【数据库】docker搭建mysql8一主两从节点,配置proxysql读写分离

docker搭建mysql8一主两从节点&#xff0c;配置proxysql读写分离 一、docker 搭建 mysql8 一主两从节点1.1 相关配置文件与docker启动1.2 半同步复制1.3 主从同步异常处理 二、mysql 中间件 ProxySql 配置读写分离2.1 在mysql服务里创建给proxySQL访问的用户2.2 安装ProxySql及…

Reactor Netty TCP 服务器端-响应式编程-011

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform…

2024第八季完美童模 上海翎秀赛区 初赛 火热启动

第八季完美童模新篇启航&#xff0c;打响2024全明星联赛第三站的火热赛程&#xff01;本季全球赛亮点纷呈&#xff0c;带领全球选手体验暑期最高规格国民赛&#xff01;6季上榜CCTV新闻报道&#xff0c;稳坐行业赛事头把交椅&#xff1b;分赛区遍布全球各地&#xff0c;覆盖350…

【Linux】自动化构建工具make/Makefile和git介绍

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12625432.html 目录 前言 Linux项目自动化构建工具-make/Makefile 举例 .PHONY 常见符号 依赖关系…

前端报错 SyntaxError: Unexpected number in JSON at position xxxx at JSON.parse

问题描述​ 控制台提示 SyntaxError: Unexpected number in JSON at position xxxx at JSON.parse 问题原因​ 原因&#xff1a;JSON 数据格式错误&#xff0c;是否符合 JSON 格式。 解决方法​ 应为json格式数据 什么是json格式数据 JSON&#xff08;JavaScript Object …

使用sqlmodel实现唯一性校验2,插入之前检查是否已存在

虽然之前添加唯一性校验的方法能够解决数据唯一的问题&#xff0c;但是如果忘了处理异常&#xff0c;则可能会导致程序崩溃。 在此基础上&#xff0c;我们可以在插入数据之前检查该数据是否已存在。 原来的代码&#xff1a; from sqlmodel import Field, Session, SQLModel,…

基于Python实现蔬菜水果识别

蔬菜水果识别在农业生产、食品加工和市场销售等领域具有重要意义。随着计算机视觉和机器学习技术的发展,利用图像识别技术实现蔬菜水果的自动化识别已成为可能。 目录 引言研究背景问题陈述研究目标文献综述蔬菜水果识别的相关研究概述基于计算机视觉和机器学习的图像识别方法…