[하루한줄] heap out-of-bounds write in Telegrams animated stickers
URL
Hunting for bugs in Telegram’s animated stickers remote attack surface
Target
- 텔레그램 안드로이드 v7.1.0(2090) (2020년 9월 30일 릴리스) 이전 버전
- 텔레그램 iOS v7.1 (2020년 9월 30일 릴리스) 이전 버전
- 텔레그램 macOS v7.1 (2020년 10월 2일 릴리스) 이전 버전
Explain
텔레그램 비밀 채팅 애니메이션 스티커 기능에서 remote code execution이 가능한 취약점이 발견되었습니다. 텔레그램은 애니메이션 스티커를 렌더링 하기 위해서 rlottie를 수정하여 사용합니다.
취약점은 VGradientCache::generateGradientColorTable
에 존재하며, 반복문의 범위 검증 미흡으로 heap memory out-of-bound write이 발생합니다.
bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
float opacity,
uint32_t *colorTable, int size)
{
int dist, idist, pos = 0, i;
bool alpha = false;
int stopCount = stops.size();
const VGradientStop *curr, *next, *start;
uint32_t curColor, nextColor;
float delta, t, incr, fpos;
if (!vCompare(opacity, 1.0f)) alpha = true;
start = stops.data();
curr = start;
if (!curr->second.isOpaque()) alpha = true;
curColor = curr->second.premulARGB(opacity); // out-of-bounds value, curr->second is controlled
incr = 1.0 / (float)size; // static
fpos = 1.5 * incr; // static
colorTable[pos++] = curColor;
while (fpos <= curr->first) { // curr->first is controlled and pos is not checked to be < size, leading to
colorTable[pos] = colorTable[pos - 1]; // out-of-bounds write
pos++;
fpos += incr;
}
[...]
size
, fpos
, incr
는 static value이고, curr->first
, curr->second
는 애니메이션 스티커에서 값을 직접 받아옵니다. 반복문에서 colorTable
을 할당할 때 pos
와colorTable
배열 크기인 size
간의 검사를 하지 않아 애니메이션 스티커의 curr->first
값에 따라 힙 메모리 arbitrary overwrite가 가능합니다.
스티커를 통해 overwrite 된 값은 premulARGB()
와 getColorReplacement()
를 통해 인코딩 되고, 해당 함수들의 소스 코드를 확인할 수 있으므로 해커가 조작할 수 있으며, ASLR 우회 가젯이 존재하면 Remote Code Execution이 가능합니다.
해당 취약점은 사용자가 보낸 sticker.id
가 텔레그램 클라우드의 public sticker set에 존재하는지 확인하여 임의로 조작된 스티커 파일을 전송할 수 없는 방법으로 패치되었습니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.