1. ๋ฌธ์ œ 

https://dreamhack.io/wargame/challenges/330

[wargame.kr] crack crack crack it

Description .htaccess crack! can you local bruteforce attack?

dreamhack.io

 

2. ํ•ด๊ฒฐ ๊ณผ์ • 

(1) ๋ฌธ์ œ ํŽ˜์ด์ง€ ํ™•์ธ 

htpasswd ํŒŒ์ผ์„ ๋ถ„์„ํ•ด์„œ Brute Force๋ฅผ ํ†ตํ•ด ํŒจ์Šค์›Œ๋“œ๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค. 

 
htpasswd ํŒŒ์ผ์€ ์ผ๋ฐ˜์ ์œผ๋กœ HTTP ์ธ์ฆ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ํŒŒ์ผ์ด๋‹ค. $์•Œ๊ณ ๋ฆฌ์ฆ˜$์†”ํŠธ$ํ•ด์‹œ๋œ๋น„๋ฐ€๋ฒˆํ˜ธ์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. 
์ด๋•Œ ํŒจ์Šค์›Œ๋“œ๋Š” ํ•ด์‹œํ™”๋˜์–ด ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— G4HeulB๋กœ ์‹œ์ž‘ํ•œ๋‹ค๋Š” ํžŒํŠธ๋ฅผ ํ†ตํ•ด ์ตœ๋Œ€ํ•œ ํšจ์œจ์ ์œผ๋กœ ๋ธŒ๋ฃจํŠธ ํฌ์Šค ๊ณต๊ฒฉ์„ ์‚ฌ์šฉํ•ด์„œ
๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค. 

  • username:$1$saltvalue$hashed_password :
    • MD5: $1$๋กœ ์‹œ์ž‘
  • username:$sha1$saltvalue$hashed_password
    • SHA-1: $sha1$๋กœ ์‹œ์ž‘์ „์ฒด ํ•ด์‹œ ๋ฌธ์ž์—ด์€ ๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค: $์•Œ๊ณ ๋ฆฌ์ฆ˜$์†”ํŠธ$ํ•ด์‹œ๋œ๋น„๋ฐ€๋ฒˆํ˜ธ
  • username:$2y$10$saltvalue$hashed_password
    • bcrypt: $2y$ ๋˜๋Š” $2a$๋กœ ์‹œ์ž‘ (๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฆ„)

์ผ๋ฐ˜์ ์œผ๋กœ MD5, SHA-1, bcrypt ๋˜๋Š” APR1(MD5 ๋ณ€ํ˜•) ๋“ฑ์˜ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋Š”์ง€
์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค. htpasswd ํŒŒ์ผ์—์„œ ํ™•์ธ๋œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹œ ๊ฐ’์€ $1$RF1ij51F$f7Ak1R4/gX3WOI9gliA981์ด๋ฉฐ, ์ด๋Š” MD5-Crypt (APR1-MD5) ํ•ด์‹œ ๋ฐฉ์‹์ด๋‹ค.

blueh4g:$1$RF1ij51F$f7Ak1R4/gX3WOI9gliA981

 

  • $1$ : MD5 ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์‹๋ณ„์ž
  • RF1ij51F : salt ๊ฐ’
  • f7Ak1R4/gX3WOI9gliA981 : ์‹ค์ œ ํ•ด์‹œ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ

(3) ์ต์Šคํ”Œ๋กœ์ž‡

๊ฐ„๋‹จํ•˜๊ฒŒ ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋‹ค. 
๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ๊ธธ์ด๋ฅผ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋‹จ +10๊นŒ์ง€(์ด 17์ž)๋กœ ๊ฐ€์ •ํ•˜๊ณ  ์ง„ํ–‰ํ•˜์˜€๋‹ค.

import crypt
import string
import itertools
import time
# htpasswd ํŒŒ์ผ ๋‚ด์šฉ
htpasswd_line = "blueh4g:$1$RF1ij51F$f7Ak1R4/gX3WOI9gliA981"
# ์‚ฌ์šฉ์ž๋ช…, ํ•ด์‹œ ์ถ”์ถœ
username, password_hash = htpasswd_line.strip().split(':')
print(f"์‚ฌ์šฉ์ž๋ช…: {username}")
print(f"๋น„๋ฐ€๋ฒˆํ˜ธ ํ•ด์‹œ: {password_hash}")
# ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 'G4HeulB'๋กœ ์‹œ์ž‘
password_prefix = "G4HeulB"
print(f"๋น„๋ฐ€๋ฒˆํ˜ธ ์ ‘๋‘์‚ฌ: {password_prefix}")
# ๋ธŒ๋ฃจํŠธํฌ์Šค์— ์‚ฌ์šฉํ•  ๋ฌธ์ž ์ง‘ํ•ฉ (์ˆซ์ž ๋ฐ ์†Œ๋ฌธ์ž)
charset = string.digits + string.ascii_lowercase
print(f"์‚ฌ์šฉํ•  ๋ฌธ์ž ์ง‘ํ•ฉ: {charset}")
def test_password(password, password_hash):
    """์ž…๋ ฅ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ•ด์‹œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ"""
    # ํ•ด์‹œ์—์„œ ์†”ํŠธ ๊ฐ’ ์ถ”์ถœ
    salt = password_hash.split('$')[2]
    full_salt = f"$1${salt}$"
    
    # ์ž…๋ ฅ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ํ•ด์‹œ ์ƒ์„ฑ
    test_hash = crypt.crypt(password, full_salt)
    
    return test_hash == password_hash
def brute_force():
    """๋ธŒ๋ฃจํŠธํฌ์Šค ๊ณต๊ฒฉ ์ˆ˜ํ–‰ (๋น„๋ฐ€๋ฒˆํ˜ธ ์ฐพ๊ธฐ)"""
    start_time = time.time()
    attempts = 0
    
    print("๋ธŒ๋ฃจํŠธํฌ์Šค ๊ณต๊ฒฉ ์‹œ์ž‘")
    # ๋น„๋ฐ€๋ฒˆํ˜ธ ๋’ท๋ถ€๋ถ„ 1-10๊นŒ์ง€ ์ฆ๊ฐ€
    for length in range(10):  
        print(f"{length}์ž๋ฆฌ ์ถ”๊ฐ€ ๋ฌธ์ž๋ฅผ ํฌํ•จํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์‹œ๋„ ์ค‘...")
        
        for suffix in itertools.product(charset, repeat=length):
            suffix_str = ''.join(suffix)
            password = password_prefix + suffix_str
            attempts += 1
            
            if attempts % 100000 == 0:
                elapsed = time.time() - start_time
                print(f"{attempts}๊ฐœ์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์‹œ๋„ํ•จ ({elapsed:.2f}์ดˆ ๊ฒฝ๊ณผ). ํ˜„์žฌ ์‹œ๋„ ์ค‘์ธ ๋น„๋ฐ€๋ฒˆํ˜ธ: {password}")
            
            if test_password(password, password_hash):
                elapsed = time.time() - start_time
                print(f"\n๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค! {attempts}๋ฒˆ ์‹œ๋„ ํ›„ {elapsed:.2f}์ดˆ ๊ฒฝ๊ณผ")
                print(f"์ฐพ์€ ๋น„๋ฐ€๋ฒˆํ˜ธ: {password}")
                return password
    
    elapsed = time.time() - start_time
    print(f"\n๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด {attempts}๋ฒˆ ์‹œ๋„, {elapsed:.2f}์ดˆ ๊ฒฝ๊ณผ.")
    return None
if __name__ == "__main__":
    found_password = brute_force()
    
    if found_password:
        print(f"\n์„ฑ๊ณต! {username}์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š”: {found_password}")
    else:
        print("\n๋น„๋ฐ€๋ฒˆํ˜ธ ์ฐพ๊ธฐ ์‹คํŒจ")

 
[๊ฒฐ๊ณผ]

 
ํ”Œ๋ž˜๊ทธ ํš๋“ ์„ฑ๊ณต ><

mnzy๐ŸŒฑ
-->