profile-image
Waterticket
개발

비밀번호 취약점 체크 애드온

비밀번호의 유출 전적을 조회해주는 애드온입니다
개발

비밀번호 취약점 체크 애드온

비밀번호의 유출 전적을 조회해주는 애드온입니다


https://haveibeenpwned.com/Passwords

Have I Been Pwned allows you to search across multiple data breaches to see if your email address or ...

 

비밀번호가 유출되었는지 알려주는 사이트이다.

 

image.png

 

거대한 데이터에 구미가 댕겨 이걸 사용해 비밀번호가 유출이 되었는지 회원가입 과정에서 알려주는 프로그램을 짜보고자 했다.

 

image.png

 

압축을 풀어보니 25GB 상당의 거대한 데이터가 나왔다.

 

image.png

 

너무 거대해 일반적인 텍스트 에디터로는 열리지 않아 HEX 에디터를 사용해 열었다.

 

image.png

 

데이터 구조는 이와 같게 생겼다

SHA1(40byte):유출횟수(int)

 

image.png

 

 

이를 분석하여 DB에 직접 넣어주었다. (초당 2천줄 꼴로 들어갔다.)

+) 데이터를 집어넣을때는 인덱스를 먼저 넣을경우 엄청 느려진다..
데이터를 전부 집어넣고 인덱스를 후에 설정해줘야한다.
 

image.png

 

image.png

 

INSERT는 오래걸리더라도 바로바로 원하는 값이 존재하는지 찾아주어야 하기에 약간의 생각을 하였다.

SHA_FIELD 항목에 앞 다섯 글자를 빼내어 인덱스로 해준다면 LIKE 를 사용해 빠르게 쿼리를 할 수 있을것이라고 생각을 하였고, 이를 위해 SHA_FIELD(5) 만큼 빼내어 인덱스로 지정해주었다.

인덱스는 해당 컬럼의 분산도(카디널리티)가 높을 수록 유용하게 쓰이기 때문에 해시값에 적당하다고 판단하였다.

 

실시간으로 DB에서 해시값을 가져와야 하기 때문에 쿼리가 매우 중요하다

먼저 쿼리를 가져오는 부분을 코딩할 때 데이터들은 INSERT작업중이였고 아직 COMMIT이 되지 않은 데이터들이라 불러오는 것이 불가능 했다.

이는 그냥 몇 일 기다리면 해결되는 문제였으나 나중에 많은 커넥션이 동시에 들어오면 DB가 block상태가 되어 뻗어버리는 일도 일어날 수 있다.

위 두 문제를 해결하기 위해 트랜잭션 레벨이라는 것을 알게 되었다.

READ UNCOMMITTED

1) COMMIT 되지 않은 데이터에 다른 트랜잭션에서 접근할수 있다.

2) INSERT, UPDATE, DELETE 후 COMMIT 이나 ROLLBACK에 상관없이 현재의 데이터를 읽어온다.

3) ROLLBACK이 될 데이터도 읽어올 수 있으므로 주의가 필요하다.

4) LOCK이 발생하지 않는다.

READ COMMIITED

1) COMMIT 된 데이터에 다른 트랜잭션에서 접근할 수 있다.

2) 구현 방식이 차이 때문에 Query를 수행한 시점의 데이터와 정확하게 일치하지 않을 수 있다.

3) LOCK이 발생하지 않는다.

4) MySQL에서 많은 양의 데이터를 복제하거나 이동할 때 이 LEVEL을 추천한다.

REPEATABLE READ

1) Default LEVEL이다.

2) SELECT시 현재 시점의 스냅샷을 만들고 스냅샷을 조회한다.

3) 동일 트랜잭션 내에서 일관성을 보장한다.

4) record lock과 gap lock이 발생한다.

5) CREATE SELECT, INSERT SELECT시 lock이 발생한다.

원래는 SELECT던 INSERT던 해당 상태를 스냅샷한 부분에서 데이터를 읽어온다.

순차적으로 처리하기 위해서인데, 이렇게 되면 한 세션에서 데이터를 읽거나 쓰고 있다면 해당 DB는 블럭상태가 되어버린다.

그러면 해당 DB에서는 블럭상태일동안 읽지 못하게 되고, 이를 해결하기 위해 READ UNCOMMITTED를 사용하기도 한다.

물론 이렇게 해결하는것이 절대 좋은 방법이라고 할 수는 없으나, 내가 데이터를 저장한 테이블에 경우 INSERT가 초반을 제외하고는 없으며 단순히 읽기만 하면 되기 때문에 위 방법을 사용하기로 했다.

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

위와같이 설정해주면 된다.

다음으로 데이터를 가져올때 쿼리이다.

SELECT SHA_FIELD, DATACNT FROM PasswordHash WHERE SHA_FIELD LIKE ?

위와 같이 SHA_FILED와 LIKE를 활용하여 인덱스를 탈 수 있도록 하였다.

'?' 에는 SHA 쿼리에 앞 5글자를 잘라낸 다음 뒷자리에 %를 썼음

ex) 'ABCDE%'


image.png

 

위와같이 check.php를 넣었다.

image.png

 

데이터를 가져오기 성공

 

image.png

JSON으로 보내주었다.

※ 클라이언트

 

image.png

1차 비밀번호 체크

 

image.png

ajax를 통한 비밀번호 유출 확인


※ 결과

 

image.png

기본적으로 비밀번호 폼은 위와같이 생겼다.
 

 

image.png

비밀번호 조건을 만족하지 못했을 경우 '비밀번호를 확인해주세요.' 라는 메세지가 나온다.
 

 

3.gif

비밀번호 조건을 만족했을 경우 sha1 암호화를 하여 서버로 쿼리를 날리게 된다.

쿼리를 체크하여 비밀번호 해시값이 존재하면 '이 비밀번호는 위험합니다! 유출 횟수: xxx회' 와 같이 위험 메세지가 나온다.

 

 

image.png

그리고 안전한 비밀번호를 입력했을 경우 이 비밀번호는 안전합니다 라고 뜨며 초록색으로 바뀌게 된다.

 


image.png

 

 

image.png

4일간 데이터를 집어넣었다.

 

image.png

쿼리타임 0.2초


https://xetown.com/tips/1591828

https://xetown.com/topics/1591321 위 글을 보고 도움이 될 것 같아 만들었습니다 기본적으로 회원가입 폼...
XETOWN - 리버스 / 2021-07-12

 

Waterticket by
Waterticket
 관리그룹 

항상 열일하는 개발자 Waterticket입니다!

 

외주 의뢰나 취업 제안 등 문의사항은 아래 연락처로 연락바랍니다~

 

이메일 : matthew218@naver.com

사이트 : https://shop.hoto.dev/cs

블로그 : https://blog.naver.com/matthew218

댓글
    0
검색어 입력
전체검색, 사이트 전체를 검색합니다.