2. 진짜 비밀 데이터를 찾아라!!
일단 어떤 웹 서비스를 하는지 확인부터 해보겠습니다.
normaltic을 검색하니 normaltic 계정의 정보가 화면에 출력됩니다.
- 아마? 입력한 아이디로 데이터베이스에서 해당아이디의 정보를 찾아 출력해주겠죠?
nor를 검색하니 nor 아이디를 검색하는데 info에는 정보가 나오지 않습니다.
뭐지?? normaltic의 계정이 나오지 않은 것을 보니 like로 패턴 검색하는 것 같지는 않습니다.
nor아이디가 있는데 info의 값이 없는건가? 생각할 수도 있습니다.
음... normaltic' or 1 # 을 입력하였는데 normaltic의 info 값이 출력되는 것을 보니 SQL Injection이 가능한 부분이며,
id부분은 데이터베이스에서 가져오는 것이 아닌 입력한 아이디를 그대로 출력해주는 것 같습니다.
또한, 전체 데이터를 검색해보았는데 normaltic 정보만 출력되었습니다.
전체 데이터에 대해 limit로 다른 정보에 접근해보니 다른 아이디의 info 값이 있습니다.
아하!! 그럼 결론적으로 select 한 결과값에서 첫번째 행만 화면에 출력해주는 것 같습니다.
1) SQL Injection 포인트 찾기
// 서버측 예상 쿼리
select * from member where id='입력한 값';
// ~ 결과의 한 행만 출력
아이디로 검색하는 부분에서 SQL Injection이 가능하며 서버측의 쿼리는 이렇게 되어 있을 것이다? 예상을 해보았습니다.
2) 컬럼 개수 찾기
order by 를 사용하여 쉽게 컬럼 개수를 찾을 수 있습니다.
// 입력 : normaltic' order by 1 #
select * from member where id='normaltic' order by 1 #'
이제 인덱스 부분의 숫자를 늘려가며 요청을 보내보겠습니다.
7을 넣어주니 normaltic의 정보가 안나오는 것을 보니 컬럼 개수가 6개 이라는 것을 알았습니다.
3) 출력 위치 찾기
union select 1,2,3,4,5,6 을 하고 출력되는 숫자를 보면 어디있는 컬럼이 출력되는 지 알 수 있습니다.
select 한 결과의 한 행만 출력해주기 때문에
normaltic' 이 아니라 그냥' 을 하여 서버측 코드 조건에 맞는 아이디는 없게하고 union하여 숫자를 출력하게 하였습니다.
select * from member id ='normaltic' union select 1,2,3,4,5,6 #'
// 결과가 normaltic 정보 밑에 1~6 까지 출력
// 만약 normaltic' 입력 시
select * from member id='normaltic' union select 1,2,3,4,5,6 limit 1,1 #'
// limit 1,1 을 사용하여 두번째 행을 출력해줌
info 값에 6이 출력되는 것을 보니 6번째 컬럼이 출력되는 것 같습니다. 우리는 이제 원하는 정보를 출력할 때는 6번째 컬럼을 이용해야 합니다.
4) DB 이름 확인
show database(); 를 사용하면 지금 우리가 사용하는 데이터베이스의 이름을 출력할 수 있습니다.
근데 진짜 비밀 데이터를 찾아보라는 문제였습니다.
왠지 다른 데이터베이스에 숨겨져 있을 수도 있을 것 같다는 생각이 들어서 다른 데이터베이스를 확인해보겠습니다.
서버 데이터베이스에 존재하는 다른 데이터베이스 이름을 확인하는 방법은 테이블 이름을 확인한 것처럼
information_schema.table을 사용하면 됩니다.
우리는 where table_schema='데이터베이스 이름' 조건을 주어 해당 데이터베이스의 테이블을 확인했습니다.
그럼!! table_schema는 데이터베이스 이름이라는 뜻이며 똑같이 information_schema에 저장되어있다는 의미가 됩니다.
하지만 어떤 조건을 줘야할지 막막할 수 있습니다.
이때 사용할 수 있는 SQL 문법이 group by 입니다. group by 는 원하는 컬럼을 그룹으로 묶어줄 수 있습니다.
해당 컬럼에 값이 같은 것은 하나의 그룹으로 만들어서 처리할 수 있습니다.
-> 예를 들어 과목을 그룹으로 묶어서 각 과목 별로 평균을 계산,
-> ORDER 테이블에서 customer_id로 그룹화하고 각 그룹의 주문 총액을 계산하는 등...
SELECT customer_id, SUM(order_amount) AS total_order_amount
FROM orders
GROUP BY customer_id;
// 이 쿼리는 orders 테이블을 customer_id 열로 그룹화하고, 각 그룹에 대해 order_amount를 합산하여 총 주문 금액을 계산합니다.
위 사진은 table_schema에 값이 같은 것들을 그룹으로 묶어서 table_schema를 출력합니다.
그럼 table_schema에 어떤 그룹이 있는 지 출력하기 때문에 우리가 원하는 데이터베이스 이름을 모두 출력할 수 있습니다.
첫번째 데이터베이스 이름은 우리가 이때까지 사용한 information_schema입니다. 여기는 아닌 것 같습니다.
두번째 데이터베이스는 우리가 앞서 알아낸 데이터베이스이름입니다.
더 있는지 limit 2,1 을 사용했는데 나오지 않네요... 아마 sqli_5에 데이터를 저장한 것 같습니다.
제가 예상한 다른 데이터베이스를 사용하지는 않았네요... 다른 데이터베이스 이름을 확인하는 공부도 되었기 때문에 좋습니다.
데이터베이스 이름 |
information_schema |
sqli_5 |
5) Table 이름 확인
이제 어떤 데이터베이스를 사용하는지 알았습니다. 이제 이 데이터베이스에는 어떤 테이블이 있는지 확인해보겠습니다.
// 입력: ' union select 1,2,3,4,5,table_name
from information_schema.tables where table_schema='sqli_5' #
select *(6개) from member where id='' union select 1,2,3,4,5,table_name
from information_schema.tables where table_schema='sqli_5' #'
일단 한행씩 밖에 출력을 안하기 때문에 어떤 테이블이 있는지 전부 확인해보겠습니다. limit를 사용하여 다음 행을 출력해주면 됩니다.
데이터베이스 이름 | 테이블 이름 |
sqli_5 | flag_honey |
sqli_5 | game_user |
sqli_5 | secret |
테이블 이름을 모두 확인했습니다.
우리가 생각했던 member 테이블이 game_user 테이블인 것 같고 flag_honey와 secret에 아마도 진짜 데이터가 저장되어 있을 것 같습니다.
진짜 데이터가 다른 데이터베이스에 있을 것이라는 추측이 틀렸지만, flag_honey같이 처음 나오는 테이블에는 없을 것 같아 secret 테이블을 먼저 확인해보겠습니다. (또 헛걸음 하면 우울할지도...)
6) 컬럼 이름 확인
secret에 어떤 컬럼이 있는지 확인해보겠습니다
// 입력: ' union select 1,2,3,4,5,column_name
from information_schema.columns where table_name='secret' #
select *(6개) from game_user where id='' union select 1,2,3,4,5,column_name
from information_schema.columns where table_name='secret' #'
추가로 다른 컬럼도 있나해서 limit를 사용하여 다른 행을 확인해봤는데 없습니다.
데이터베이스 이름 | 테이블 이름 | 컬럼 이름 |
sqli_5 | flag_honey | ? |
sqli_5 | game_user | ? |
sqli_5 | secret | flag |
7) 데이터 추출
이제 모든 정보는 알았습니다. 해당 테이블에서 데이터만 가져올 일만 남았습니다.
// 입력: ' union select 1,2,3,4,5,flag from secret #
select *(6개) from game_user where id='' union select 1,2,3,4,5,flag from secret #'
일단 첫번째 데이터는 우리가 찾는 데이터가 아닌 것 같습니다. limit 를 사용하여 다른 행도 확인해보겠습니다.
다른 행에는 진짜 비밀 데이터가 숨겨져있습니다.
휴... 예상한 테이블에 있어서 다행입니다. 아니었으면 다시 올라가서 flag_honey의 컬럼을 확인하고 또 데이터를 찾아야합니다.
이번 주차에는 만약 데이터베이스의 데이터를 화면에 출력할 경우 다른 테이블에 있는 데이터를 가져오는 방법을 알아보았습니다.
또한, 데이터베이스를 관리, 운용할 때 필요한 정보들이 저장되어있는 information_schema가 있고 데이터베이스 이름, 테이블 이름, 컬럼 이름도 저장되어 있습니다. 그 정보를 union select를 통해 가져오고 limit를 통해 원하는 정보를 출력할 수 도 있습니다.
이번 주차 과제도 여기서 마무리해보겠습니다.
'웹 해킹' 카테고리의 다른 글
웹 해킹 공부 일기장 3 - 2 (Blind SQL Injection) (0) | 2023.12.07 |
---|---|
웹 해킹 공부 일기장 3 - 1 (Error Based SQLI) (0) | 2023.12.07 |
웹 해킹 공부 일기장 2 - 과제 (챌린지1) (2) | 2023.12.01 |
웹 해킹 공부 일기장 2 - 과제 (0) | 2023.12.01 |
웹 해킹 공부 일기장 2 - 1 (SQL Injection 데이터 추출) (0) | 2023.11.30 |