C, PHP, VB, .NET

Дневникът на Филип Петров


* Goto грешката на Apple

Публикувано на 11 април 2014 в раздел ОСУП.

В средата на февруари Епъл пуснаха критично обновяване на iOS. Версията беше iOS 7.0.6. После се оказа, че засяга всякакви i-работи, че дори и версии на OSX операционната система. Този бъг позволяваше да се прави man in the middle атака срещу iPhone, iPad и други епъл устройства. А за който не си е обновил софтуера, това важи все още и ще важи – уязвимостта е при клиентските приложения :)

Грешката идва при прилагането на т.нар. „forward secrecy“ проверка. Идеята е да се използва „ephemeral ключ“ – трафика не се криптира само с public key, но и с допълнителен временно генериран ключ, който гарантира, че дори в бъдеще ако някой открадне основния private key, той няма да успее да декриптира „стар“ трафик, защото няма да има ephemeral ключа. Проблемът на Apple се коренеше във файла им sslKeyExchange.c – официалната SSL/TLS библиотека на Епъл. В нея се виждаше следния код:

static OSStatus
SSLVerifySignedServerKeyExchange(
     SSLContext *ctx, 
     bool isRsa, 
     SSLBuffer signedParams,
     uint8_t *signature, 
     UInt16 signatureLen)
{
OSStatus err;
...
if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
      goto fail;
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
      goto fail;
      goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
      goto fail;
...
fail:
      SSLFreeBuffer(&signedHashes);
      SSLFreeBuffer(&hashCtx);
      return err;
}

Нека пропуснем подробностите и да караме по-общо и по-грубо – явно има код, който прави три проверки за checksum – имаме три if-а с извикване на SSLHashSHA1.update() функцията. Ако някоя от тях даде резултат различен от 0, се отива на маркера „fail“, който очевидно връща число – статус, който означава, че сертификата не е валиден. Иначе, ако всичко е наред, статуса ще е 0.

Къде е грешката в кода тук? Вижте вторият if – „в него“ има два пъти „goto fail„. А всъщност… те не са в пограмен блок! Тоест вторият „goto fail“ ще се изпълни със сигурност – той е самостоятелна операция, която се изпълнява без условен оператор. Тоест тези проверки дават гарантирано преминаване в блока за грешка – fail, – независимо какво се проверява!

Ето и къде всъщност е проблема – представете си, че първите две проверки дават валиден сертификат. Тоест във втория if условието „err = SSLHashSHA1.update(&hashCtx, &signedParams))“ e записало в променливата „err“ число равно на нула. Свободният „goto fail“ незабавно ще изпрати програмата във „fail“ блока, а там се прави… просто „return err;„. Тоест функцията връща резултат err равен на 0. По този начин третата проверка – „if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)“ – никога не е извършена, а функцията е върнала резултат 0, който означава, че всичко е наред.

Решението на този проблем е ясно – просто излишния ред в кода трябва да се премахне. Проблемите, който той създава обаче са големи – хакерите могат да си генерират сами невалидни SSL сертификати, които не отговарят на последната проверка, а браузъра на i-устройството ще ги приеме за валидни. Имате предпоставка (практически лесно осъществима) за man-in-the-middle атака.

Източник: https://www.imperialviolet.org/2014/02/22/applebug.html

 



Добави коментар

Адресът на електронната поща няма да се публикува


*