[ CAPTCHA 공격이란? ]
컴퓨터가 알 수 없는 흘려 쓴 글씨 등을 이용하여 이를 제대로 인식하면 사람이라고 확인하는 것이다. 회원가입이나 비밀번호와 같이 사람이 직접 하지 않을때, 문제가 발생할 경우에 주로 사용된다. 브루트포스 공격과 같이 프로그램을 이용한 공격에 대응할 때 매우 효과적이다.
하지만 제대로 구현하지 않는다면, 해커는 이를 우회하여 공격할 수 있다.
그림을 통해 자세히 알아보자. 비밀번호 단계는 총 두 단계로 진행된다.
우선 CAPTCHA를 통해 사람인지 확인한다. 확인이 된 이후에는 두번째 단계에서 비밀번호를 변경한다. 하지만 이 과정이 제대로 구현되어 있지 않다면 해커가 CAPTCHA를 확인한 것처럼 꾸미고 두번째 단계만 진행하여 비밀번호를 변경하는 것이 가능하다.
[ CAPTCHA 공격 실습 ]
로우 단계)
CAPTCHA 공격 과정을 자세히 살펴보기 위해 프록시의 HTTP History 부분을 활용한다.
DVWA 카테코리 중 CAPTCHA 를 클릭하여 기존 dvwa의 현재 비밀번호와 아래 그림에 표시되어있는 문자를 입력한다.
입력한 후 CAPTCHA가 확인되었다는 문구를 볼 수 있음. 이때의 요청을 살펴보자.
Step 파라미터에 1이라는 값이 설정되어 있고 바로 옆 password 파라미터에는 우리가 입력해주었던 normal 값이 있는 것을 볼 수 있다. recaptcha_challenge_field 는 captcha 확인 시, 계속 랜덤으로 생성되는 값을 말한다. recaptcha_response_field 에는 입력한 captcha 값이 설정되었다.
※ CAPTCHA 업데이트 이후, recaptcha_challenge_field, recaptcha_response_field 파라미터 대신 g-recaptcha-response가 전송된다. (우회공격 실습에는 영향 X)
여기서 step 파라미터 값이 1인것에 주목하고 dvwa의 change 버튼을 누르면 요청이 한번 더 날아가는 것을 볼 수 있다. 다시 발생된 요청의 request 테이블에서 step 파라미터가 2로 변경되었고, password 요청이 한번 더 보내졌다.
따라서 총 요청이 두번 보내졌고, 첫 번째 요청에서 step은 1이며 두 번째 요청은 step은 2로 표시되어 요청 후 전송되었다. 그리고 두 요청 모두 패스워드가 포함되어 전송되었다.
첫번째 요청은 생략하고 두번째 요청만 보낼경우 어떻게 되는지 Repeater 탭을 통해 알아보자.
Repeater 기능을 이용하면 내가 원하는 요청만 보내는 것이 가능하다.
두번째 요청에서 마우스 오른쪽 클릭 후 Send to Repeater 을 누르면 Repeater 탭에서 방금 보낸 요청을 확인할 수 있다.
이때 비밀번호 부분을 normal이 아닌 hacker로 변경해주고 이미지 왼쪽 상단에 있는 Go 버튼을 누르고 응답 부분을 살펴보자. 응답 부분을 확인해보면 비밀번호가 변경되었다는 문구를 볼 수 있었다.
실제로 패스워드가 변경되었는지 DVWA 로그아웃 후 hacker을 비밀번호로 하여 로그인 해본결과, 비밀번호가 변경되었다. 따라서 CAPTCHA 값을 제대로 입력하지 않고, 두번째 요청만 변경하여 패스워드를 변경할 수 있었다.
미디엄 단계)
로우 단계에서와 마찬가지로 실습을 진행해보고 두번째 요청의 Proxy history를 확인해보았다. 그 결과, 나머지 부분은 동일하지만 passed_captcha 부분이 추가된 것을 확인할 수 있었다.
이 요청만 따로 Repeater로 보내어 자세히 확인해보자.
앞서 진행한 로우 단계에서의 실습과 동일하게 패스워드 부분을 hacker로 변경하고 상단의 Go 버튼을 누르고 Response 테이블에 있는 Render 부분을 확인한 결과, 패스워드가 변경된 것을 확인할 수 있었다. 파라미터가 하나 더 추가 되었긴하지만, 로우 단계와 마찬가지로 쉽게 공격이 가능했다.
하이 단계)
이전 실습과 동일하게 비밀번호를 변경하고 CAPTCHA 검증을 거친 후 Proxy의 History를 확인해보았다. 하이 단계에서의 요청 내용을 간단히 살펴보면 password, g-recaptcha-response, user_token 등의 파라미터가 전달되고 있는 것을 확인할 수 있다.
이때 중요한 것은 step 파라미터에서도 알 수 있다시피, 요청이 두번이 아닌 한번으로만 전송된 것을 볼 수 있었다.
하이 단계에서의 소스코드를 살펴보자. 중간 부분에 있는 if 구문을 확인해보면 resp 변수가 참이거나 두개의 추가 조건이 OR 연산으로 묶여있다. resp 변수가 참이라는 것은 captcha가 올바르게 입력된 경우이다.
이때, if 구문의 조건을 확인해보자. 먼저 g-recaptcha-response 가 hidden value 값이고, HTTP_USER_AGENT의 값이 reCAPTCHA 값이어야 한다. 하지만 여기서 resp 변수 뒷부분에 있는 OR 연산으로 인해 resp 변수 값과는 관계없이 즉, CAPTCHA 입력과는 상관없이 공격자가 g-recaptcha-response 파라미터와 USER_AGENT 값을 조작하여 이 조건을 만족시킨다면, CAPTCHA가 올바르게 입력된 것처럼 처리된다.
해당 요청의 Repeater 에서 비밀번호를 normal2로 변경한 후 Go 버튼을 누른 결과 Response의 Render 부분에서 CAPTCHA가 일치하지 않는다는 문구가 표시되었다. 이 부분의 경우 CAPTCHA는 항상 랜덤한 값을 표시하기 때문에 이전에 사용했던 CAPTCHA 값을 넣을 경우 다음과 같이 일치하지 않다는 문구가 출력될 수 있다
이번에는 g-recaptcha-response 파라미터에 hidden value를 입력하고 USER_AGENT에는 reCAPTCHA를 입력하여 준다. 입력 후 GO 버튼을 누르고 Response의 Render을 확인해보니 비밀번호가 바뀌었다는 메시지가 출력된 것을 볼 수 있었다.
요청을 한단계로 만든 것은 좋은 대응방법이었으나, 이와 같이 특정한 값을 if 문으로 검사하여 우회할 수 있는 코드를 넣은 것이 문제가 되었다. 이러한 조건문은 개발자가 디버깅이나 테스트를 할 때 조금 더 간편하게 하기 위해 코드를 넣은 후 나중에 지우는 것을 잊어버린 경우 발생할 수 있다.
[ CAPTCHA 공격 대응 ]
보안 단계를 impossible로 변경한 후, 소스코드를 확인해본 결과, 하이 단계에 있었던 디버깅 조건은 없어진 것을 볼 수 있었다. 오른쪽 사진의 페이지를 보면 CSRF 공격을 대응할때와 마찬가지로 현재 패스워드를 한번 더 입력하도록 되어 있어서 패스워드 변경과 같은 중요한 부분의 보안을 강화하였다.
마지막으로 CAPTCHA 를 확인하는 루틴이 한번에 처리되는 것이 좋다. 만약, 어쩔 수 없이 요청을 여러개로 나누어서 처리해야할 경우 반드시 모든 단계를 정상적으로 통과하도록 구현해야 한다,
[참고자료] 인프런_화이트해커가 되기 위한 8가지 웹 해킹 기술
'Security > Web hacking' 카테고리의 다른 글
XSS 공격 (0) | 2023.01.13 |
---|---|
SQL 인젝션 공격 (1) (0) | 2023.01.09 |
파일 업로드 공격 (0) | 2023.01.08 |
파일인클루젼 공격 (0) | 2023.01.07 |
CSRF 공격 (0) | 2023.01.02 |