Hi there 👋

ありがたいからありがとう、去りがたいだら去りがとう。

GitLab部分漏洞分析

GDK运行+调试环境搭建 GDK全称GitLab Development Kit,是GitLab官方为了方便开发者为GitLab开源项目贡献开源代码而开发的一键式GitLab运行+调试部署工具,在需要对GitLab漏洞进行调试和分析的情况下,除去使用GitLab的Docker镜像也可以利用GDK来搭建环境,地址为https://gitlab.com/gitlab-org/gitlab-development-kit。 如果需要分析的是GitLab最新的代码,则使用GDK官方文档里的安装步骤就可以一步到位。但如果利用GDK进行漏洞复现与分析,往往需要使用到老版本的GitLab代码,此时如果使用最新的GDK部署的话,则会不可避免的出现很多依赖相关的问题(如Ruby版本要求不一致,一些Ruby依赖包不符合版本要求等),在整个部署的时候会遇到很多坑。下面大概说一下一个较为可行的部署流程,以及我在部署过程中的一些问题。 此处以v15.1.0-ee版本的部署为例。首先Clone一下GDK: 1 git clone https://gitlab.com/gitlab-org/gitlab-development-kit.git gdk GDK版本调整和初始化 接下来需要查看GitLab版本的发布时间,将GDK也Checkout到对应版本发布日期附近的提交处,这样可以保证GDK使用的Ruby版本和GitLab一致,避免后续安装过程中因为Ruby大版本不一致导致的各种依赖问题。 查看提交记录可以发现v15.1.0-ee的发布时间为2022年6月21日,所以我将GDK调整至2022年7月26日的提交处:77019f1204a3bbcb44bac37bfd0da4059aa130e9。只要保证GDK的Ruby依赖版本不要和GitLab的相差过大即可。 切换版本之后,与官方文档中手动部署的步骤一致,使用make bootstrap初始化GDK,安装GDK相关的依赖。在这篇文章中提到了使用一键脚本部署后再Checkout GitLab到对应版本的方式,经过测试我发现如果版本相差过大,依赖问题依然会存在,并且可能存在数据库结构不一样的问题,因此此处更好的解决方案是手动Clone GitLab仓库,自行Checkout之后再开始部署GDK,如下。 1 2 3 4 5 git clone https://gitlab.com/gitlab-org/gitlab.git gdk/gitlab cd gdk/gitlab git checkout v15.1.0-ee cd .. gdk install 在gdk install的过程中可能会出现各种各样奇奇怪怪的问题,我主要把问题归结于以下两类: 由于GDK调整了到早期版本,有些Bug还没修,通过Google和GDK的Issues大部分可以找到解决方案; 一些Native Extension的编译问题,如OpenSSL、gpgme等等;(gpgme问题出现的频率最高,主要表现为gpgme编译失败,解决方案是不通过bundler安装gpgme而是使用gem install gpgme -- --use-system-libraries手动安装) Ruby版本不同导致的依赖问题,如有些软件包的老版本不再被新版Ruby支持,又或是一些新版本的软件包不被老版本的Ruby支持。(这里因为前面已经通过Checkout把GDK和GitLab的依赖版本调整到尽可能一致了,所以这里不会有太大的问题) 一些配置的修改 gdk install成功跑完之后,就相当于脚本安装结束了。接下来修改gitlab/config/gitlab.yml配置文件,修改监听的IP地址,以及关闭Webpack的开发模式,可以减少一点占用: 1 2 3 4 5 6 7 8 gitlab: host: 0.0.0.0 port: 3000 https: false webpack: dev_server: enabled: false 修改完了配置文件,需要重新编译一下前端资源: 1 rake gitlab:assets:compile 然后使用gdk start启动GitLab,可以使用gdk tail看看启动的Log,有报错信息再对症下药去修,直到没有报错,应该就能够正常访问了,整个环境也就搭建完毕。...

Jul. 22, 2023 · 5 min · 990 words

NeSE三月升级赛WriteUp (Web)

又是一个XSS题,Docker里起了一个Web一个Bot一个Redis,Web使用Java写的,用的Eclipse的Jetty服务器,上层是Micronaut微服务框架来的,整体打包成一个JAR。 附件地址:CTF-Chal/fancy-notes.zip (github.com) 一开始还以为是Java相关的漏洞,随手看了下反编译,发现好像除了题目是Java写的之外和Java没啥关系,同理Redis也只是个用来传数据的中间媒介,似乎也利用不了什么漏洞。于是继续关注题目本身的逻辑。 先看Bot做了啥: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 const puppeteer = require("puppeteer"); const Redis = require('ioredis'); const connection = new Redis(6379, process....

Mar. 19, 2023 · 7 min · 1362 words

HXPCTF 2023 Web复现

valentine Web签到题,考的是Node.js的ejs模板库命令执行。首先给出源码,里面的库版本都是最新的: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 var express = require('express'); var bodyParser = require('body-parser') const crypto = require("crypto"); var path = require('path'); const fs = require('fs'); var app = express(); viewsFolder = path....

Mar. 12, 2023 · 5 min · 978 words

NeSE十二月升级赛WriteUp (Web)

一个硬核的XSS题,收获相当大(还得感谢CrumbledWall师傅点拨了我几次) 开局给了后端的源码,能看见里面用了腾讯的COS对象存储,可以上传文件到上面,docker-compose.yml里面还有一个名为的bot的服务但没有给出源码,能看出来后端有个接口会去连接这个bot。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 const express = require("express") const isJpg = require('is-jpg') const isPng = require('is-png') const isWebp = require('is-webp') const fs = require('fs') const fileUpload = require('express-fileupload') const bodyParser = require('body-parser') const net = require('net') const crypto = require("crypto") const https = require('https') var COS = require('cos-nodejs-sdk-v5') const app = express() const BOT_HOST = 'bot' const BOT_PORT = 8080 app....

Dec. 20, 2022 · 6 min · 1267 words

UCORE Lab 2

UCORE的段页式内存布局 从UCORE启动到物理内存管理的初始化结束,一共加载了3次GDT,实现了由单纯的分段到段页式内存管理的布局。 在内核链接脚本中,内核的加载地址由Lab1中的0x100000改为了0xC0100000: 1 2 3 4 5 6 7 8 9 10 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(kern_entry) SECTIONS { /* Load the kernel at this address: "." means the current address */ . = 0xC0100000; ...... } 根据文档里提到的,这个地址为虚拟地址,后续通过分段和分页来映射到物理地址,实际内核还是放在0x100000的物理地址开始的。这个从bootmain函数中可以看得出来,在加载ELF段的时候对va进行了与操作,去除了地址中的高8位数据,也就是把C0给抹除了: 1 2 3 4 5 6 7 8 9 10 // load each program segment (ignores ph flags) ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff); eph = ph + ELFHDR->e_phnum; for (; ph < eph; ph ++) { readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset); } // call the entry point from the ELF header // note: does not return ((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))(); 1 - 准备进入内核代码 在boot/bootasm....

Dec. 2, 2022 · 8 min · 1680 words

N1CTF 2022 Web 复现

Easy_S2 这题主要考察的是Struts2的路径匹配规则以及Java Web中的Security-Constraint安全约束选项。题目附件是一个.war包,将其解压之后可以直接通过Tomcat部署,代码实现也很简单。通过web.xml可以了解到整个网站的路由都被导向了中间Struts2,同时有两条安全约束项: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <!-- 整个网站的路由都由Struts2处理 --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- /img/* 和 /index.jsp 不需要认证即可访问 --> <security-constraint> <display-name>pass-static</display-name> <web-resource-collection> <web-resource-name>static</web-resource-name> <url-pattern>/img/*</url-pattern> <url-pattern>/index....

Nov. 21, 2022 · 8 min · 1642 words

UCORE Lab 1

Ex.1 Makefile 狗都不看 操作系统镜像文件ucore.img是如何一步一步生成的? make -n可以输出具体执行的命令: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 # Compile Kernel Sources echo + cc kern/init/init....

Oct. 24, 2022 · 17 min · 3555 words

Node.js require() RCE复现

前言 前阵子参加了Balsn CTF 2022,有道Node.js的题目叫2linenodejs,个人觉得思路十分巧妙,遂进行了完整的复现,收获颇多。下面是整个复现的过程。 题目代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // server.js process.stdin.setEncoding('utf-8'); process.stdin.on('readable', () => { try{ console.log('HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Close\n'); const json = process.stdin.read().match(/\?(.*?)\ /)?.[1], obj = JSON.parse(json); console.log(`JSON: ${json}, Object:`, require('./index')(obj, {})); }catch{ require('./usage') }finally{ process.exit(); } }); // index.js module.exports=(O,o) => (Object.entries(O).forEach(([K,V])=>Object.entries(V).forEach(([k,v])=>(o[K]=o[K]||{},o[K][k]=v))), o); // usage.js console.log('Validate your JSON with <a href="/?...

Oct. 11, 2022 · 11 min · 2142 words