[WEB HACKING] SQLite SQL Injection and Payload

최근 예전에 SSRF 올렸던 내용의 확장격인 나름 개인의 연구과제와 Blind XSS 테스팅 툴 만드는 것 때문에 짧은 글로 가끔 포스팅하는 것 같습니다. (시간이 없다는 핑계, 사실 놀거 다 놀고 있는 느낌..)

아무튼 오늘은 SQLite 에서의 Injection과 Payload에 대한 이야기를 할까합니다.

Injection Point

서버에서 직접 쓰는 경우는 기존 SQL Injection과 동일합니다. 그저 DB가 어떤거냐의 차이뿐.

대신 SQLite의 경우 로컬스토리지나 모바일 앱에서 많이 사용되고 있기 떄문에 몇가지 또다른 공격 포인트가 있습니다.

LocalStorage

HTML5 이후부터 LocalStorage를 이용한 데이터 저장이 많이 이루어지고 있습니다. 그중에는 파라미터를 통한 값들이 DOM 영역을타고 LocalStorage로 저장되어 나중에 불러와지는 경우도 많지요. 덕분에 XSS에서 득을 많이 보고있죠.

(걍 링크로 걸어놓으려고 했는데 정리를 안해뒀었네요)

파라미터를 통해 SQLite(LocalStorage) 부분 제어가 가능할 때 공격자는 피해자의 LocalStorage에 데이터를 읽거나 쓸 수 있고 더 나아가 파일을 생성한다던가, 다른 모듈을 불러오는 등 여러 위험요소로 작용할 수 있습니다.

Mobile App

어찌보면 LocalStorage와 비슷합니다. 앱 중에선 파일에 여러 설정정보를 두고 신뢰하는 앱들도 있어 공격을 통해 추가적인 보안 위험이 발생할 수 있습니다.

웹뷰의 캐시부터, 각종 설정~잡다한 정보가 거의 SQLite로 (.db파일) 저장되며 사용되기 때문에 Mobile 환경에서 Client를 대상으로한 SQL Injection 공격 또한 위험하다고 생각됩니다.

Payloads

SQL Query Control

기본적으로 SQL Injection의 가장 기초적이고, 많이 사용되는 공격은 데이터 조회, 수정, 삭제, 추가 등 Query문 제어입니다.

SQLite도 다른 DB와 동일하게 Injection 구문을 통해 데이터 제어가 가능합니다.

그러나 SQLite는 대체로 Front-end DB로 많이 사용되고 서버보단 사용자 입장에서 동작하는 DB의 경우가 많기 떄문에 전체 테이블, 시스템 정보 탈취보단 Injection을 통해 사용자의 중요 정보를 추출해서 공격자 서버로 보내거나, 토큰으로 활용, DB내 데이터 변조를 통해 XSS, CSRF 등 다른 웹 공격에 사용하는 부분이 많습니다.

ATTACH 를 이용한 Webshell

ATTACH문은 SQLite에서 새로운 DB를 연결할때 사용합니다. 아래와 같이 쿼리를 넘겼을 때 SQLite는 파일을 생성하고 연결되는 DB(database_name)에 저장되는 데이터를 해당 파일로 저장합니다. (SQLite가 파일 기반이기 떄문에)

ATTACH DATABASE file_name AS database_name;

재미있는점은 이 파일이 생성되는 과정을 이용하면 다른 행위를 할 수 있게됩니다. .sqlite3, .db 등 보편적인 SQLite 확장자가 아닌 Application 확장자로 파일을 만들고 DB에 데이터를 써서 파일 내용을 채울 수 있습니다.

ATTACH DATABASE '/var/www/html/filename.php' AS zzzz ; CREATE TABLE zzzz.payload (dataz text);INSERT INTO zzzz.payload (dataz) VALUES ('<?php echo phpversion();;?>');

코드를 보면 filename.php 라는 파일을 만들고 이를 zzzz 라는 database로 이름을 지어줍니다. 그 다음 zzzz에 table을 만들어주는데, 값에 php 구문을 넣어주죠.

결론적으론 filename.php라는 php 문서가 생기게됩니다.

OneLine shell로 연결하면 간단한 Injection으로도 시스템 접근 권한 탈취가 가능하겠지요? 물론 웹상에서 SQLite를 사용하는 경우는 적습니다. 대체로 RDBMS나 NoSQL과 연결되지만 간혹, 아주 간혹 사용되는 경우도 있고 안드로이드나 iOS App들은 SQLite를 기본적으로 사용하기 때문에 잘 활용한다면 좋은 공격 포인트가 될 수 있을 것 같습니다.

load_extension을 이용한 동적 라이브러리 로드

load_extension이라는 재미있는 메소드가 있습니다. 이 메소드는 sqlite에서 외부 라이브러리를 로드할 수 있게 해줍니다.

int sqlite3_load_extension(
  sqlite3 *db,          /* Load the extension into this database connection */
  const char *zFile,    /* Name of the shared library containing extension */
  const char *zProc,    /* Entry point.  Derived from zFile if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
);

load_extension으로 악의적인 라이브러리(쉘)을 호출하게 되면 쉘 접근 권한을 획득할 수 있을겁니다.

UNION SELECT 1,load_extension('meterpreter.dll','DllMain')

PRAGMA문을 이용한 Information Leakage

PRAGMA는 SQLite에서 라이브러리 쿼리를 하기 위해 사용됩니다. 이를 활용하면 연결되는 DB데이터나 파일 저장위치 등 시동 쿼리로 수행할 수 없는 부분을 처리할 수 있습니다.

먼저 database_list나 index_list로 연결되는 DB간의 관계를 파악할 수 있습니다.

PRAGMA database_list
PRAGMA [database.]index_list( table_name ) ;

단일 쿼리로 위험한건 아니지만 공격자가 Injection 쿼리를 통해 여러 정보를 알아가는데 사용될 수 있습니다. (조회된 결과로 인해 조회문 뒤에 이어지는 쿼리의 내용이 바뀌겠지요. 더 알차게!)

temp_store_directory를 조작해서 DB파일이 저장될 위치를 바꿀 수 있습니다.

PRAGMA temp_store_directory = '/path';

딱봐도 위험한 부분이고, 해당 PRAGMA 는 사용할 수 없도록 패치되었습니다.

물론 해당 구문을 처리하던 SQLite 버전의 경우 먹히겠죠 :)

이외에도 많은 문법이 있습니다. 잘 활용하면 추가적인 취약점 체크에 사용할 수 있겠지요.

자세한 내용은 pragma 문서 참고해주세요.

Defence

SQL Injection 에 대한 대안은 입력값 검증이 일반적입니다만..

$name = sqlite_escape_string($name);
$result = @$db->query("SELECT * FROM users WHERE username = '{$name}'");
// 알아서 이렇게 짜면 얼마나 좋을까

SQLite측에서 load_extension, ATTACH 문에 대한 적절한 제한이 필요할 것 같습니다. (물론 이게 굉장히 어렵겠죠. 기능성과 직결되어있어서..)

Reference

https://sqlite.org/c3ref/load_extension.html https://www.blackhat.com/docs/us-17/wednesday/us-17-Feng-Many-Birds-One-Stone-Exploiting-A-Single-SQLite-Vulnerability-Across-Multiple-Software.pdf http://www.sqlitetutorial.net/sqlite-attach-database/ https://sqlite.org/pragma.html