* 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
Добави коментар