※ 자동화 프로그램은 블로그 하단에서 다운로드할 수 있습니다.
1. 코드 분석
일단 서버코드인 app.py 코드를 보면 DB를 사용하지 않고 서버가 처음 켜질 때 정해진 랜덤 변수와 입력한 값인 locker_num와 password를 비교하여 해당 조건에 충족하는 경우 FLAG 또는 Good 을 출력하도록 되어 있다.
그리고 서버 시작 시 rand_str와 rand_num 이 정해지는데,
rand_str는 숫자 또는 영어 소문자 중에 랜덤 4자리, rand_num 은 100과 200 사이 랜덤숫자가 저장되게 된다.
locker_num
일단 처음에 웹사이트 접속 시는 GET으로 접속하기 때문에 GET의 경우 index.html 파일을 그냥 주도록 되어있고,
그 이후 POST로 데이터를 담아 보낼 때문 result 값을 담아서 index.html을 주게 되어있다.
일단 method를 거르는 if문 다음거를 보면,
locker_num 가 비어있지 않고 랜덤으로 만들어진 문자열과 같은 경우 다음 단계로 진행, 아닌 경우 Wrong! 을 출력하도록 되어 있다.
근데 여기서 보면 locker_num와 랜덤 문자열인 rand_str를 그냥 비교하는 게 아닌,
locker_num의 자릿수만큼 rand_str와 비교하게 되어있다.
즉 locker_num이 한자리라면 rand_str의 처음 한자리와 비교하고
locker_num 가 두 자리라면 rand_str의 처음 두 자리끼리 비교하는 것이다.
이것을 파이썬에서 슬라이스 문법이라고 한다.
일단 이게 만족이 되며 locker_num와 rand_str가 같지 않고 password와 rand_num이 같지 않은 경우
Good을 출력하도록 되어 있다.
그리고 만약 locker_num와 rand_str가 같고 password와 rand_num이 같은 경우
FLAG가 출력이 된다.
FLAG를 얻기 위해서는 먼저 rand_str 값을 알아야 하는데,
랜덤 값인 rand_str 값은 코드적으로 알 수 있는 방법이 없다.
그리고 4자리이며 숫자와 영어 소문자가 총 36개 이기에
rand_str 값의 경우의 수는 36^4 = 1,679,616 => 1,679,616개가 된다.
이와 같이 하나하나 다 대입해 보는 공격을 brute force라고 한다.
이거를 1,679,616번 요청해서 brute force 공격으로 답을 얻을 수도 있지만 일단 시간이 엄청 걸리고
드림핵 서버에서 어떻게 처리할지도 의문이다..
그러면 어떤 식으로 해야 할까?
2. rand_str 값 찾아내기
여기서 결정적인 것은 위에서 말한 슬라이스 문법을 잘 활용하는 것이다.
만약 locker_num 값이 한자리라면 rand_str값도 처음 한자리만 비교하고 맞으면 Good을 출력한다.
이 말은 good이 나올 때까지 최대 36번 동안 숫자부터 영어 소문자 z까지 넣어서 요청하면 된다는 것이다.
그러면 rand_str 값의 첫 번째 자리를 알게 된다.
그러면 두 번째짜리는 어떻게 구할까??
첫 번째 자리와 마찬가지로
good이 나올 때까지 최대 36번 동안 숫자부터 영어 소문자 z까지 넣어서 요청하면 된다.
그리고 첫 번째 자리를 위에서 구한 값을 넣어서 보내면 2개의 문자끼리 비교하여
맞는 경우 Good을 출력할 것이다.
이것을 4번 반복하면 총 4자리를 알 수 있다.
그러면 1,679,616번이 아니라 최대 36*4 = 144 => 144번만 요청하더라도 rand_str를 구할 수 있는 것이다.
이렇게 답을 구하는 것 역시 brute force 공격이지만 서버의 취약점을 이용해 더 쉽게 하게 된 것이다.
일단 답을 구하는 경로는 구해졌는데,
그래도 사람이 144번 요청하는 게 안 귀찮을 수가 없다.
이런 경우 javascript 또는 python으로 자동화 프로그램을 만들어 brute force공격을 시도하면 된다.
일단 우리가 지금 하고 있는 문제는 python 서버 기반의 문제이기에
python을 이용하여 만들기로 했다.
brute-locker_num.py를 실행한 장면
이 파일을 다운로드하여 실행시키면 사용할 수 있는데,
이 문제의 경우 각자의 서버 킬 때마다 데이터가 랜덤으로 생성되기 때문에 위에 보이는 영상의 답과
자기가 실행한 서버의 rand_str의 답은 항상 다르다. 이걸 참고하여 직접 본인 서버 URL을 넣고 실행하면 된다.
brute-locker_num.py
0.00MB
그리고 해당 코드의 경우 python으로 실행하고 requests라는 pip을 사용하는데,
이것을 설치해야 하니 가장 하단의 5번 챕터를 보면 할 수 있다. (실행방법도 다 있다.)
진짜 매우 간단하니 해보는 게 좋다.
일단 해당 코드를 조금 설명하자면,
url을 입력받고 해당 url로 locker_num을 바꿔가며 요청을 계속 보내고
Good이라는 글자가 돌아온 데이터 안에 있는 경우 해당 데이터를 가지고 다음 자리 문자를 알아내는 방식이다.
그리고 4개가 모두 완료되었을 때는 최종적으로 알아낸 locker_num의 값을 보여준다.
3. password 구하기
다음으로 locker_num를 구했으면 마지막 if 문을 통과해야 한다.
일단 마지막 if 문의 처음 조건은 이미 알게 되었으니 패스하고
password와 100부터 200 사이의 랜덤 숫자와 같아야 하는 조건이 있다.
이것 또한 랜덤으로 생성하고 비교하는 것이기 때문에 그냥 flag 나올 때까지 brute force 공격을 하면 된다.
100번 정도 하면 되니 이건 무작정 100부터 대입하여 FLAG 가 출력되면 멈추는 python 코드를 만들면 된다.
rand_num의 값 또한 각자 서버마다 다 다르니 직접 자기 서버의 URL을 대입하고 전에 알아낸 locker_num 값도 넣어서 실행하여 알아내야 한다.
실행하고 값을 구하면
locker_num과 password를 알려주는데 이걸로 서버 웹사이트로 들어가서 요청하면 FLAG가 출력된다.
4. 한 번에 구하기 && 최종 flag 얻기
이대로 끝내기는 자동화 프로그램이 한 번에 돌아가면 좋겠다고 생각해서
URL만 입력하면 다 자동으로 구해주도록 두 코드를 결합하였다.
얻은 locker_num와 password 값으로 제출 시 flag 가 출력되는 것을 볼 수 있다.
flag는
DH{2e583205a2555b8890d141b51cee41379cead9a65a957e72d4a99568c0a2f955} 가 된다.
5. python 실행 방법 및 pip 설치 방법
일단 python을 실행하기 위해서는 python 이 컴퓨터에 설치되어있어야 한다.
설치 및 기초 방법은 따로 포스팅을 했으니 참고할 수 있다.
위 코드들 실행 방법은 여러 가지가 있는데,
가장 기초인 터미널(명령프롬프트)을 사용하여 실행할 것이다.
일단 다운로드 한 파일이 있는 폴더를 열어 두고 터미널(명령프롬프트)을 열어 준다.
맥에서 터미널을 여는 방법:
• 단축키 사용: Command + Space 또는 f4를 눌러 Spotlight 검색을 열고, “터미널”을 입력한 뒤 Enter를 누릅니다.
• 또는 애플리케이션 폴더에서 유틸리티 폴더를 찾아 터미널을 선택할 수도 있습니다.
윈도에서 명령 프롬프트(CMD)를 여는 방법:
• 단축키 사용: Windows + R을 눌러 실행 창을 열고, “cmd”를 입력한 후 Enter를 누릅니다.
pip 설치 방법
그리고 이제 requests라는 pip을 설치해야 한다.
(만약 pip 자체가 설치가 안 된 경우 따로 포스팅된 블로그를 확인하거나 구글에 검색하여 설치해 줘야 한다.)
터미털에
pip install requests
또는
pip3 install requests
을 입력 하여 설치하면 된다.
설치 방법
실행 방법
1. python3 또는 python을 넣고 띄어쓰기 후 파일을 드래그하여 파일 위치를 넣고 엔터를 친다.
만약 여기서 오류가 발생한다면 터미널에 chmod +x를 넣고 띄어쓰기 후 파일을 드래그하여 파일 위치를 넣고 엔터를 치고 난 후 처음부터 다시 해 보세요.
2. url 입력창이 나오는데 여기에 자신에게 할당된 서버 주소 전체를 복사하여 넣어준다.
3. 종료는 control + c이다.
gif 변환 과정중 화질이 저하 되었지만 설명으로도 충분히 할수 있습니다! 이해해주세요..^^
이렇게 하면 최종 실행까지 완료되어 flag를 구할 수 있다.
※ 답을 복사하지 말고 위 글을 이해하여 직접 풀어보세요.