Взлом проигрывателя Apple TV

Взлом проигрывателя Apple TV

Несколько месяцев назад на конференции Derbycon я презентовал изящный хак, позволяющий загружать любые приложения в проигрыватель Apple TV. Однако через несколько дней хак перестал работать. Настало время рассказать о том, что произошло, а также узнать чуть подробнее о технологии «certificate pinning» (дословно «привязка сертификата» или технология, защищающая от подделки сертификата).

Автор: dschuetz

Несколько месяцев назад на конференции Derbycon я презентовал изящный хак, позволяющий загружать любые приложения в проигрыватель Apple TV. Однако через несколько дней хак перестал работать. Настало время рассказать о том, что произошло, а также узнать чуть подробнее о технологии «certificate pinning» (дословно «привязка сертификата» или технология, защищающая от подделки сертификата).

Для начала небольшое отступление: у операционной системы проигрывателя (Apple TV OS) есть функция «Add Site», позволяющая добавить ссылку на пользовательское приложение, после чего оно появляется на главном экране (home screen). Чтобы эта функция была доступна, необходимо загрузить специальный конфигурационный профиль. Самая веселая часть моего доклада заключалась в демонстрации того, как создать подобный профиль посредством дизассемблирования некоторые бинарных файлов Apple TV.

За несколько дней до доклада кнопка «Add Site» (до этого представляющая собой пустую иконку) вдруг изменилась и стала изящной и красивой. Я не был уверен, как такое могло быть, но предположил, что этому могло быть простое объяснение: в Apple TV (далее я буду употреблять аббревиатуру ATV) обновился XML-файл с именем «StoreFront», который, среди всего прочего, содержит описания всех приложений, находящихся на главном экране. Для того чтобы получить копию этого файла, необходимо выполнить следующую команду (в одну строку):

curl -H "User-Agent: iTunes-AppleTV/5.3 (2; 8GB; dt:11)"
https://itunes.apple.com/WebObjects/MZStore.woa/wa/storeFront
| sed 's/&lt;/</g; s/&gt;/>/g'

(Спасибо Аману Гупте (Aman Gupta), его твиттер @tmm1, который подсказал мне содержимое поля User-Agent и тем самым помог сэкономить много времени. В конце команды используется sed, поскольку перечень встроенных приложений закодирован как элемент <a> большого файла и был бы практически не читаем со всеми элементами HTML).

Необходимая нам часть файла выглядит так:

<dict>
<key>merchant</key>
<string>internet-add-site</string>

<key>enabled</key>
<string>YES</string>

<key>menu-title</key>
<string>Add Site</string>

<key>menu-icon-url</key>
<dict>
<key>720</key>
<string>http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/images/AddSite@720.png</string>

<key>1080</key>
<string>http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/images/AddSite@1080.png</string>
</dict>

<key>menu-icon-url-version</key>
<string>2.1</string>

<key>minimum-required-version</key>
<string>6.0</string>

<key>preferred-order</key>
<integer>2147483647</integer>
</dict>

При осмотре файла видно, что приложение Add Site описано по тому же принципу, что и остальные приложения, хотя его и не видно до тех пор, пока не выставлены соответствующие локальные права. Изменение было связано с добавлением элементов menu-icon-url.

Через несколько дней после доклада приложение Add Site исчезло с моего главного экрана. Это также было связано с изменением файла StoreFront (на этот раз было добавлен флаг «minimum-required-version», который скрывал приложение на версиях ATV ниже 6.0 даже в случае, если в настройках показ приложения был разрешен; версии ATV на единицу ниже версии iOS, и ATV 6.0 эквивалентно версии iOS 7.0).

Казалось бы, нужно просто обновиться до версии ATV 6.0 и перезагрузить профиль. Все просто, не правда ли? За исключением того, что это не работает.

Выясняется, что компания Apple также добавила условие подписи профиля до версий 6.0 (и снова спасибо @tmm1, предоставившего убедительное доказательство сему факту). Так когда же это произошло? И можем ли мы обойти эту защиту, например, путем создания профиля подписанного достоверным центром сертификации (CA)?

Отличный вопрос! Давайте разбираться.

Добавление конфигурационного профиля в ATV происходит во фреймворке ManagedConfiguration, в частности в демоне profiled:

/System/Library/PrivateFrameworks/ManagedConfiguration.framework
/Support/profiled
Метод

[MCProfile evaluateTrustOfCertificateChain:(id)
outIsAllowedToWriteDefaults:(char *)]

по существу отвечает на вопрос: «позволено ли подписанному профилю записывать в значения по умолчанию компонента com.apple.frontrow». Проверка происходит в следующем методе:

[MCProfileTrustEvaluator sanitizedProfileSignerCertificateChain
IsAllowedToWriteDefaults:(id)]

Я немного структурировал код:

policy = SecPolicyCreateConfigurationProfileSigner()
trust = SecTrustCreateWithCertificates(cert_chain, policy)
result = SecTrustEvaluate(trust)

if (result == 4 || result == 1)
ALLOWED = TRUE
else
ALLOWED = FALSE

Дальше уже становится намного проще, поскольку все функции задокументированы. Для начала рассмотрим содержимое функции SecPolicyCreateConfigurationProfileSigner. В гугле находим следующий файл: SecPolicyPriv.h.

/*!
@function SecPolicyCreateConfigurationProfileSigner
@abstract Check for key usage of digital signature, has a EKU OID of
1.2.840.113635.100.4.16 and
roots to Apple Application Integration 2 Certification Authority
*/
SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void);

После просмотра файла становится ясно, что в сертификате, который используется для подписи профиля, необходимо присутствие специального ключа (1.2.840.113635.100.4.16). За более подробной информации обращайтесь к соответствующей документации.

На самом деле, проблемы особой нет, и мы можем просто подделать этот ключ. А что насчет проверки второй части условия: «roots to Apple»? (дословно: «корни к Apple»). Если из условия следует, что «эмитент (или выданный сертификат) должен называться Apple», то мы должны уметь подделывать это. Давайте заглянем в файл SecPolicy.c (я объединил значимые части в один блок):

static const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = {
0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58,
0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60
};

static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef
options)
{
return SecPolicyAddAnchorSHA1Options(options, kAppleCASHA1);
}

SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void)
{
SecPolicyRef result = NULL;
CFMutableDictionaryRef options = NULL;
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks), errOut);

SecPolicyAddBasicX509Options(options);
SecPolicyAddAppleAnchorOptions(options);

// Require the profile signing EKU
add_eku(options, &oidAppleExtendedKeyUsageProfileSigning);

require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner,
options), errOut);

errOut:
CFReleaseSafe(options);
return result;
}

В этом коде создается объект SecPolicyRef, которому необходимы данные X509, вышеупомянутый флаг EKU и привязка к Apple. Функция AddAppleAnchor является реальным ключом, которая добавляет проверку для SHA1 хеша. Черт! Происходит привязка к определенному сертификату корневого центра сертификации на основе SHA1 хеша этого сертификата.

Если у вас ATV версии 6.x и нет загруженного профиля с приложением Add Site, вы не сможете добавить приложение до тех пор, пока не получите профиль подписанный Apple. А поскольку программа Apple TV не имеет доступа во внешнюю среду, вы не сможете получить этот профиль.

Надежная защита, не правда ли?

Однако все же существует один метод: если ваш ATV версии 5.2 или 5.3 вы можете добавить профиль (но при этом вы все равно не увидите кнопку), а затем обновиться до версии 6.0, после чего приложение Add Site станет полностью доступным.

В конце концов, мы одержали победу, верно? Не стоит торопиться с выводами. Компания Apple добавила проверку на сигнатуру при использовании приложения Add Site, однако, эта тема другой статьи.

Где кванты и ИИ становятся искусством?

На перекрестке науки и фантазии — наш канал

Подписаться