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