flawopen.com/Teardowns/cve-2015-3824-android-stagefright-tx3g-integer-overflow
Bagaimana penjumlahan ukuran tanpa pemeriksaan saat mengurai atom subtitel tx3g MPEG-4 berputar balik, mengalokasikan buffer heap yang sangat kecil, dan membuat video rekayasa bisa merusak memori mediaserver tanpa interaksi pengguna sama sekali.
Bayangkan sebuah percetakan yang formulir pesanannya hanya punya empat kotak untuk panjang spanduk. Sudah tercatat 9.998 meter dan Anda meminta tambahan 5 meter. Petugas menulis totalnya di empat kotak itu, angkanya berputar menjadi 0003, dan percetakan hanya memotong lembaran 3 meter. Lalu mesin mencetak seluruh 10.003 meter teks ke lembaran itu, dan tintanya meluber ke pesanan pelanggan lain di meja. Stagefright melakukan hal yang sama pada memori: total ukurannya berputar balik, buffer kecil dialokasikan, dan seluruh data video ditulis ke dalamnya.
Stagefright (libstagefright)Atom MPEG-4tx3gInteger overflowMPEG4Extractor::parseChunk() menjumlahkan ukuran data format yang sudah tersimpan dengan chunk_size atom tx3g yang dikendalikan penyerang tanpa memeriksa overflow. Jumlah yang berputar balik menentukan ukuran alokasi heap, lalu readAt() menyalin seluruh chunk_size byte ke dalamnya.
Penyerang mengirim berkas MP4 yang atom tx3g-nya menyatakan chunk_size mendekati nilai maksimum, misalnya lewat MMS atau aplikasi pesan.
Pada Android 5.1 dan sebelumnya, layanan media mengurai media masuk untuk membuat pratinjau dan thumbnail, sehingga tidak perlu ketukan apa pun.
size + chunk_size mengalami overflow dan new[] hanya mengalokasikan buffer beberapa byte.
readAt() menyalin chunk_size byte ke buffer kecil itu, merusak heap mediaserver, dan memberi penyerang eksekusi kode dengan hak proses tersebut.
// Simplified from MPEG4Extractor::parseChunk() in libstagefright, before the fix
case FOURCC('t', 'x', '3', 'g'):
{
uint32_t type;
const void *data;
size_t size = 0;
if (!mLastTrack->meta->findData(kKeyTextFormatData, &type, &data, &size)) {
size = 0;
}
// chunk_size is read from the file. size + chunk_size can wrap around,
// so a tiny buffer is allocated for a huge copy.
uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
if (buffer == NULL) {
return ERROR_MALFORMED;
}
if (size > 0) {
memcpy(buffer, data, size);
}
// Copies the full chunk_size bytes into the undersized buffer.
if ((size_t)mDataSource->readAt(*offset, buffer + size, chunk_size) < chunk_size) {
delete[] buffer;
return ERROR_IO;
}
mLastTrack->meta->setData(kKeyTextFormatData, 0, buffer, size + chunk_size);
delete[] buffer;
*offset += chunk_size;
break;
}
// Simplified from MPEG4Extractor::parseChunk() in libstagefright, after the fix
case FOURCC('t', 'x', '3', 'g'):
{
uint32_t type;
const void *data;
size_t size = 0;
if (!mLastTrack->meta->findData(kKeyTextFormatData, &type, &data, &size)) {
size = 0;
}
// Reject any length whose sum would overflow before allocating.
if (chunk_size < 0 || (uint64_t)chunk_size > SIZE_MAX - size) {
return ERROR_MALFORMED;
}
uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
if (buffer == NULL) {
return ERROR_MALFORMED;
}
if (size > 0) {
memcpy(buffer, data, size);
}
if ((size_t)mDataSource->readAt(*offset, buffer + size, chunk_size) < chunk_size) {
delete[] buffer;
return ERROR_IO;
}
mLastTrack->meta->setData(kKeyTextFormatData, 0, buffer, size + chunk_size);
delete[] buffer;
*offset += chunk_size;
break;
}
fsanitize=integer aktif.