제목이 굉장히 길다.. 작명같은거에 센스가 없는게 여기서 여실히 드러나는 ㅠㅠ
로그인 로직은 저번에 작성한 글에서의 설명과 이어서 공부해보자
쿠키와 세션 / 로그인 로직
HTTP는 연결성이 없다. 하지만 로그인을 할 때 사용자가 아이디와 비밀번호를 보내면 A 사용자와 B 사용자를 구분할 수 있어야 한다. 로그인은 동적 페이지이기 때문에 웹 서버가 WAS로 데이터를
ragdo11.tistory.com
우선 식별과 인증이라고 했는데 식별과 인증이 정확히 무엇인가!
식별은 그 사람의 정보를 가져오는 것이라고 하였고 인증은 그 사람의 정보가 맞는지 확인하는 것이라 했다.
이것만으로도 SQLi를 수행하는데는 전혀 문제가 없지만 여기서 접근통제의 개념을 살짝만 정리하고 가보자
Access Control, 즉 접근통제는 주체(외부에서 접근하는 사람, 시스템 등)가 객체(접근대상이 되는 수동적인 개체 혹은 행위가 일어날 아이템)에 접근할 때 보안상의 위협, 변조 등과 같은 위험으로부터 객체와 제반 환경을 보호하기 위한 보안대책을 말한다.
이러한 접근통제는 식별, 인증, 인가의 3단계를 원칙으로 구성되는데 이곳에서 나온 개념이 로직에서 사용되는 것이다.
식별은 인증 서비스에 자신이 누구인지를 밝히는 신원 정보를 제공하는 것이다. 그렇기 때문에 식별 정보는 항상 unique한 값이어야 하고 아이디가 이에 속해서 다른 사용자가 같은 아이디로 계정을 만들 수 없는 것! 추가로 unique한 특성 때문에 accountability에 중요한 역할을 한다.
인증은 주체의 신원을 검증하기 위한 증명 활동이다. A라는 사용자가 자신이 A임을 시스템에게 아무리 말을 해봤자 증명할 방법이 없으니 이를 비밀번호같은 타인이 알 수 없는 매체를 활용하여 증명을 하는 것이다.
이렇게 증명이 된 사용자는 시스템에 의해 접근이 허용하는 인가 과정을 받는다. 관리자로 들어오면 그 시스템의 거의 모든 부분에 접근할 수 있는 권한을 받을 것이고, 외부 사용자들은 일반적인 other의 권한을 받을 것이다. 이러한 과정이 인가이다.
이제 본론으로 들어와서 그럼 식별과 인증을 동시에 하는 로그인 로직이 뭐냐??
SQL 질의문 한 번으로 식별과 인증을 동시에 한다! 라고 저번 글에서 아주 잘 썼다.
그럼 이러한 곳에서는 어떻게 SQLi를 할 수 있을까?
우선 SQLi를 하기 전에 가장 먼저 해야할 것은 당연히 취약점이 존재하는지 부터 알아봐야 한다.
취약점이 존재하면 서버가 어떠한 형태로 SQL문을 사용할지도 떠올려 본다. 이번에는 식별과 인증을 동시에 하는 형태이므로
select * from member where id = 'user' and pw = '1234'
이러한 형태가 될 것인데.. 눈여겨 봐야 하는 곳은 어딜까?
그곳은 where 절이다. 뭐가 됬든 간에 where 절이 참이기만 한다면 저 SQL문은 참이 될 것이다.
where 절이 참이 될 수 있게끔 id에 변화를 줘보면 대표적으로
id = user' or '1'='1
id에 저 구문을 삽입하는 방법이 있다. 이는 or '1'='1' 이라는 항상 참이 되는 식을 넣어 뒤의 pw가 맞지 않더라도 참이 된다.
select문에 넣으면 아래와 같은 형태가 된다.
select * from member where id = 'user' or '1'='1' and pw = '1234'
and의 우선순위가 더 높으므로 '1'='1' and pw = '1234'가 계산이 될 것이고 pw가 맞지 않기 때문에 저 식의 결과는 False이지만 id = 'user' or FALSE 에서 보면 id가 user인 계정이 있으므로 이는 참이 되어 user로 로그인하게 된다.
아예 주석을 넣어 식을 무력화할 수도 있다.
select * from member where id = 'user' # and pw = 'blah'
#의 주석처리 때문에 비밀번호 검증을 하지 않고 아이디 만으로 로그인이 되어버린다!
그럼 실제로 어떤 식으로 적용되나 한 번 보도록 하자
id가 cat이고 패스워드가 ragdoll인 유저가 있다고 가정을 하자!
비밀번호를 모르는 공격자 입장에서는 cat이란 아이디로 접속할 수 없을 것이다. (물론 비밀번호가 매우 취약해서 brute force 공격으로 쉽게 털릴 것이다..)
공격자 입장에서 식별과 인증을 동시에 하는 stmt문을 생각해 볼 수 있을 것이다. 위에서 했던 대로 where 절이 참이 되도록 id에 구문을 삽입해보자.
이러면 아래와 같은 SQL문이 생성될 것이다.
select * from member where id = 'cat' or 1=1# and password = '---'
이 경우 and 부분은 주석처리가 되어 인증을 하는 부분이 날라가버리게 되고, where절은 항상 참이 되어 로그인되게 된다. 공격자가 기대할 수 있는 부분은 그럼 cat이란 유저로 로그인이 되는 거겠지 흐흐흐!! 겠지만..
실제 로그인이 되는 유저는 cat이라는 유저가 아니라 111이라는 유저였다. 왜 이런 현상이 발생하게 된 걸까?
다시 위의 SQL문을 보게 되면 where절 자체가 그냥 참이라는 값이 되기 때문에 member 테이블의 모든 컬럼들을 불러오게 되고 그 중에 제일 위의 값인 111 유저로 로그인되게 되는 것이다.
실제 DB를 보자면 위와 같은 형태로 입력했을 때 where절이 참이 되면서 모든 컬럼이 나오고, 첫 번째 칼럼으로 아이디가 111인 컬럼이 있다.
그럼 cat이라는 유저로 로그인하고 싶으면 어떻게 해야 할까?
마지막에 꼭 True를 만드는 식을 넣지 않고 주석만으로 무력화하는 것을 알아봤었는데 그 방식을 이용하면 원하는 아이디로 우회가 가능하다.
select * from member where id='cat'# and password='123'
위와 같이 넣어주면 where 절에 id가 cat인 컬럼을 찾게 되어 cat이라는 유저로 로그인할 수 있게 된다.
+++(6/11) 추가
물론 guessing 능력이 뛰어(?)나거나, 테이블명과 컬럼명을 알고 있다면(그럴리 없겠지만) 서브쿼리 형식으로도 로그인 우회가 가능하다.
ID : admin
PW : '+(select password from users where username='admin')+'
깔끔하게 로그인 성공
'SQL Injection > SQL Injection' 카테고리의 다른 글
Union Based SQLi (0) | 2024.06.13 |
---|---|
식별과 인증 동시/분리 처리 + Hash 실습 파트 (0) | 2024.06.11 |
식별과 인증 동시/분리 처리 + Hash (0) | 2024.06.11 |
식별과 인증을 분리해서 검사하는 로직에서의 SQLi - 2 (1) | 2024.06.11 |
식별과 인증을 분리해서 검사하는 로직에서의 SQLi - 1 (0) | 2024.06.11 |