일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 뿌요뿌요2
- 대회 후기
- rounded corner
- SUAPC #낙서장 #대회후기
- 프로그래밍
- UCPC
- Tizen
- Dali
- 콘솔게임
- 메이플스토리2
- ui 그래픽스
- Hinohie
- 알고리즘 #자료구조 #퀵소트 #정렬 #시간복잡도
- 낙서장
- Problem Solving
- PS #문제출제 #알고리즘 #곰곰이
- 뿌요뿌요
- C언어
- 곰곰이
- 이산로그
- 타이젠
- 히노히에
- Today
- Total
히농의 잡합다식
[SCTF 2017 예선] 예선문제 writeup 본문
드디어 이 암호학 Tag에도 뭔가 글을 올릴만한게 생겼네요ㅋㅋㅋ
저번주 토요일. 즉, 2017년 7월 8일에 제 1회 삼성 CTF 대회에 참가를 했습니다.
아침에 일어난 오전 11시부터, 새벽 4시까지 풀고, 더이상 풀 게 없다고 판단하여 일요일에는 던지고 놀았습니다ㅋㅋㅋㅋ
일단 제출한 write_up paper를 같이 올리긴 하겠습니다만.. 문제 설명을 안쓰고 진짜 풀이만 써서 도움이 될지는 모르겠네요
2017_SCTF_write_up_pichulia.pdf
나중에 제가 까먹지 않기 위해서라도 이렇게 기록을 남겨두고자 합니다.
1. DFA
DFA를 구현한 코드를 던져놓고
취약점이 있으니 찾아서 고쳐봐라! 라는 식으로 던져준 문제입니다.
이건 그냥 디버깅 좀 해본 사람이라면 수상한 냄세를 풍기는 곳을 바로 캐치해서
뜌샤뜌샤 했을 문제입니다.
문제에 대해서 설명할건 딱히 없네요.
2. Message
수식 입력에는 역시 ppt만한게 없는거같네요...암튼
서버에 계정을 등록할 때, id를 hashing한 hid값과, 서버 내부적으로 가진 secure vaule인 sk값을 이용해서
계정 고유의 키값인 key(id) 를 위 수식처럼 생성해서 보내줍니다. (key(id) = sk ^ hid)
그리고 로그인할 때 서버는 클라이언트에게 임의의 값 rnd를 보내게 되고,
클라이언트는 자신의 key(id)값에 ^rnd승을 한 값을 서버에 전송합니다. (key_otp_client)
서버가 받은 이 key_otp_client랑, 자신이 계산한 key_otp_server 값이 일치하면 본인인증이 완료되는.. 그런 시스템입니다.
rnd 값을 사용해서 인증하는 이유는...똑같은 사용자가 항상 똑같은 값을 서버에 전송하면, 그 똑같은 값을 토대로 공격자가 거짓인증하는 공격방식을 막기 위함인듯 합니다.
하지만 이 문제같은 경우는, 그 거짓인증을 막기위한 방책이 도리여 독이 된 케이스입니다.
공격자가 알아야할 정보는 임의의 계정에 대한 hid, key 쌍 2개정도. 그리고 공격하고싶은 계정의 hid와, otp에 사용되는 랜덤값 rnd입니다.
만약 공격자가 계정 2개에 대해 hid(id)와 key(id)값을 알고있다고 가정해봅시다. 그 hid값을 각각 a와 s, b와 t라고 가정해봅시다.
공격자가 거짓인증을 하고싶은 id의 hid값과 rnd값의 곱셈 결과를 a와 b의 합으로 표현할 수 있다면 key_otp_server 값을 s와 t의 곱으로 표현할 수 있게 됩니다.
그걸 ax + by = hid(id) * rnd 형태로 표현됐다면 s를 x번, t를 y번 곱한 값은
key_otp_server랑 일치하게 됩니다.
만약 rnd값 없이 그냥 hid(id) 만으로 인증을 했다면 ax + by = hid(id)를 만족하는 x, y 가 양의 정수중에서는 없게 됩니다. 그렇다고 위의 공격을 막기 위해서 rnd 범위를 줄인다면 그건 그것대로 문제가 될 수 있습니다... 어렵네요
3. Broken Window
문제 내용을 설명하자면... rsa 암호화하는 과정에서 생기는 exp 함수의 계산 중간과정의 값을 조작해버리는 짓이 가능한 특수한 상황일 때 메세지를 복호화 하는 것이 가능한지를 묻는 문제이다.
exp(m, d, dep) {
p = exp(m, d/256, dep - 1);
q = m ^ (d%256);
if(dep == attack_byte)
q ^= 0xff;
return p^256 * q;
}
만약 중간과정에 attack_byte에 의한 변형이 생겼다면 결과값도 우장창창 달라질 것이다.
메세지 m이 주어지고,
이 m에 대해서 exp(m,d,127)결과값고,
attack_byte = 0 ~126일 때의 결과값 127개가 주어졌을 때
d값을 구하는 문제이다.
자세한 풀이는 write_up에 적어넣긴 했지만..
attack_byte = 0일 때 공격을 시도해볼만한 경우의 수가 256가지밖에 없기 때문에 모든 경우를 시도해보면 구하고자하는 d값의 상위 8bit를 구할 수 있게 된다.
이렇게 되면 attack_byte = 1 일 때 시도해볼 경우의 수도 256가지로 줄어들게 되고, 그 결과 d값의 상위 16bit를 알게 된다.
---------------------------------------------------------------------------------
내가 푼 문제 2개가 다 a^b을 이용한 암호화를 뚫는 공격들이였다.
파이선 언어도 써본적 없어서 허둥지둥 배껴쓴 코드들로 풀만한게 저런것들 뿐이였으니...
암튼 재밌는 경험이였다. 본선가서도 이 운빨이 통할련지..