
إثبات المفهوم لـ ZRTP man-in-the-middle
CVE-2016-6271 يؤثر على libbzrtp، وهي مكتبة ZRTP طورتها Belledonne Communications.
هذه المكتبة مضمنة في تطبيقات المستخدم النهائي، مثل linphone، المتاح كـ تطبيق Android على متجر Play. الإصدار الحالي 3.2.7 يضم نسخة من libbzrtp لا ينبغي أن تكون معرضة لـ CVE-2016-6271.
cd vulnerable-bzrtp && docker build -t vulnerable-bzrtp .
cd mitm-bzrtp && docker build -t mitm-bzrtp .
docker-compose -f cve-2016-6271.yaml up
ZRTP هو حل لتأمين مكالمات الصوت عبر IP.
التالي مقتطف من IETF rfc6189:
ZRTP is a key agreement protocol that performs a Diffie-Hellman key
exchange during call setup in the media path and is transported over
the same port as the Real-time Transport Protocol (RTP) [RFC3550]
media stream which has been established using a signaling protocol
such as Session Initiation Protocol (SIP) [RFC3261]. This generates
a shared secret, which is then used to generate keys and salt for a
Secure RTP (SRTP) [RFC3711] session. ZRTP borrows ideas from
[PGPfone]. A reference implementation of ZRTP is available in
[Zfone].
The ZRTP protocol has some nice cryptographic features lacking in
many other approaches to media session encryption. Although it uses
a public key algorithm, it does not rely on a public key
infrastructure (PKI). In fact, it does not use persistent public
keys at all. It uses ephemeral Diffie-Hellman (DH) with hash
commitment and allows the detection of man-in-the-middle (MiTM)
attacks by displaying a short authentication string (SAS) for the
users to read and verbally compare over the phone.
للخلاصة:
يتم تجميع وكيل ZRTP قابل للاختراق من ملف C واحد:
ctx = bzrtp_createBzrtpContext(self_ssrc);
assert(ctx != NULL);
ret = bzrtp_setCallbacks(ctx, &bzrtp_callbacks);
assert(ret == 0);
bzrtp_initBzrtpContext(ctx);
bzrtp_setClientData(ctx, self_ssrc, ctx);
ret = bzrtp_startChannelEngine(ctx, self_ssrc);
assert(ret == 0);
for (now = 0; now += 50;) {
usleep(500000);
ret = recv(sd, buffer, sizeof(buffer), MSG_DONTWAIT);
if (ret > 0) {
received = ret;
bzrtp_processMessage(ctx, self_ssrc, buffer, received);
}
bzrtp_iterate(ctx, self_ssrc, now);
}
للاستمتاع به، قم ببناء صورة docker باستخدام cd vulnerable-bzrtp && docker build -t vulnerable-bzrtp .. انتبه أن Dockerfile يعرّف start.sh كنقطة دخول، والتي تقوم بتعيين التوجيه عبر mallory - المزيد عن ذلك لاحقًا.
تم الكشف عنه في 30 مارس 2016 لـ Belledone Communications، وتم إصلاح هذه الثغرة بسرعة من خلال هذا التزام.
يقوم ZRTP بإجراء Diffie-Hellman في رسالتين تسمى DHPart1 و DHPart2. يقوم Bob بالتزم رسالة DHPart2 التي سيرسلها بعد استلام DHPart1 من Alice.
| Commit (Bob's ZID, options, hash value) F5 |
|<--------------------------------------------------|
| F6 DHPart1 (pvr, shared secret hashes) |
|-------------------------------------------------->|
| DHPart2 (pvi, shared secret hashes) F7 |
|<--------------------------------------------------|
الثغرة المكتشفة في bzrtp هي غياب التحقق من التزام التجزئة، مما يترك مجالًا للمهاجم لتزوير pvi بخصائص مثيرة للاهتمام.
ينفذ هذا الإثبات المفاهيمي الضعف الموصوف في rfc6189:
The use of hash commitment in the DH exchange constrains the attacker to only one guess to generate the correct Short Authentication String (SAS) (Section 7) in his attack, which means the SAS can be quite short. A 16-bit SAS, for example, provides the attacker only one chance out of 65536 of not being detected. Without this hash commitment feature, a MiTM attacker would acquire both the pvi and pvr public values from the two parties before having to choose his own two DH public values for his MiTM attack. He could then use that information to quickly perform a bunch of trial DH calculations for both sides until he finds two with a matching SAS. To raise the cost of this birthday attack, the SAS would have to be much longer. The Short Authentication String would have to become a Long Authentication String, which would be unacceptable to the user. A hash commitment precludes this attack by forcing the MiTM to choose his own two DH public values before learning the public values of either of the two parties.
مع Mallory كمهاجم نشط، يصبح تبادل DH أعلاه كما يلي:
Bob Mallory Alice
| | Commit (Alice's ZID...) |
| |<------------------------|
| Commit (Alice's ZID...) | |
|<------------------------| |
| | |
| DHPart1 (pvr...) | |
|------------------------>| |
| | DHPart1 (pvr'...) |
| |------------------------>|
| | DHPart2 (pvi...) |
| |<------------------------|
| * SAS(Mallory, Alice) is known at this time * |
| * now find a pvi' such as SAS(Bob, Mallory) * |
| * equals SAS(Mallory, Alice) * |
| DHPart2(pvi'...) | |
|<------------------------| |
| * SAS(Mallory, Bob) = SAS(Alice, Mallory) * |
| * Both parties will confirm they share the same * |
| * SAS value * |
| * Note that SRTP material (Alice, Mallory) will * |
| * not match SRTP material (Mallory, Bob) * |
| * However, Mallory will be able to handle SRTP * |
| * flows from both Bob and Alice, giving * |
| * interception and tampering capabilities. * |
تم بناؤه باستخدام Python3 و asyncio. يتم التقاط حزم IP الخام باستخدام مقبس PF_PACKET، مع الاستماع فقط على إطارات IPv4. يساعد Scapy في تحليل الإطارات الخام. يقوم بتحليل حزم ZRTP وإعادة كتابتها، على وجه الخصوص، يعيد حساب علامات مصادقة HMAC.
مفكك SAS بالقوة الغاشمة مبني على C ويأخذ كمدخلات:
Hello of responder || Commit || DHPart1DHPart1قم ببناء صورة docker باستخدام cd mitm-bzrtp && docker build -t mitm-bzrtp . && cd ...
سيتم إعداد هجوم الوسيط بمساعدة:
Alice و Bob سيتواصلان عبر Mallory، والتي تقوم بشكل انتهازي بهجوم الوسيط.
يتلخص الأمر في اختبار svi مختلفة والتحقق مما إذا كانت SAS المشتقة تطابق SAS التي تم الحصول عليها بالفعل. يمكن العثور على جميع التفاصيل الدموية في مصدر bruteforce.
يتم مصادقة رسائل ZRTP باستخدام سلسلة معكوسة من التجزئات المتكررة كمفاتيح. إذا تم تعديل DHPart2 أثناء النقل بواسطة Mallory، فستكتشف Alice أن DHPart2 المشوه لـ Mallory غير أصلي، لأن HMAC المحسوب لن يتطابق مع HMAC المستلم. لاجتياز هذا الفحص، يجب على Mallory استخدام سلسلة كاملة من التجزئات المتكررة، وتحتاج إلى توقيع جميع الرسائل المرسلة باستخدام هذه السلسلة.