R's Hacking Daily Log

SQLi (3) 본문

Port Swigger/SQL Injection

SQLi (3)

hanhxx 2023. 4. 27. 14:32

이번에 살펴볼 SQLi와 관련된 내용은

"Retrieving data from other database tables" 이다.

 

:) DB 안에 있는 또 다른 테이블의 데이터를 조회하는 공격

:) Retrieving data from other database tables와 관련해서 중요한 keywords, "UNION"

 

다른 테이블의 데이터를 조회하는 부분은 UNION이라는 keyword가 중요하게 사용된다.

따라서 UNION과 관련된 SQL 내용을 전반적으로 살펴볼까 한다.

 

 


SQL injection UNION Attack

UNION attack이 무엇인지를 살펴보기 전에 UNION이 무엇인지를 먼저 간단히 설명하자면,

UNION은 SQL에서 접속사처럼 사용할 수 있는 keyword로

하나 or 그 이상의 select문을 원래 select문 뒤에서 실행시켜 각 select문의 결과를 이어붙이는 역할을 한다. 

 

 

예시를 보자면 

SELECT a, b FROM table1 UNION SELECT c, d FROM table2

original select query ) SELECT a, b FROM table1 

injected select query ) SELECT c, d FROM table2

 

union을 사용해서 table1으로부터 a, b를 출력하는 query와 table2로부터 c, d를 출력하는 query를 연결한 것이다.

이렇게 되면 각 select query의 내용이 합쳐진 하나의 결과값이 나오게 된다. 

 

 

! 단, UNION keyword를 사용하기 위해서는 2개의 요구사항이 만족되어야 한다. 

:) union을 사용해서 연결된 select query의 결과로 나오는 column의 개수가 같아야 한다.

:) original & injected select query의 결과인 column은 각각 동일한 데이터 형이어야 한다. 

 

따라서 union attack을 실행하기 전에

original select query의 col이 몇 개이고, 각 col의 데이터 타입이 무엇인지를 알아야 한다. 

 

 

 

Determining the number of columns required in a SQL injection UNION attack

우선 column의 개수를 알아내는 방법 2가지에 대해 살펴보자.

 

:) order by 

order by문은 정렬을 하기 위해 사용된다. 

' ORDER BY 1--

이런 식으로 original select query에 주입했을 때, 이는 selecte문의 결과를 첫 번째 column 기준으로 정렬하라는 의미이다. 

 

' ORDER BY 2--

이번엔 두 번째 column을 기준으로 정렬하라는 의미로, 위에서도 -- (주석)가 사용되었기 때문에 

original select query에서 order by가 사용된 이후의 내용은 신경쓰지 않아도 된다.

 

' ORDER BY 3--

이런 식으로 column의 인덱스를 늘려가면서 order by를 실행하다보면 어느 순간에 error가 발생하게 된다.

 

The ORDER BY position number 3 is out of range of the number of items in the select list.

에러의 내용을 보면 3이라는 인덱스를 item의 범위를 넘어갔다고 한다. 

즉, order by 3은 실행할 수가 없는데 그 이유가 3번 째 column이 없기 때문이라는 것이다.

여기서 공격자는 "아, 이 테이블에는 column이 2개 있구나"라는 걸 알 수 있다. 

 

 

:) union

두 번째 방법으로 union keyword를 사용해보자.

앞에서 말했듯이 union은 original & injected select query의 column수가 같아야 한다.

 

' UNION SELECT NULL--

 

original select query와 column 수가 같지 않기 때문에 위와 같이 sql을 주입하게 되면 에러가 발생하게 된다.

 

All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.

 

' UNION SELECT NULL,NULL--

그 다음 번엔 null을 두 번 넣어서 실행해보고 

 

' UNION SELECT NULL,NULL,NULL--

또 그 다음 번엔 null을 세 번 넣어서 실행해보면서 null의 개수를 늘려가다보면 에러가 발생하지 않는 경우를 찾을 수 있다.

에러가 발생하지 않고 original select query 결과에 null 값만 들어간 column이 더해져 하나의 result set으로 나올 것이다. 

 

 

! union은 에러가 발생하지 않는 순간의 null의 개수로 original select query의 column 수를 알 수 있다. 

 

! union을 활용해 column 개수를 알아내기 위해 Null을 사용하는 이유는 union을 실행하기 위한 두 번째 조건,

데이터 타입 때문이다.

NULL은 일반적으로 모든 데이터 타입으로 변환 가능하기 때문에

original select문에서 조회하는 column의 데이터 형을 몰라도 union은 실행할 수 있게 해준다. 

 

 

 

Finding columns with a useful data type in a SQL injection UNION attack

이번엔 column의 데이터 타입을 알아내는 방법을 살펴보자.

기본적으로 UNION 공격을 하는 데에 있어서 목적은 또 다른 테이블의 데이터를 조회하기 위함인데

대게 공격자가 알고 싶어하는 정보는 "string" 형태로 되어있다. ( ex. password )

 

:) select query의 결과 4개의 column이 나온다고 할 때,

어느 column이 string 형태의 데이터를 갖고 있는 지 확인하기 위한 상황이라고 생각해보자. 

 

공격자는 다음과 같이 sql을 주입할 수 있다.

' UNION SELECT 'a',NULL,NULL,NULL--

총 4개의 column을 갖는 다고 했으니 UNION으로 연결할 select문도 4개의 column을 갖도록 한다. 

위의 sql로는 원래 select문의 결과로 나온 첫 번째 column이 string data를 갖는 지 확인할 수 있다.

 

' UNION SELECT NULL,'a',NULL,NULL--

두 번째 column이 string data를 갖는 지 확인하기 위해서는 주입할 sql의 두 번째 값을 string으로 하면 된다.

 

' UNION SELECT NULL,NULL,'a',NULL--

이와 같이 나머지 column에 대해서도 SQL 주입을 하다보면 에러가 날 수 있는데

 

' UNION SELECT NULL,NULL,NULL,'a'--

 

! 에러가 발생한다는 것은 'a'를 입력한 순서의 column이 string data를 갖지 않는 다는 의미이다. 

Conversion failed when converting the varchar value 'a' to data type int.

이렇게 union keyword를 이용해서 column의 data type을 확인하는 방법까지 살펴보았다!

 

 

(+) Oracle의 경우, select문을 작성할 때 반드시 from keyword를 사용해야하는 데 이때

DUAL table을 활용한다.


Using a SQL injection UNION attack to retrieve interesting data

UNION keyword에 대한 알아본 목적은 DB 안에 있는 또 다른 테이블의 정보를 조회하기 위함이었다.

그러기 위해선 column 수와 column의 데이터 타입을 알아야 한다는 요구 사항이 만족되어야 했다.

 

 

:) 각각 string data를 갖는 2개의 column으로 이뤄진 테이블이 있다고 가정하자. 

:) 앞에서 살펴본 방법들로 original select query의 결과가 string data를 갖는 2개의 column이란 정보를 얻었다.

:) 이때 공격자는 users라는 테이블의 username & password column 또한 조회하고 싶어한다. 

 

 

그렇다면 공격자는 다음과 같은 query를 만들 수 있다.

' UNION SELECT username, password FROM users--

위의 query가 주입되면 원래 select query 결과에 username & password 내용이 덧붙은 결과를 볼 수 있다. 

 

 

! 사실 위의 상황도 공격자가 users table이 존재하고 users table에 username, password라는 column이

있다는 걸 알아야 가능한 query이다. 

 

이 부분에 대해서는 추후 따로 다룰 내용이기 때문에 여기서는 그냥 넘어가도록 한다 (~.~)

 

 

Retrieving multiple values within a single column

지금까지는 조회하고자 하는 데이터를 각각의 column 수에 맞춰 출력시켰다면

이번에는 여러 column의 값을 하나의 값으로 합쳐서 출력시키는 방법에 대해 볼 것이다.

 

:) username & password column이 있는 테이블에서 내용을 출력할 때, 

username & password로 2개의 column을 출력하는 게 아니라 두 결과를 합쳐서 출력시키고자 한다.

 

 

' UNION SELECT username || '~' || password FROM users--

위의 SQL은 users table에서 username & password 값을 찾아 출력하는 데

username과 password 값을 " ~ " 문자로 연결해서 출력하라는 의미이다. 

 

" || " (double pipeline)이 문자는 concatenate를 의미하는 문자로,

앞 뒤에 오는 문자/문자열을 이어붙이는 연산을 수행한다. 

 

따라서 이 SQL의 결과는 다음과 같이 나올 수 있다.

...
administrator~s3cure
wiener~peter
carlos~montoya
...

username~password 형태로 출력된 결과이기 때문에 administrator 계정의 비밀번호가 s3cure이라는 걸 알 수 있다.

'Port Swigger > SQL Injection' 카테고리의 다른 글

SQLi (4)  (0) 2023.04.28
SQLi (3) - Lab  (0) 2023.04.28
SQLi (2) & Lab  (0) 2023.04.27
SQLi (1) - Lab  (0) 2023.04.26
SQLi (1)  (0) 2023.04.26
Comments