CVE-2020-7245: CTFd Account Takeover
최근 GRAPE 해킹 동아리에서 CTF문제 사이트를 공개하였다. CTF 문제사이트를 위한 CTF-D라는 라이브리를 사용하였다. 이에 CTF-D에 취약점이 존재하였는지 확인하다. 간단하지만 재미있는 CVE를 찾게 되었다. 위 CVE는 account takeover vulnerability 이다.
아래 사진은 cve에 대한 트윗이다.
아래사진은 이에 대한 댓글이다.
account takeover vulnerability이 가능했던 이유는 filter_by라는 함수가 공백을 무시하고 필터링하는 점을 인지하지 못하였기 때문이다
아래 사진은 filter_by함수를 leading, trailing space(앞, 뒤 공백)을 테스트 한 결과이다. trailing space만 제거됨.
CVE가 존재하여 패치된 register 함수를 보면 다음과 같다.(로그인 기능)
패치 후 strip() 함수가 새로 생긴 것을 알 수 있다. 즉, 패치 전에 admin이라는 계정이 존재했을 때, admin\x20\x20이라는 계정을 새로 생성하는 것이 가능하다.
reset_password 함수를 보게되면, 패치 전에는 name을 가져와서 역직렬화를 한 뒤, name에 맞는 user를 찾고 이것의 password를 변경하였다.
결론
- admin\x20\x20 이라는 이름과 hackeremail@gmail.com이라는 메일로 아이디를 만든다.
- hackeremail@gmail.com라는 이메일로 password reset(비밀 번호 재설정)을 요청하게 되면, team(사용자)가 존재하는지 확인한다. 당연히 admin\x20\x20라는 이름으로 회원가입을 했기 때문에 아이디가 존재한다.
- 그렇다면, name을 직렬화 한 뒤 url를 만들어서 가입된 이메일로 보내준다.
- URL에 들어가서 비밀번호를 바꾸면 이름을 역직렬화 한 뒤, filter_by함수를 통해서 사용자를 구하고 사용자의 비밀번호를 변경한다. 역직렬한 name은 admin\x20\x20이다.
- 이때 filter_by는 앞서 말했듯이 공백을 무시하기 때문에 name이 admin인 user와 동일한 결과 값을 가져오게 되고, admin이라는 유저가 먼저 가입하였기 때문에 admin에 관련된 데이터베이스가 추출되게 된다.
- 이러한 admin의 데이터베이스를 우리가 입력한 비밀번호를 받아와서 변경한다.
추가적으로 아래 댓글을 분석해보면서, 위 cve가 발생될 수 있는 다른 환경을 찾아보고자 한다. (참고로 TL;DR는 "Too Long; Didn't Read"의 약자로 3줄 요약 이런의미입니다 ㅎㅎ)
다음과 같은 문제가 발생되는 경우는 쉽게 mysql 에서 고정 길이를 사용했을 때 찾아볼 수 있다.
create table hacker(
idx int auto_increment primary key,
id char(10)
);
다음과 같이 char(10)을 사용하게 되면, 10byte의 고정길이가 입렵된다는 소리이다. 만약 10byte 이하로 입력하게 된다면, 남는 바이트만큼 공백으로 채우게 된다(\x20)
또한, mysql에서 공백은 비교시 무시되는데
SELECT * FROM hacker WHERE id = 'admin';
필드에서 오른쪽 공백은 비교 시 무시되므로 ‘admin’과 ‘admin(공백)’은 같은 결과를 가져오게 된다.
그럼으로 만약 mysql 사용하는 웹 사이트가 Trim()과 같은 함수를 사용하지 않고 아이디를 받고 있다면, 위와 같은 CVE가 발생될 수 있다.
출처
https://blog.saika.kr/2020/02/cve-2020-7245-ctfd-account-takeover/
https://github.com/CTFd/CTFd/blob/master/CTFd/auth.py
https://hack-cracker.tistory.com/165