혜랑's STORY

[2020-2학기 웹] : SQL Injection - ­(Login Form/Hero) 본문

2020 SISS 21기 활동/2학기 WEB

[2020-2학기 웹] : SQL Injection - ­(Login Form/Hero)

hyerang0125 2020. 10. 3. 22:04

# MISSION. 데이터베이스에 접속하여 hero들의 secret들을 빼오자.

- Low Level

(1) SQL Injection이 통하는지 아닌지 확인하고, 만약 SQL Injection이 된다면 데이터베이스의 서버 종류가 무엇인지 확인하여라.

 

-> 페이지 소스코드가 "/bWAPP/sqli_3.php"에 저장되어 있으며, 소스코드를 확인해 본 결과 데이터베이스 형식으로 저장하고 있다는 것을 알 수 있었다.

"SELECT * FROM heroes ...."

-> 데이터베이스에서 작은따옴표(')를 통하여 문자열을 구분한다는 특성을 이용하여 [Login] 칸에 작은따옴표를 입력하여 데이터베이스 서버의 종류가 "MySQL"이라는 사실을 확인할 수 있다.

데이터베이스 서버 종류 확인

 

(2) login에 주석문자를 넣어 항상 참이된는 쿼리를 삽입하면 아래와 같이 neo라는 이름으로 접속할 수 있다. 분명 입력해야 하는 것은 login과 password인데 login에 삽입하는 걸로 충분한 이유는 무엇인가?

 

-> 먼저 항상 참이되는 쿼리인 " 'or 1=1# "을 입력하여 상황을 확인해보자.

-> Neo라는 사용자로 로그인이 되고, 비밀번호 힌트가 출력되는 것을 볼 수 있었다.

-> 로그인에 사용되는 쿼리는 "$sql = "SELECT * FROM heroes WHERE login = ' ".$login." ' AND password = ' ".$password." ' " 이다. 이때 AND 연산이 OR보다 연산 우선순위가 빠르기 때문에 참 or 참 and 거짓을 계산하면, 해당 구문의 연산 값이 true가 되어 올바를 값으로 판단하고 실행하게 된다. 즉, 아이디와 비밀번호를 몰라도 'or 1=1# 구문을 통하여 로그인에 성공하게 된다. 

 

(3) 칼럼의 개수 알아내기

 

-> 지난번에 사용했던 UNION 사용시 주의점(칼럼별 데이터타입이 같아야한다.)을 이용하여 칼럼의 개수가 "4"개라는 것을 알아낼 수 있었다.

칼럼의 개수 확인

 

(4) hero 정보가 들어있는 데이터베이스 이름을 알아내기

 

-> 앞서 칼럼의 개수를 확인할 때, 2와 4번 자리의 값이 출력된다는 것을 이용하여 " ' union select all 1,2,3,database() # " 를 입력한다. (database()가 데이터베이스의 이름을 반환한다는 것을 이용함) 

데이터베이스 이름 알아내기

-> 이를 통하여 데이터베이스의 이름이 "BWAPP"라는 것을 알아낼 수 있었다.

 

(5) hero 정보가 들어있는 테이블 이름 알아내기

 

-> 지난번에 공부한 테이블과 필드의 정의를 통해 테이블과 관련된 정보를 가진  테이블이 "information_schema.tables"라는 것을 이용한다. 즉, ' UNION SELECT ALL 1, table_name,3,4 from information_schema.tables where table_schema='BWAPP'# 를 입력한다.

테이블 이름 알아내기

-> 이를 통하여 테이블 이름이 "Blog"라는 것을 알아냈다. 그러나 우리가 원하는 hero의 정보가 들어있는 테이블은 아닌 것 같다. where 조건문을 이용하여 이전에 나왔던 테이블 이름이 나오지 않도록 조작하여 hero 정보가 들어있는 테이블의 이름을 알아내야 할 것 같다.

-> " ' UNION SELECT ALL 1, table_name,3,4 from information_schema.tables where table_schema='BWAPP' and table_name != 'blog'# " 입력한다. (blog 이름 출력 x)

테이블 이름 알아내기

-> " ' UNION SELECT ALL 1, table_name,3,4 from information_schema.tables where table_schema='BWAPP' and table_name != 'blog' and table_name != 'Heroes'# " 입력한다. (blog와 Heroes 이름 출력 x)

테이블 이름 알아내기

-> " ' UNION SELECT ALL 1, table_name,3,4 from information_schema.tables where table_schema='BWAPP' and table_name != 'blog' and table_name != 'Heroes' and table_name != 'Movies'# " 입력한다. (blog와 Heroes와 Movies 이름 출력 x)

테이블 이름 알아내기

-> 이를 통하여 모든 테이블의 이름을 알아낼 수 있었다. (blog, Heroes, Movies, Users) 이 중, hero의 정보가 들어있는 테이블의 이름은 "Heroes"인 것 같다.

 

(6) heroes 테이블의 칼럼 알아내기

 

-> " ' UNION SELECT ALL 1,column_name,3,4 from information_schema.columns where table_name='Heroes'# " 이용하기

-> 이를 통하여 Heroes 테이블에 있는 칼럼 이름을 알아낼 수 있었다. (Id, Login, Password)

 

(7) Neo 외의 다른 hero들의 secret을 알아내기

->  ' union select 1,Id,3,password from heroes limit (순서번호, secret 정보)# 이용하여 secret 알아내기

-> 이를 통하여 secret의 정보를 알아낼 수 있었다.

 

- Medium Level

미디엄 레벨에서는 sqli_check_1($data) 함수가 사용된다는 것을 알 수 있었다.

이때, sqli_check_1($data) 함수는 addslashes($data) 함수를 반환하고 이 함수는 그 문자열에 특수 문자, 예를 들어 작은 따옴표('), 쌍 따옴표("), 역슬래시(\) 문자가 포함되어 있다면 그러한 문자앞에 역슬래시(\)를 붙이는 역할을 한다. 즉, 특수 문자에 역슬래시가 붙어서 데이타베이스의 필드값으로 저장되면 그 특수 문자가 순수한 하나의 문자로 인식되어 저장되어 low level에 사용한 취약점을 사용할 수 없게된다.