본문 바로가기
Security/Web Hacking

[bWAPP] SQL Injection - GET/search

by 단월໒꒱ 2022. 2. 10.

1. SQL 기본 지식 정리하기 (쿼리, 테이블 등 기본 용어 및 SELECT문 숙지)

 1) SQL

   - 관계형 데이터베이스 관리 시스템의 데이터를 관리하기 위해 만들어진 프로그래밍 언어

 

 2) 쿼리 (질의)

   - 데이터베이스에 정보를 요청하는 것

   - DB에 대한 명령문

   - 전달 과정

       : 사용자 -> 쿼리(질의) -> DB 서버 -> 결과 -> 사용자

 

 3) 데이터 정의어 (DDL, Data Definition Language)

   - 데이터베이스의 구조 정의

   - 명령어

      ① CREATE (테이블 생성)

      ② ALTER (테이블 수정)

      ③ DROP (테이블 삭제, 롤백 불가)

      ④ TRUNCATE (테이블의 모든 행 삭제, 테이블 구조는 그대로고 데이터만 삭제)

 

 4) 데이터 조작어 (DML, Data Manipulation Language)

   - 데이터베이스의 레코드를 조작해 조회, 삽입, 수정, 삭제

      ① SELECT (데이터 조회)

      ② INSERT (데이터 삽입)

      ③ DELETE (데이터 삭제)

      ④ UPDATE (데이터 수정)

 

 5) 데이터 제어어 (DCL, Data Control Language)

   - 데이터베이스의 접근권한 및 트랜잭션 제어

      ① GRANT (권한 부여)

      ② REVOKE (권한 회수)

 

 

2. SQL injection에 대해 정리하기

 1) SQL injection

   - 임의의 SQL문을 주입하고 실행되게 하여 데이터베이스가 비정상적인 동작을 하도록 조작하는 행위

   - 사용자가 데이터를 입력할 수 있는 곳 어디에서든 발생 가능

 

 2) 종류

    ① Error based SQL Injection

      - 논리적 에러를 이용한 공격

      - ' OR 1=1 -- 을 주입하여 WHERE 절을 모두 참으로 만들고 뒤의 구문을 주석 처리해버림

 

 

 

 

    ② Union based SQL Injection

      - Union 명령어를 이용한 공격

      - UNION : 두 개의 쿼리문에 대한 결과를 통합해서 하나의 테이블로 보여주게 하는 명령어

      - 성공 조건 : Union 하는 두 테이블의 컬럼 수가 같아야 함 / 데이터형이 같아야 함

 

 

 

 

    ③ Blind SQL Injection (Boolean based SQL)

      - DB로부터 특정한 값이나 데이터를 전달받지 않고 단순히 참과 거짓만 알 수 있을 때 사용

      - 로그인 폼에 SQL Injection 가능할 때, 서버가 응답하는 로그인 성공과 로그인 실패 메세지를 이용하여 DB의 테이블 정보 추출 가능

 

 

 

 

    ④ Blind SQL Injection (Time based SQL)

      - 서버로부터 특정한 응답 대신에 참 또는 거짓의 응답을 통해 DB의 정보 유추

      - MySQL 기준으로 SLEEP, BENCHMARK라는 함수 사용

 

 

 

 

    ⑤ Stored Procedure SQL Injection

      - 저장된 프로시저에서의 공격
      - 공격자가 시스템 권한을 획득해야 하므로 공격 난이도가 높지만 성공한다면 서버에 직접적인 공격 가능

 

    ⑥ Mass SQL Injection

      - 다량의 SQL Injection 공격

      - 보통 DB 값을 변조하여 DB에 악성스크립트를 삽입하고, 사용자들이 변조된 사이트에 접속 시 좀비PC로 감염되게 함

 

 3) 대응방안

    ① 입력 값에 대한 검증

      - 서버에서 화이트리스트 기반으로 검증 (블랙리스트 기반 시 공격에 취약)

      - 공백으로 치환하는 방법도 많이 쓰이지만 공격에 취약

 

    ② Prepared Statement 구문 사용

      - Prepared Statement 구문 사용시 사용자의 입력 값이 DB의 파라미터로 들어가기 전에 DBMS가 미리 컴파일하여 실행하지 않고 대기

      - 그 후 사용자의 입력 값을 문자열로 인식하여 공격쿼리가 들어간다고 하더라도 사용자의 입력은 이미 의미없는 문자열이라 공격자의 의도대로 작동 x

 

    ③ Error Message 노출 금지

      - 공격자가 SQL Injection 수행하기 위해 데이터베이스의 테이블명, 컬럼명 등이 필요함

      - 에러 발생에 대한 처리를 따로 하지 않으면 에러 발생시 위의 사항들이 노출됨

      - 따라서 오류 발생시 사용자에게 보여줄 수 있는 페이지나 메세지박스를 만들 필요가 있음

 

 

3. 영화 정보가 들어 있는 데이터베이스에 저장된 사용자들의 아이디와 비밀번호를 획득하자.

  - 아래 퀘스트들을 단계별로 해결하면 MISSION을 해결할 수 있습니다.

 

 Quest 1) SQL Injection이 통하는지 아닌지 확인해보고, SQL Injection이 된다면 데이터베이스의 서버 종류가 무엇인지 확인해봅시다.

 

구글링을 해보니 SQL Injection 취약점이 존재하는 지 확인하기 위해 작은 따옴표(')를 입력하고, SQL Injection 취약점이 존재할 경우 SQL 오류 메세지가 출력된다고 한다.

데이터베이스에서 문자열을 구분할 때 작은따옴표를 사용하기 때문이다.

 

위의 내용을 참고하여 입력창에 작은따옴표(')를 입력해보았다.

 

 

 

 

데이터베이스의 서버가 MySQL인 것을 확인할 수 있다.

 

 

 Quest 2) 모든 영화자료를 출력해봅시다.

 

소스코드를 확인하여 사용된 sqli_1 파일을 열어 코드를 살펴보았다.

 

 

<?php

if(isset($_GET["title"]))
{

    $title = $_GET["title"];

    $sql = "SELECT * FROM movies WHERE title LIKE '%" . sqli($title) . "%'";

    $recordset = mysql_query($sql, $link);

    if(!$recordset)
    {

        // die("Error: " . mysql_error());

?>

 

 

입력하는 창의 쿼리문은 SELECT * FROM movies WHERE title LIKE '%" . sqli($title) . "%' 이다.

또한 위에서 정리했던 내용 중에 WHERE문을 모두 참으로 만드는 공격 기법을 사용하기로 했다.

이들을 참고하여 모든 영화자료를 출력하기 위해 코드를 완성해주었다.

 

 

 

 

위의 방법을 통해 무사히 모든 영화자료를 출력할 수 있었다.

 

주석은 # 또는 -- 을 통해 처리되는데, 여기서는 --이 통하지 않아서 #로 했다.

--로 할 경우 위에 작은 따옴표를 하나 더 붙여서 ' OR 1=1 --'으로 넣어주면 위와 똑같이 출력되기는 한다.

 

 

 Quest 3) 데이터베이스에서 호출하는 칼럼 수가 몇 개인지 알아내세요.

 

잘 모르겠어서 힌트를 참고했다.

힌트에 따라 Union based SQL Injection을 이용해보기로 했다.

 

위에서 정리한 Union based SQL Injection 내용을 참고하여 들어갈 내용을 작성했다.

 

 

 

 

 

 

실패했다.

오류 메세지를 보니 Union 하는 두 테이블의 컬럼 수가 달라서 그런 것 같았다.

그래서 하나씩 개수를 늘려가며 내용을 입력해주었다.

 

 

 

 

컬럼 수 7개를 입력했을 때 성공한 것으로 보아 데이터베이스에서 호출하는 칼럼 수는 7개인 것을 확인할 수 있다.

 

 

 Quest 4) 데이터베이스에 존재하는 모든 테이블 명을 출력하세요.

테이블 명을 확인하기 위해서는 information_schema를 사용해야 한다.

구글링을 통해 사용방법에 따라 필요한 코드를 작성해주었다.

 

' UNION SELECT ALL 1, table_name,3,4,5,6,7 from information_schema.tables#

 

 

 

너무 많으므로 이하 생략...

 

 

데이터베이스에 존재하는 모든 테이블을 출력할 수 있었다.

 

 

 Quest 5) 우리가 출력한 테이블 명에서 사용자 정보가 있을 것 같은 테이블이 있습니다. 그 테이블의 칼럼 명을 출력해봅시다.

 

Quest 4에서 출력한 테이블명을 살펴보았는데, 그 중에 사용자 정보가 있을 것 같은 users 테이블이 있었다.

해당 테이블의 칼럼 명을 출력하기 위해 위에서 사용한 코드를 살짝 변형해주었다.

 

' UNION SELECT ALL 1, column_name,3,4,5,6,7 from information_schema.columns where table_name='users'#

 

 

 

 

해당 테이블의 칼럼 명을 출력할 수 있었다.

 

 

 Quest 6) 사용자의 id, password, email 정보 등을 출력해봅시다.

 

위에서 구한 내용을 바탕으로 원하는 내용을 출력하기 위해 적당한 곳에 해당 칼럼명을 넣어주었다.

 

' UNION SELECT ALL 1,login,id,email,password,6,7 from users#

 

 

 

 

원하는 정보를 출력할 수 있었다.

 

 

 

댓글