본문 바로가기
3. 웹 애플리케이션 취약점 진단/비박스를 활용한 웹 애플리케이션 취약점 진단

[비박스를 활용한 웹 취약점 진단] 2-3. SQL 인젝션 [GET/SELECT]

by Robert8478 2023. 12. 12.

[난이도 하]

이번 페이지는 드롭다운 메뉴를 선택하여 선택한 영화의 정보를 보여준다. GET 메소드기에 URL창에 변수가 노출되는것을 볼 수 있다.
드롭다운 메뉴를 변경해보면 movie 변수값이 변경되는 것을 볼 수 있고 숫자형을 입력 값으로 받는 듯 하다.

movie 변수에 ' 작은 따옴표 값을 주었더니 SQL 에러가 나왔다. 이제 union select 구문을 바로 써보면 될 것 같다.
그 전에 order by 구문을 이용해 칼럼 개수를 알아보자.

0 order by 8 에서 unknown column이 떴다. 즉, 칼럼 개수는 7개라는 뜻이다. 이제 union select로 넘어가자

0 union select 1,2,3,4,5,6,7 을 movie 값에 넣어주었다. 써보니 주석문자를 사용하지 않아도 공격이 가능하였다.
또한 0 뒤에 '를 붙여주지 않아야 정상적으로 쿼리가 들어갔다. 이제 시스템의 각종 정보를 확인해보자.

0%20union%20select%20null,database(),version(),@@datadir,null,null,null
이번에는 숫자 대신 null을 넣어보았다. 그러면 숫자 대신 빈칸이 표시되게 된다.
database(),version(), @@datadir 을 이용해 각종 데이터베이스 정보를 출력하였다. 이제 테이블 명을 뽑아보자.

0%20union%20select%20null,table_name,null,null,null,null,null from information_schema.tables 구문을 넣어주었다. 그런데 이 페이지는 출력값이 한 줄만 나오는 페이지여서 데이터베이스의 첫번째 페이지만 출력되었다.
MySQL DB에 있는 기본 테이블인 mysql과 information_schema에 포함되지 않는 테이블 스키마, 테이블명, 칼럼명을 확인해보자.

0%20union%20select%20null,table_schema,table_name,column_name,null,null,null%20from%20information_schema.columns where table_schema!='mysql' and table_schema!='information_schema'

위의 쿼리를 넣었더니 mysql과 information_schema를 제외한 최상위 테이블 스키마는 bWAPP, 거기에서 최상위 테이블명은 blog, 거기에서 최상위 칼럼명은 id 라고 출력되었다.
limit을 이용해서 users 테이블을 참조해보자.

0%20union%20select%20null,column_name,null,null,null,null,null%20from%20information_schema.columns%20where%20table_name="users"%20limit%202,1​ 쿼리를 사용했다.

limit 0,1 부터 시작해서 limit 1,1 limit2,1 이런식으로 컬럼을 하나씩 이동하며 확인해 나갈 수 있다.
원하는 정보를 찾아서 노출시킬 수 있게 되는것이다.

[난이도 중]

우선 ' 로 에러도 발생하고 칼럼수가 7자인 것도 알아낼 수 있었다. 그렇다면 한번 union select도 써보자.

테이블명이 노출까지 되었다. 아무래도 medium 또한 ' " 와 같은 특수문자에 addslashes를 붙여주는데 이번에 쿼리에
'와 "를 쓰지 않아 패스된 듯 싶다. 만약 "가 들어간 쿼리를 넣으면 어떻게될까?

에러메시지를 잘 보면 "users" 쿼리가 \"users\" 로 변한것을 볼 수 있다. addslashes 필터링이 된 것이다.
' " 를 사용하는 구문은 막았으나 여전히 테이블명, 칼럼명까지 노출될 수 있기 때문에 완벽한 방어는 되지 않았다.


[난이도 상]
우선 php 코드를 먼저 살펴보았다.

난이도 중의 sqli_check_2 함수는 addslash 일 것인데 위쪽에 security 레벨이 2면 sqli_2-ps.php 페이지로 넘어가도록 되어있다. 열어보자.

보안 코딩 부분을 찾아보니 이번에는 우회 함수를 사용한것이 아닌 SQL 쿼리를 호출하는 방식이었다.
row = recordset , 즉 DB에서 가져온 내용을 -> fetch_object 함수를 사용해서 객체로 생성한다.
그 다음 movie 변수에 입력한 숫자 값이 id 변수에 대입되는것을 볼 수 있다.

id 변수는 recordset에 저장된 db 내용의 순서 번호를 뜻하는데 bind_param 함수를 사용해서 db에서 쓰는 변수들을 불러온 뒤 execute 함수로 쿼리를 실행한다. 그 뒤 bind_result 함수로 각 변수를 연결한 뒤 store_result 함수로 쿼리결과를 저장한다.
이처럼 이번 난이도 상 문제는 칼럼을 개별로 호출해서 연결하는 방식으로 SQL 인젝션을 방어하고 있다.