CyberStreak v1.0

dvCTF Web 문제입니다.

 

Description :

Thank you for your report !

You can now create your own challenges, delete them, deactivate / activate them.

xXx-michel-xXx

http://challs.dvc.tf:5002

Brute force is strictly forbidden and useless.Hello,

I am a student and I would like to improve my web development skills. To practice, I am creating my first web application. This application is a kind of cybercoach. Example: you want to do sports. A sport goal could be to do 100 push-ups per day for 1 month. The application will allow you to create this "challenge" and each day, you will have to do the number of push-ups you have set and note it in the application. If you don't do the push-ups for 3 days, it's a failure and you lose your streak.

This first version of the application gives you the possibility to create an account and to do the challenge of the example.

Can you test the security of my application ?

xXx-michel-xXx

http://challs.dvc.tf:5001

Brute force is strictly forbidden and useless.

 

푸시업 챌린지가 있습니다. 취약점을 찾아서 신고해주시기 바랍니다.

웹페이지 테스트를 통해 취약점을 찾아내는 문제입니다.

 

 

문제 분석

index page

정보가 없기 때문에 페이지 소스코드,  네트워크 패킷, 쿠키 순으로 살펴보았습니다.

페이지 소스코드는 hidden과 disable 처리된 구문들이 있었지만 문제와는 크게 상관 없었습니다.

네트워크 패킷 또한 눈에 보이는게 없었습니다.

 

cookie

그러던 중 cookie에서 익숙한 형태의 값을 발견하였습니다.

JWT로 추정되며 이를 확인하기 위해 base64로 디코딩 해보았습니다.

 

decoding

JWT인 것이 확실합니다.

 

 

문제 풀이

인코딩하여 제출해보았으나 로그아웃이 이루어질 뿐 flag는 확인할수 없었습니다.

때문에 secret 키가 존재하는지 확인해 보았습니다.

 

username : xXx-michel-xXx
secret : s3cr3t

확인 결과 secret 값이 존재하였으며 username은 해당 서버 소유자인 xXx-michel-xXx로 추정하여 진행하였습니다.

 

encoding

인코딩된 세션값을 획득할 수 있었습니다.

 

flag

해당 값으로 cookie값을 바꿔주게 되면 flag가 나오게 됩니다.

 

더보기

dvCTF{80b8d1A92G6a13a98Dc7b546a7a7Y35}

 

'Challenge > CTF' 카테고리의 다른 글

[dvCTF] ICMP  (0) 2022.03.15
[UTCTF] Websockets?  (0) 2022.03.14
[dvCTF] CyberStreak v2.0  (0) 2022.03.14
[dvCTF] RSA  (0) 2022.03.14
[Codegate2022] PrimeGenerator  (0) 2022.03.07

CyberStreak v2.0

dvCTF Web 문제입니다.

 

Description :

Thank you for your report !

You can now create your own challenges, delete them, deactivate / activate them.

xXx-michel-xXx

http://challs.dvc.tf:5002

Brute force is strictly forbidden and useless.

 

취약점 신고 고맙습니다. 이제 나만의 챌린지를 만들고 삭제 하고 이것저것할수 있습니다.

웹페이지 테스트를 통해 취약점을 찾아내는 문제입니다.

 

문제 분석

New challenge

새로운 페이지에서 취약점을 찾아내야 되는것으로 보입니다.

file upload 기능이 있는것으로 보아 이를 이용하는 LFI 혹은 file_upload를 이용한 웹쉘 취약점인것으로 예상됩니다.

 

request

임의의 값과 파일들을 입력하여 확인을 해보았습니다.

challengename : test

filename : aa

 

url path로 hash값들이 사용되는 것처럼 보여집니다.

 

test hash
aa hash

이를 통해 제가 입력한 값들을 hash화하여 url path로 사용중이라는 사실을 알수 있었습니다.

뿐만 아니라 첫번째 챌린지를 통해 flag의 이미지 파일 이름을 획득할수 있습니다.

 

challengename : xXx-michel-xXx
filename : flaggggggggggggggggggggggg.png

이를 이용하여 url path를 생성합니다.

SHA256(xXx-michel-xXx)/MD5(flaggggggggggggggggggggggg.png2)

 

 

문제 풀이

url path를 생성하여 접근하면 file이 다운로드 됩니다.

7e0c7ec9c02bffca0ff9a9dc26f02f5b
0.01MB

이 파일을 수정해서 flag를 획득할 수 있습니다.

더보기

dvCTF{7rz1nv12kmv35sQaVOfsdzA8fQ}

 

'Challenge > CTF' 카테고리의 다른 글

[UTCTF] Websockets?  (0) 2022.03.14
[dvCTF] CyberStreak v1.0  (0) 2022.03.14
[dvCTF] RSA  (0) 2022.03.14
[Codegate2022] PrimeGenerator  (0) 2022.03.07
[CODEGATE2022] CAFE  (0) 2022.03.05

RSA

dvCTF Warmup 문제입니다.

 

Description :

Our team has found a cipher text: there seems to be some clues to decipher it. Can you help us to read it?

 

암호를 발견했다며 해독을 요구하는 문제입니다.

 

문제 분석

문제 제목부터 보란듯이 RSA를 사용한것을 알려주고 있습니다.

 

n = 0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F1A523013791EDFEB1FBBA160799892C118892FB7F199C9957DF5A26DAB4D776E5226F06ACD05412F6DD2B1B75D24CE9DC2DDAC513BCB96CD9B97F9BEF8543A3A1

phi = 0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F037D2317D3864035ECE8BCDD458711B788B5B3FDFD5164F7D736D0A56F416E8C16126E3868D73F54AF4D61F6033E069994319C849460C60A725A0F4DD97EDCC84

e = 0x10001

ct = 0x268D7D5F5593EA30F536635B58585620B51D2D143AFE4734635C259278D61413D0C89678E81EDF466B1E45E27EBF802F62F61263E499A516465163C7CB668F94258B3424C3E2BD76634923DECD670E4B6034F8FD00C76F9DAD00A72DB22B70B9408C89FCEE4C9B0D2D4B5664284328711BFAD57FBE1EDCC0854AAD57390DCAD6

뿐만아니라 n, phi, e, chiper text 값까지 제공해주었습니다.

 

RSA 암보호화

위 식에 의하면 RSA를 복호화 하기 위해서는 C(ct), d, n값이 필요합니다.

현재 확보 되지 않은 값은 d입니다. 하지만 e값과  phi 값이 있기 때문에 d를 구할 수 있습니다.

 

d = invert(e, phi)

위 식에 대입하여 얻어낼 수 있습니다.

 

문제 풀이

from gmpy2 import *
from Crypto.Util.number import *

n = '0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F1A523013791EDFEB1FBBA160799892C118892FB7F199C9957DF5A26DAB4D776E5226F06ACD05412F6DD2B1B75D24CE9DC2DDAC513BCB96CD9B97F9BEF8543A3A1'
phi = '0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F037D2317D3864035ECE8BCDD458711B788B5B3FDFD5164F7D736D0A56F416E8C16126E3868D73F54AF4D61F6033E069994319C849460C60A725A0F4DD97EDCC84'
e = '0x10001'
ct = '0x268D7D5F5593EA30F536635B58585620B51D2D143AFE4734635C259278D61413D0C89678E81EDF466B1E45E27EBF802F62F61263E499A516465163C7CB668F94258B3424C3E2BD76634923DECD670E4B6034F8FD00C76F9DAD00A72DB22B70B9408C89FCEE4C9B0D2D4B5664284328711BFAD57FBE1EDCC0854AAD57390DCAD6'
pt=''

n = int(n, 16)
phi = int(phi, 16)
e = int(e, 16)
ct = int(ct, 16)
d = invert(e, phi)

pt = pow(ct, d, n)
print(pt)

M(pt) : 100118678470123102108521039599861127251114116518811695988695828352125

 

Convert Decimal to ASCII - Online ASCII Tools

 

Convert Decimal to ASCII - Online ASCII Tools

Incredibly simple, free and fast browser-based utility for converting decimal to ASCII. Just paste your decimals and they will be instantly converted to ASCII.

onlineasciitools.com

얻어낸 plaint text 값을 위 사이트를 통해 변환하면 flag를 획득할 수 있습니다.

 

더보기

dvCTF{fl4g_cVpH3rt3Xt_bV_RS4}

'Challenge > CTF' 카테고리의 다른 글

[dvCTF] CyberStreak v1.0  (0) 2022.03.14
[dvCTF] CyberStreak v2.0  (0) 2022.03.14
[Codegate2022] PrimeGenerator  (0) 2022.03.07
[CODEGATE2022] CAFE  (0) 2022.03.05
[MHSCTF] Erlenmeyer Biscuits (Cuppa Joe 2)  (0) 2022.02.23

CODEGATE 2022 암호학 문제입니다.

풀이에는 실패했으나 접근 방식은 맞았었기에 아쉬운 마음이 커서 작성하게 되었습니다.

암호학 방식은 RSA입니다.(Bold 쳐진 부분은 solver의 설명을 참조한 부분입니다.)

 

 

문제 분석

#!/usr/bin/python3
from Crypto.Util.number import *
import os

BITS = 512
UPPER_BITS = 296
LOWER_BITS = BITS - UPPER_BITS

UPPER = bytes_to_long(os.urandom(UPPER_BITS // 8)) << LOWER_BITS 
FLAG = b'codegate2022{this_is_a_sample_flag}'

def menu1():
    while True:
        lower = bytes_to_long(os.urandom(LOWER_BITS // 8))     
        p = UPPER | lower
        if isPrime(p): return lower    # p가 소수면 lower 반환

def menu2():
    p = UPPER + menu1()     
    q = getPrime(512)       
    e = 65537               
    n = p * q              
    return n, pow(bytes_to_long(FLAG + b'\x00' + os.urandom(128 - 2 - len(FLAG))), e, n)
    
   
while True:
    print("1. Generate 10 random primes (only lower bits)")
    print("2. Encrypt a flag")
    idx = int(input("> "))
    if idx == 1:
        print("How many? (Up to 10)")
        num = int(input("> "))
        for _ in range(min(10, num)):
            print(menu1())             
    elif idx == 2:
        n, c = menu2()
        print(f"n : {n}")              
        print(f"c : {c}")                            
UPPER = bytes_to_long(os.urandom(UPPER_BITS // 8)) << LOWER_BITS

본 대회에서 제공된 문제 코드입니다.

문제 풀이를 위해 코드 분석부터 해보도록 하겠습니다.

크게 menu1과 menu2 두가지 부분으로 나뉩니다.

 

 

def menu1():
    while True:
        lower = bytes_to_long(os.urandom(LOWER_BITS // 8))     
        p = UPPER | lower
        if isPrime(p): return lower

menu1 : p가 소수면 216 비트(25 바이트) lower 값을 반환합니다.

어떻게든 UPPER 값을 찾을 수 있다면 p의 상위 비트 중 절반 이상을 알 수 있으므로 Coppersmith 알고리즘을 사용하는 표준 RSA 공격을 통해 n을 인수분해할 수 있습니다.

이는 특정 소수에 대한 나머지 후보를 제거할 수 있습니다.

 

UPPER + lower가 소수가 되도록 충분한 수의 lower가 주어지면 각 소수 p<700에 대해 UPPER (mod p)에 대해 하나의 가능한 후보를 제외하고 모두 제거할 수 있습니다. 이는 소수 p<700에 대해 UPPER (mod p)를 복구할 수 있음을 의미합니다.

 

 

def menu2():
    p = UPPER + menu1()     # UPPER + lower
    q = getPrime(512)       # 512 비트 소수
    e = 65537               # 65537 알려진 지수 공격
    n = p * q               # 공개키에 사용되는 (e, n) -> (65537, n) 
    return n, pow(bytes_to_long(FLAG + b'\x00' + os.urandom(128 - 2 - len(FLAG))), e, n)

menu2 : FLAG값을 포함하여 연산한 값에 FLAG가 포함되어 있습니다.

 

 

#!/usr/bin/python3
from Crypto.Util.number import *
import os

BITS = 512
UPPER_BITS = 296
LOWER_BITS = BITS - UPPER_BITS

UPPER = bytes_to_long(os.urandom(UPPER_BITS // 8)) << LOWER_BITS # 37바이트, 206비트만큼 왼쪽으로 이동
FLAG = b'codegate2022{this_is_a_sample_flag}'

def menu1():
    while True:
        lower = bytes_to_long(os.urandom(LOWER_BITS // 8))      # 25바이트
        p = UPPER | lower
        if isPrime(p): return lower    # p가 소수면 lower 반환

def menu2():
    p = UPPER + menu1()     # UPPER + lower
    q = getPrime(512)       # 512 비트 소수
    e = 65537               # 65537 알려진 지수 공격
    n = p * q               # 공개키에 사용되는 (e, n) -> (65537, n) 
    return n, pow(bytes_to_long(FLAG + b'\x00' + os.urandom(128 - 2 - len(FLAG))), e, n)
    
    # bytes_to_long(codegate2022{this_is_a_sample_flag} + 0x00 + random(91))만큼 랜덤 비트 생성^65537 % n

while True:
    print("1. Generate 10 random primes (only lower bits)")
    print("2. Encrypt a flag")
    idx = int(input("> "))
    if idx == 1:
        print("How many? (Up to 10)")
        num = int(input("> "))
        for _ in range(min(10, num)):
            print(menu1())              # lower값 획득
    elif idx == 2:
        n, c = menu2()
        print(f"n : {n}")               # n
        print(f"c : {c}")               #  bytes_to_long(codegate2022{this_is_a_sample_flag} + 0x00 + random(91))만큼 랜덤 비트 생성^65537 % n                 
UPPER = bytes_to_long(os.urandom(UPPER_BITS // 8)) << LOWER_BITS    # 37바이트, 206비트만큼 왼쪽으로 이동

최종적으로 분석한 내용은 위와 같습니다.

 

더보기

시도해본 방법

  • 임의의 소수 q를 잡아내보려함 (어림도 없었습니다.)
  • 충분한 정보를 수집하여 중국인의 나머지 정리를 적용 (실제로 해본적이 없었기에 대회 당시 생각은 했으나 많이 해매 결국 풀이에는 적용하지 못했습니다.)
더보기

생각 정리

 

암호화 C = M^e mod n

우리가 구하고자 하는 FLAG값은 M에 들어가 있습니다.

C나 e, n 값은 모두 주어집니다.

복호화 M = C^d mod n

d를 구하기 위해서는 n을 이루고 있는 소수 p, q를 알아야 합니다.

여기서 p는 upper+lower, q는 512바이트짜리 임의의 소수 (p-1)(q-1)을 통해서 phi라는 값을 구해야됩니다. invert(e, phi)를 통해서 d값을 구할수 있기 때문입니다.

 

 

문제 풀이

#!/usr/bin/sage
from Crypto.Util.number import *
from pwn import *
from sage.all import *
import math

r = remote("localhost", 9001)

BITS = 512
UPPER_BITS = 296
LOWER_BITS = BITS - UPPER_BITS

primes = [ 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659]

remainders = [set([x for x in range(p)]) for p in primes]

def prod(L):
    val = 1
    for x in L:
        val *= x
    return val

def get_lower():
    r.recvuntil(b"> ")
    r.sendline(b"1")
    r.recvuntil(b"> ")
    r.sendline(b"10")
    return [int(r.recvline()) for _ in range(10)]

def get_nc():
    r.recvuntil(b"> ")
    r.sendline(b"2")
    r.recvuntil(b"n : ")
    n = int(r.recvline())
    r.recvuntil(b"c : ")
    c = int(r.recvline())
    return n, c

def rsa_high_bits_known(n, c, upper):
    F.<x> = PolynomialRing(Zmod(n), implementation='NTL'); 
    pol = x - upper
    beta = 0.48  # we should have q >= N^beta
    XX = 2 ** LOWER_BITS
    epsilon = beta / 7
    rt = pol.small_roots(XX, beta, epsilon)  
    q = int(gcd(rt[0] - upper, n))
    p = int(n) // int(q)
    assert(p*q == n and p > 1 and q > 1)
    phi = (p-1)*(q-1)
    e = 0x10001
    d = int(pow(e, -1, phi))
    plain = int(pow(c, d, n))
    print(long_to_bytes(plain))

#### STEP 1. Recover UPPER using crt ####
print("[+] STEP 1. Recover UPPER using crt")
crt_a = [0]
crt_m = [2**LOWER_BITS]

cnt = 0
while prod(crt_m) < 2**BITS:
    cnt += 1
    if cnt % 10 == 0:
        print(f"Gather {cnt*10} primes.. progress : {int(100 * (math.log2(prod(crt_m))-LOWER_BITS) / UPPER_BITS)}%")
    lowers = get_lower()
    for lower in lowers:
        for i in range(len(primes)):
            rem = lower % primes[i]
            if rem in remainders[i]:
                remainders[i].remove(rem)
                if len(remainders[i]) == 1:
                    crt_a.append(primes[i] - remainders[i].pop())
                    crt_m.append(primes[i])

upper = crt(crt_a, crt_m)
print(f"[+]UPPER = {upper.hex()}")

#### STEP 2. Recover FLAG using RSA Factoring with high bits known attack ###
print("[+] STEP 2. Recover FLAG using RSA Factoring with high bits known attack")
n, c = get_nc()
rsa_high_bits_known(n, c, upper)

위 코드는 solver barkingdog의 풀이 코드로 본 문제 이해에 있어 많은 도움이 되었습니다.

추후 시간이 남는다면 풀이 코드에 대한 해설도 적어보도록 하겠습니다.

암호는 너무 어려운거 같습니다...

'Challenge > CTF' 카테고리의 다른 글

[dvCTF] CyberStreak v2.0  (0) 2022.03.14
[dvCTF] RSA  (0) 2022.03.14
[CODEGATE2022] CAFE  (0) 2022.03.05
[MHSCTF] Erlenmeyer Biscuits (Cuppa Joe 2)  (0) 2022.02.23
[MHSCTF] Cuppa Joe  (0) 2022.02.20

decription

 

CODEGATE2022 문제입니다.

 

Description :

You can enjoy this cafe :)

upload text, youtube, ...

 

본 사이트에서 텍스트 업로드 유튜브 등 사용하여 보세요 :) 라고 설명하고 있습니다.

이때만 해도 업로드란 단어에 포커싱이 되어 파일 업로드로 푸는 문제인줄 알고 착각하였습니다.

 

문제 분석

index

login, search, write 등 많은 기능들이 존재합니다.

write에서 파일 업로드를 수행하는 줄 알고 접근하였으나 실패하여 코드를 살펴보았습니다.

 

 

code

그 중 bot.py가 존재하는 것을 보고 이를 살펴보았습니다.

코드는 다음과 같았습니다.

 

#!/usr/bin/python3
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time
import sys

options = webdriver.ChromeOptions()

options.add_argument('--headless')
options.add_argument('--disable-logging')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--no-sandbox')
#options.add_argument("user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")

driver = webdriver.Chrome(ChromeDriverManager().install(),options=options)
driver.implicitly_wait(3)

driver.get('http://3.39.55.38:1929/login')
driver.find_element_by_id('id').send_keys('admin')
driver.find_element_by_id('pw').send_keys('$MiLEYEN4')
driver.find_element_by_id('submit').click()
time.sleep(2)

driver.get('http://3.39.55.38:1929/read?no=' + str(sys.argv[1]))
time.sleep(2)

driver.quit()

의도치 않게 표기되어 있는 admin 계정의 id와 pw를 확인하게 되었습니다.

 

driver.find_element_by_id('id').send_keys('admin')
driver.find_element_by_id('pw').send_keys('$MiLEYEN4')

 

 

flag

이를 사용하여 로그인을 진행하였더니 flag를 확인할수 있었습니다.

 

'Challenge > CTF' 카테고리의 다른 글

[dvCTF] RSA  (0) 2022.03.14
[Codegate2022] PrimeGenerator  (0) 2022.03.07
[MHSCTF] Erlenmeyer Biscuits (Cuppa Joe 2)  (0) 2022.02.23
[MHSCTF] Cuppa Joe  (0) 2022.02.20
[MHSCTF] James Harold Japp  (0) 2022.02.20

Erlenmeyer Biscuits (Cuppa Joe 2)

mhsctf2022 Web 문제입니다.

 

Description :

You remember that coffee shop that just opened up, Cuppa Joe? Well there's now a competitor shop that's opening up across from them! It's called Erlenmeyer Biscuits, and here is their website. I really don't want Cuppa Joe to go out of business, so do you think you could dig up some dirt on Erlenmeyer Biscuits to stop them from opening? mhsctf-erlenmeyer-biscuits.0xmmalik.repl.co (you may need to wait for the site to wake up)

 

경쟁 카페의 웹사이트가 생겼습니다. 경쟁 카페로부터 flag를 획득해야됩니다.

 

 

문제 분석

index-page

웹 페이지 첫화면입니다.

이 페이지의 화면과 소스코드 말고는 다른 정보가 없었기에 우선 cookie 부터 확인해보았습니다.

 

cookie

cookie에 session으로 설정되어 있는 값을 확인하였고 형식을 토대로 짐작했을때 JWT로 짐작하였습니다.

 

 

문제 풀이

확인된 JWT token을 decode 하였습니다.

flag 값이 확인되었습니다.

 

더보기

flag{fl45k_s35510n_c00k13s_4r3_1n53cure}

 

 

'Challenge > CTF' 카테고리의 다른 글

[Codegate2022] PrimeGenerator  (0) 2022.03.07
[CODEGATE2022] CAFE  (0) 2022.03.05
[MHSCTF] Cuppa Joe  (0) 2022.02.20
[MHSCTF] James Harold Japp  (0) 2022.02.20
[MHSCTF] Crash Hacker (Em Dee 2)  (0) 2022.02.20

+ Recent posts