DolDol 계정만 출력

DATE : 2023/12/03

여기, 비밀번호를 입력하면 해당 비밀번호를 사용하는 계정 정보를 보여주는 시스템이 있다.

이번 POST에서는 normaltic이 아닌 doldol 계정만 출력하는 게 목표이다.

일단 우리가 비밀번호를 입력했을 때, 어떤 Query가 실행될 지 예측해보자.

PASSWORD : 1234

> QUERY : SELECT id, passwd, mail, rand from member where passwd = '1234'

화면에 보여지는 결과만 고려했을 때, 총 4개의 COLUMN 정보를 가져올 것이라 추측했고

정보를 꺼내오는 Table을 member라고 가정해보면

아마 passwd가 1234인 ROW를 찾아오는 게 아닐까 싶었다.

정답을 확인해보자!

서버에서 실행되는 Query를 확인해보면 member Table에서

id가 normaltic인 동시에 pass가 1234인 ROW를 조회하라는 내용이 적혀 있다.

아! 일단 서버에서 실행되는 Query는 id 또한 고려하고 있었으며

ROW의 모든 column 값을 가져 오고 있음을 볼 수 있다. (SELECT *)

(추가적으로 member Table에는 id & pass column이 있음을 짐작할 수 있다.)

그럼 이제 어떤 Query가 실행되는지 확인했으니 SQL injection이 가능한 지의 여부를 확인해보자.

SELECT * FROM member WHERE id='normaltic' and pass='___'

현재 작성되어 있는 Query에 우리가 주입할 수 있는 부분은 pass 값으로

어떤 Query를 넣어야 결과가 달라짐을 확인할 수 있을 지 고민해 봐야 한다.

PASSWORD : ' or '1'='1
SELECT * FROM member WHERE id='normaltic' and pass='' or '1'='1'

만약 비밀번호 값에 항상 참인 조건을 or 연산으로 주입한다면 어떤 일이 벌어질까??

비밀번호가 공백인 동시에 id가 normaltic인 ROW가 없기 때문에, and 연산의 결과는

id = 'normaltic' and pass=''

false가 될 것이다.

이어서

false or '1'='1'

은 false or true이기 때문에 결과는 true로 member Table에 있는 모든 ROW가 나올 것이라 예측할 수 있다.

실제로 값을 넣어보면 총 4명의 정보가 나오는 걸 확인!!

이 중에서 우리는 doldol의 정보만 출력하는 게 목표이다.

여러 개의 ROW가 결과로 나오는 와중 어떻게 하면 특정 위치의 ROW만 골라낼 수 있을까??

limit start, number

이런 상황에서 사용할 수 있는 게 바로, LIMIT이다.

limit는 총 2개의 값이 뒤따라 오는 형태로 사용되는 데 이때

start는 여러 ROW 중에서 몇 번째를 시작 위치로 삼을 것 인지 나타내는 값이고,

number는 시작 위치를 기준으로 몇 개의 ROW를 가져와야 하는 지 개수를 나타내는 값이다.

즉 LIMIT는 start 위치의 ROW부터 총 number 개수 만큼만 결과를 가져오도록

제한 시키는 기능이 필요할 때 사용할 수 있다.

그렇다면, 총 4개의 ROW가 나오는 결과에서 제일 위에 있는 doldol의 ROW만 가져오도록 제한하려면

SELECT * FROM member WHERE id='normaltic' and pass='' or '1'='1' limit 0,1

이와 같이 SQL을 주입하면 될 거 같다!

여기서 사용된 limit는 결과의 제일 첫 번째 ROW부터 1개만 가져와라!는 의미이기 때문에

첫 번째 ROW만 해당이 될 것이다.

값을 주입해 결과를 확인해보면 예측한 대로 doldol의 계정 정보만 나오는 것을 볼 수 있다!

우리의 목표는 이걸로 성공..! 이지만 번외로 두 번째에 위치한 fake 계정의 정보만

출력하고 싶다면 어떻게 해야 할지도 고민해보자.

정답은 그리 어렵지 않다!

fake 계정이 결과의 두 번째 ROW에 위치하기 때문에 1을, (= start)

fake 계정을 기준으로 ROW 하나만 가져오면 되기 때문에 1을(= number) 입력해주면 된다!

이렇게 해서 여러 ROW가 결과로 나올 때,

어떻게 하면 특정 ROW만 가져올 수 있는 지에 대한 방법을 살펴보았다.

앞으로도 아주 유용하게 쓰일 거 같은 느낌이 드니 한 번 정리하고 넘어가면 도움이 될 듯하다! 👏

Last updated