Wednesday, December 12, 2018

Adventures in Video Conferencing Part 4: What Didn't Work Out with WhatsApp

Posted by Natalie Silvanovich, Project Zero

Not every attempt to find bugs is successful. When looking at WhatsApp, we spent a lot of time reviewing call signalling hoping to find a remote, interaction-less vulnerability. No such bugs were found. We are sharing our work with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hopes of saving ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r researchers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time it took to go down this very long road. Or maybe it will give ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs ideas for vulnerabilities we didn’t find.

As discussed in Part 1, signalling is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process through which video conferencing peers initiate a call. Usually, at least part of signalling occurs before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving peer answers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. This means that if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code that processes incoming signals before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is answered, it does not require any user interaction.

WhatsApp implements signalling using a series of WhatsApp messages. Opening libwhatsapp.so in IDA, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are several native calls that handle incoming signalling messages.

Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOffer
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferAck
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallGroupInfo
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallRekeyRequest
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallFlowControl
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferReceipt
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallAcceptReceipt
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferAccept
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferPreAccept
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallVideoChanged
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallVideoChangedAck
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferReject
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallTerminate
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallTransport
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallRelayLatency
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallRelayElection
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallInterrupted
Java_com_whatsapp_voipcalling_Voip_nativeHandleCallMuted
Java_com_whatsapp_voipcalling_Voip_nativeHandleWebClientMessage

Using apktool to extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp APK, it appears cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se natives are called from a loop in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 com.whatsapp.voipcalling.Voip class. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smali, it looks like signalling messages are sent as WhatsApp messages via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp server, and this loop handles cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 incoming messages.

Immediately, I noticed that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was a peer-to-peer encrypted portion of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message is only encrypted peer-to-server). I thought this had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest potential of reaching bugs, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server would not be able to sanitize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data. In order to be able to read and alter encrypted packets, I set up a remote server with a python script that opens a socket. Whenever this socket receives data, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data is displayed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 screen, and I have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 option of eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r sending cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unaltered packet or altering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet before it is sent. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n looked for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp smali where messages are peer-to-peer encrypted.

Since WhatsApp uses libsignal for peer-to-peer encryption, I was able to find where messages are encrypted by matching log entries. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n added smali code that sends a packet with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server I set up, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n replaces it with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server returns (changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 byte array if necessary). This allowed me to view and alter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peer-to-peer encrypted message. Making a call using this modified APK, I discovered that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peer-to-peer message was always exactly 24 bytes long, and appeared to be random. I suspected that this was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call, and confirmed this by looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smali.

A single encryption key doesn’t have a lot of potential for malformed data to lead to bugs (I tried lengcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ning and shortening it to be safe, but got nothing but unexploitable null pointer issues), so I moved on to looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peer-to-server encrypted messages. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Voip loop in smali, it looked like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 general flow is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device receives an incoming message, it is deserialized and if it is of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right type, it is forwarded to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messaging loop. Then certain properties are read from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message, and it is forwarded to a processing function based on its type. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processing function reads even more properties, and calls one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above native methods with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 properties as its parameters. Most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se functions have more than 20 parameters.

Many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se functions perform logging when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are called, so by making a test call, I could figure out which functions get called before a call is picked up. It turns out that during a normal incoming call, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device only receives an offer and calls Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOffer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n spawns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 incoming call screen in WhatsApp. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r signal types are not used until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is picked up.

An immediate question I had was whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r signal types are processed if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are received before a call is picked up. Just because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initiating device never sends cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se signal types before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is picked up doesn’t mean cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device wouldn’t process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m if it received cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

Looking through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 APK smali, I found cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class com.whatsapp.voipcalling.VoiceService$DefaultSignalingCallback that has several methods like sendOffer and sendAccept that appeared to send cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messages that are processed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se native calls. I changed sendOffer to call ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r send methods, like sendAccept instead of its normal messaging functionality. Trying this, I discovered that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Voip loop will process any signal type regardless of whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call has been answered. The native methods will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n parse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters, process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m and put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 results in a buffer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n call a single method to process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer. It is only at that point processing will stop if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message is of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wrong type.
I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n reviewed all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above methods in IDA. The code was very conservatively written, and most needed checks were performed. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were a few areas that potentially had bugs that I wanted to investigate more. I decided that changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters to calls in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 com.whatsapp.voipcalling.VoiceService$DefaultSignalingCallback was too slow to test cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of cases I wanted to test, and went looking for anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r way to alter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messages.

Ideally, I wanted a way to pass peer-to-server encrypted messages to my server before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were sent, so I could view and alter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. I went through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp APK smali looking for a point after serialization but before encryption where I could add my smali function that sends and alters cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packets. This was fairly difficult and time consuming, and I eventually put my smali in every method that wrote to a non-file ByteArrayOutputStream in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 com.whatsapp.protocol and com.whatsapp.messaging packages (about 10 total) and looked for where it got called. I figured out where it got called, and fixed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class so that anywhere a byte array was written out from a stream, it got sent to my server, and removed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r calls. (If you’re following along at home, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smali file I changed included cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string “Double byte dictionary token out of range”, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two methods I changed contained calls to toByteArray, and ended with invoking a protocol interface.) Looking at what got sent to my server, it seemed like a reasonably comprehensive collection of WhatsApp messages, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signalling messages contained what I thought cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y would.

WhatsApp messages are in a compressed XMPP format. A lot of parsers have been written for reverse engineering this protocol, but I found cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whatsapp-reveng parser worked cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best. I did have to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tokens in whatsapp_defines.py with a list extracted from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 APK for it to work correctly though. This made it easier to figure out what was in each packet sent to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server.

Playing with this a bit, I discovered that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are three types of checks in WhatsApp signalling messages. First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server validates and modifies incoming signalling messages. Secondly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messages are deserialized, and this can cause errors if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format is incorrect, and generally limits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Java message object that is passed on. Finally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 native methods perform checks on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir parameters.

These additional checks prevented several of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 areas I thought were problems from actually being problems. For example, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a function called by Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOffer that takes in an array of byte arrays, an array of integers and an array of booleans. It uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se values to construct candidates for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. It checks that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array of byte arrays and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array of integers are of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same length before it loops through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, using values from each, but it does not perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same check on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 boolean array. I thought that this could go out of bounds, but it turns out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 integer and booleans are serialized as a vector of pairs, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 arrays are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n copied from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector, so it is not actually possible to send arrays with different lengths.

One area of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signalling messages that looked especially concerning was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 voip_options field of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message. This field is never sent from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sending device, but is added to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server before it is forwarded to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device. It is a buffer in JSON format that is processed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device and contains dozens of configuration parameters.

{"aec":{"offset":"0","mode":"2","echo_detector_mode":"4","echo_detector_impl":"2","ec_threshold":"50","ec_off_threshold":"40","disable_agc":"1","algorithm":{"use_audio_packet_rate":"1","delay_based_bwe_trendline_filter_enabled":"1","delay_based_bwe_bitrate_estimator_enabled":"1","bwe_impl":"5"},"aecm_adapt_step_size":"2"},"agc":{"mode":"0","limiterenable":"1","compressiongain":"9","targetlevel":"1"},"bwe":{"use_audio_packet_rate":"1","delay_based_bwe_trendline_filter_enabled":"1","delay_based_bwe_bitrate_estimator_enabled":"1","bwe_impl":"5"},"encode":{"complexity":"5","cbr":"0"},"init_bwe":{"use_local_probing_rx_bitrate":"1","test_flags":"982188032","max_tx_rott_based_bitrate":"128000","max_bytes":"8000","max_bitrate":"350000"},"ns":{"mode":"1"},"options":{"connecting_tone_desc": "test","video_codec_priority":"2","transport_stats_p2p_threshold":"0.5","spam_call_threshold_seconds":"55","mtu_size":"1200","media_pipeline_setup_wait_threshold_in_msec":"1500","low_battery_notify_threshold":"5","ip_config":"1","enc_fps_over_capture_fps_threshold":"1","enable_ssrc_demux":"1","enable_preaccept_received_update":"1","enable_periodical_aud_rr_processing":"1","enable_new_transport_stats":"1","enable_group_call":"1","enable_camera_abtest_texture_preview":"1","enable_audio_video_switch":"1","caller_end_call_threshold":"1500","call_start_delay":"1200","audio_encode_offload":"1","android_call_connected_toast":"1"}
Sample voip_options (truncated)

If a peer could send a voip_options parameter to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r peer, it would open up a lot of attack surface, including a JSON parser and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se parameters. Since this parameter almost always appears in an offer, I tried modifying an offer to contain one, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 offer was rejected by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp server with error 403. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were three ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r signal types in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 incoming call flow that could accept a voip_options parameter. Java_com_whatsapp_voipcalling_Voip_nativeHandleCallOfferAccept and Java_com_whatsapp_voipcalling_Voip_nativeHandleCallVideoChanged were accepted by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server if a voip_options parameter was included, but it was stripped before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message was sent to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peer. However, if a voip_options parameter was attached to a Java_com_whatsapp_voipcalling_Voip_nativeHandleCallGroupInfo message, it would be forwarded to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peer device. I confirmed this by sending malformed JSON looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 log of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device for an error.

The voip_options parameter is processed by WhatsApp in three stages. First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON is parsed into a tree. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tree is transformed to a map, so JSON object properties can be looked up efficiently even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are dozens of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. Finally, WhatsApp goes through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 map, looking for specific parameters and processes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, usually copying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to an area in memory where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will set a value relevant to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call being made.

Starting off with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON parser, it was clearly cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP JSON parser. I compiled cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code and fuzzed it, and only found one minor out-of-bounds read issue.

I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n looked at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conversion of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON tree output from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 map. The map is a very efficient structure. It is a hash map that uses FarmHash as its hashing algorithm, and it is designed so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire map is stored in a single slab of memory, even if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON objects are deeply nested. I looked at many open source projects that contained similar structures, but could not find one that looked similar. I looked through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 creation of this structure in great detail, looking especially for type confusion bugs as well as errors when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory slab is expanded, but did not find any issues.

I also looked at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functions that go through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 map and handle specific parameters. These functions are extremely long, and I suspect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are generated using a code generation tool such as bison. They mostly copy parameters into static areas of memory, at which point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y become difficult to trace. I did not find any bugs in this area eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than going through parameter names and looking for value that seemed likely to cause problems, I did not do any analysis of how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values fetched from JSON are actually used. One parameter that seemed especially promising was an A/B test parameter called setup_video_stream_before_accept. I hoped that setting this would allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device to accept RTP before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is answered, which would make RTP bugs interaction-less, but I was unable to get this to work.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of looking at this code, it became difficult to verify its functionality without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to debug it. Since WhatsApp ships an x86 library for Android, I wondered if it would be possible to run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON parser on Linux.

Tavis Ormandy created a tool that can load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libwhatsapp.so library on Linux and run native functions, so long as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y do not have a dependency on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JVM. It works by patching cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 .dynamic ELF section to remove unnecessary dependencies by replacing DT_NEEDED tags with DT_DEBUG tags. We also needed to remove constructors and deconstructors by changing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DT_FINI_ARRAYSZ and DT_INIT_ARRAYSZ to zero. With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se changs in place, we could load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library using dlopen() and use dlsym() and dlclose() as normal.

Using this tool, I was able to look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON parsing in more detail. I also set up distributed fuzzing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 JSON binary. Unfortunately, it did not uncover any bugs eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r.

Overall, WhatsApp signalling seemed like a promising attack surface, but we did not find any vulnerabilities in it. There were two areas where we were able to extend cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface beyond what is used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 basic call flow. First, it was possible to send signalling messages that should only be sent after a call is answered before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is answered, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were processed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device. Second, it was possible for a peer to send voip_options JSON to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r device. WhatsApp could reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface of signalling by removing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se capabilities.

I made cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se suggestions to WhatsApp, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y responded that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were already aware of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first issue as well as variants of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second issue. They said cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of limiting what signalling messages can be processed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device before a call is answered. They had already fixed ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issues where a peer can send voip_options JSON to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r peer, and fixed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method I reported as well. They said cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are also considering adding cryptographic signing to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 voip_options parameter so a device can verify it came from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 server to furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r avoid issues like this. We appreciate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir quick resolution of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 voip_options issue and strong interest in implementing defense-in-depth measures.

In Part 5, we will discuss cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conclusions of our research and make recommendations for better securing video conferencing.

Tuesday, December 11, 2018

Adventures in Video Conferencing Part 3: The Even Wilder World of WhatsApp

Posted by Natalie Silvanovich, Project Zero

WhatsApp is anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r application that supports video conferencing that does not use WebRTC as its core implementation. Instead, it uses PJSIP, which contains some WebRTC code, but also contains a substantial amount of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r code, and predates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC project. I fuzzed this implementation to see if it had similar results to WebRTC and FaceTime.

Fuzzing Set-up

PJSIP is open source, so it was easy to identify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP code in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android WhatsApp binary (libwhatsapp.so). Since PJSIP uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open source library libsrtp, I started off by opening cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary in IDA and searching for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string srtp_protect, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function libsrtp uses for encryption. This led to a log entry emitted by a function that looked like srtp_protect. There was only one function in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary that called this function, and called memcpy soon before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. Some log entries before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call contained cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file name srtp_transport.c, which exists in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP repository. The log entries in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp binary say that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function being called is transport_send_rtp2 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP source only has a function called transport_send_rtp, but it looks similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function calling srtp_protect in WhatsApp, in that it has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same number of calls before and after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy. Assuming that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code in WhatsApp is some variation of that code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy copies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire unencrypted packet right before it is encrypted.

Hooking this memcpy seemed like a possible way to fuzz WhatsApp video calling. I started off by hooking memcpy for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire app using a tool called Frida. This tool can easily hook native function in Android applications, and I was able to see calls to memcpy from WhatsApp within minutes. Unfortunately though, video conferencing is very performance sensitive, and a delay sending video packets actually influences cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next packet, so hooking every memcpy call didn’t seem practical. Instead, I decided to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 single memcpy to point to a function I wrote.

I started off by writing a function in assembly that loaded a library from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem using dlopen, retrieved a symbol by calling dlsym and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n called into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library. Frida was very useful in debugging this, as it could hook calls to dlopen and dlsym to make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were being called correctly. I overwrote a function in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp GIF transcoder with this function, as it is only used in sending text messages, which I didn’t plan to do with this altered version. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy call to point to this function instead of memcpy, using this online ARM branch finder.

sub_2F8CC
MOV             X21, X30
MOV             X22, X0
MOV             X23, X1
MOV             X20, X2
MOV             X1, #1
ADRP            X0, #aDataDataCom_wh@PAGE ; "/data/data/com.whatsapp/libn.so"
ADD             X0, X0, #aDataDataCom_wh@PAGEOFF ; "/data/data/com.whatsapp/libn.so"
BL              .dlopen
ADRP            X1, #aApthread@PAGE ; "apthread"
ADD             X1, X1, #aApthread@PAGEOFF ; "apthread"
BL              .dlsym
MOV             X8, X0
MOV             X0, X22
MOV             X1, X23
MOV             X2, X20
NOP
BLR             X8
MOV             X30, X21
RET
The library loading function

I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n wrote a library for Android which had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same parameters as memcpy, but fuzzed and copied cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer instead of just copying it, and put it on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem where it would be loaded by dlopen. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n tried making a WhatsApp call with this setup. The video call looked like it was being fuzzed and crashed in roughly fifteen minutes.

Replay Set-up


To replay cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packets I added logging to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library, so that each buffer that was altered would also be saved to a file. Then I created a second library that copied cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer being copied instead of altering it. This required modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp binary slightly, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packet will usually not be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet currently being sent. I changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hooked memcpy to be passed by reference instead of by value, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packet. This changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length so that it would be correct for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to srtp_protect. Luckily, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet is copied into is a fixed length, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no concern that a valid packet will overflow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer length. This is a common design pattern in RTP processing that improves performance by reducing length checks. It was also helpful in modifying FaceTime to replay packets of varying length, as described in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous post.

This initial replay setup did not work, and looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets, it turned out that WhatsApp uses four streams with different SSRCs for video conferencing (possibly one for video, one for audio, one for synchronization and one for good luck). The streams each had only one payload type, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were all different, so it was fairly easy to map each SSRC to its stream. So I modified cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replay library to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current SSRC for each stream based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload types of incoming packets, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSRC of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replayed packets with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct one based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir payload type. This reliably replayed a WhatsApp call. I was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n able to fuzz and reproduce crashes on WhatsApp.

Results

Using this setup, I reported one heap corruption issue on WhatsApp, CVE-2018-6344. This issue has since been fixed. After this issue was resolved, fuzzing did not yield any additional crashes with security impact, and we moved on to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r methodologies. Part 4 will describe our ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r (unsuccessful) attempts to find vulnerabilities in WhatsApp.

Wednesday, December 5, 2018

Adventures in Video Conferencing Part 2: Fun with FaceTime

Posted by Natalie Silvanovich, Project Zero

FaceTime is Apple’s video conferencing application for iOS and Mac. It is closed source, and does not appear to use any third-party libraries for its core functionality. I wondered whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r fuzzing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of FaceTime’s audio and video streams would lead to similar results as WebRTC.

Fuzzing Set-up


Philipp Hancke performed an excellent analysis of FaceTime’s architecture in 2015. It is similar to WebRTC, in that it exchanges signalling information in SDP format and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n uses RTP for audio and video streams. Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FaceTime implementation on a Mac, it seemed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bulk of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling functionality of FaceTime is in a daemon called avconferenced. Opening up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary that supports its functionality, AVConference in IDA, it contains a function called SRTPEncryptData. This function cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calls CCCryptorUpdate, which appeared to encrypt RTP packets below cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header.

To do a quick test of whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r fuzzing was likely to be effective, I hooked this function and altered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying encrypted data. Normally, this can be done by setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DYLD_INSERT_LIBRARIES environment variable, but since avconferenced is a daemon that restarts automatically when it dies, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re wasn’t an easy way to set an environment variable. I eventually used insert_dylib to alter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AVConference binary to load a library on startup, and restarted cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process. The library loaded used DYLD_INTERPOSE to replace CCCryptorUpdate with a version that fuzzed every input buffer (using fuzzer q from Part 1) before it was processed. This implementation had a lot of problems: it fuzzed both encryption and decryption, it affected every call to CCCryptorUpdate from avconferenced, not just ones involved in SRTP and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was no way to reproduce a crash. But using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modified FaceTime to call an iPhone led to video output that looked corrupted, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 phone crashed in a few minutes. This confirmed that this function was indeed where FaceTime calls are encrypted, and that fuzzing was likely to find bugs.

I made a few changes to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function that hooked CCCryptorUpdate to attempt to solve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se problems. I limited fuzzing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input buffer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two threads that write audio and video output to RTP, which also solved cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem of decrypted packets being fuzzed, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se threads only ever encrypt. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n added functionality that wrote cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted, fuzzed contents of each packet to a series of log files, so that test cases could be replayed. This required altering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox of avconferenced so that it could write files to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 log location, and adding spinlocks to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hook, as calling CCCryptorUpdate is thread safe, but logging packets isn’t.

Call Replay


I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n wrote a second library that hooks CCCryptorUpdate and replays packets logged by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first library by copying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets in sequence into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet buffers passed into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function. Unfortunately, this required a small modification to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AVConference binary, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SRTPEncryptData function does not respect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length returned by CCCryptorUpdate; instead, it assumes that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted data is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plaintext data, which is reasonable when CCCryptorUpdate isn’t being hooked. Since SRTPEncryptData always uses a large fixed-size buffer for encryption, and encryption is in-place, I changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function to retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted buffer from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 very end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer, which was set in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hooked CCCryptorUpdate call. This memory is unlikely to be used for ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r purposes due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 typical shorter length of RTP packets. Unfortunately though, even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same encrypted data was being replayed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target, it wasn’t being processed correctly by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device.

To understand why requires an explanation of how RTP works. An RTP packet has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following format.


It contains several fields that impact how its payload is interpreted. The SSRC is a random identifier that identifies a stream. For example, in FaceTime cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 audio and video streams have different SSRCs. SSRCs can also help differentiate between streams in a situation where a user could potentially have an unlimited number of streams, for example, multiple participants in a video call. RTP packets also have a payload type (PT in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 diagram) which is used to differentiate different types of data in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload. The payload type for a certain data type is consistent across calls. In FaceTime, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video stream has a single payload type for video data, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 audio stream has two payload types, likely one for audio data and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r for synchronization. The marker (M in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 diagram) field of RTP is also used by FaceTime to represent when a packet is fragmented, and needs to be reassembled.

From this it is clear that simply copying logged data into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current encrypted packet won’t function correctly, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data needs to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct SSRC, payload type and marker, or it won’t be interpreted correctly. This wasn’t necessary in WebRTC, because I had enough control over WebRTC that I could create a connection with a single SSRC and payload type for fuzzing purposes. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no way to do this in FaceTime, even muting a video call leads to silent audio packets being sent as opposed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 audio stream shutting down. So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se values needed to be manually corrected.

An RTP feature called extensions made correcting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se fields difficult. An extension is an optional header that can be added to an RTP packet. Extensions are not supposed to depend on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RTP payload to be interpreted, and extensions are often used to transmit network or display features. Some examples of supported extensions include cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 orientation extension, which tells cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 endpoint cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 orientation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mute extension, which tells cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 endpoint whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving device is muted.

Extensions mean that even if it is possible to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload type, marker and SSRC of data, this is not sufficient to replay cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact packet that was sent. Moreover, FaceTime creates extensions after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet is encrypted, so it is not possible to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complete RTP packet by hooking CCCryptorUpdate, because extensions could be added later.

At this point, it seemed necessary to hook sendmsg as well as CCCryptorUpdate. This would allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 outgoing RTP header to be modified once it is complete. There were a few challenges in doing this. To start, audio and video packets are sent by different threads in FaceTime, and can be reordered between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are encrypted and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are sent by sendmsg. So I couldn’t assume that if sendmsg received an RTP packet that it was necessarily cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last one that was encrypted. There was also cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem that SSRCs are dynamic, so replaying an RTP packet with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same SSRC it is recorded with won’t work, it needs to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new SSRC for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 audio or video stream.

Note that in MacOS Mojave, FaceTime can call sendmsg via eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AVConference binary or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IDSFoundation binary, depending on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 network configuration. So to capture and replay unencrypted RTP traffic on newer systems, it is necessary  to hook CCCryptorUpdate in AConference and sendmsg in IDSFoundation (AVConference calls into IDSFoundation when it calls sendmsg). Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as on older systems.

I ended up implementing a solution that recorded packets by recording cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unencrypted payload, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n recorded its RTP header, and using a snippet of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted payload to pair headers with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct unencrypted payload. Then to replay packets, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packets encrypted in CCCryptorUpdate were replaced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets, and once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted payload came through to sendmsg, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header was replaced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged one for that payload. Fortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two streams with unique SSRCs used by FaceTime do not share any payload types, so it was possible to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new SSRC for each stream by waiting for an incoming packet with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct payload type. Then in each subsequent packet, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSRC was replaced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct one.

Unfortunately, this still did not replay a FaceTime call correctly, and calls often experienced decryption failures. I eventually determined that audio and video on FaceTime are encrypted with different keys, and updated cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replay script to queue cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CCCryptor used by CCCryptorUpdate function based on whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r it was audio or video content. Then in sendmsg, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire logged RTP packet, including cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unencrypted payload, was copied into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 outgoing packet, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSRC was fixed, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload encrypted with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next CCCryptor out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 appropriate queue. If a CCCryptor wasn’t available, outgoing packets were dropped until a new one was created. At this point, it was possible to stop using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modified AVConference binary, as all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet modification was now happening in sendmsg. This implementation still had reliability problems.

Digging more deeply into how FaceTime encryption works, packets are encrypted in CTS mode, which requires a counter. The counter is initialized to a unique value for each packet that is sent. During cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initialization of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RTP stream, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peers exchange two 16-byte random tokens, one for audio and one for video. The counter value for each packet is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calculated by exclusive or-ing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token with several values found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet, including cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSRC and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence number. Only one value in this calculation, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence number, changes between each packet. So it is possible to calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 counter value for each packet by knowing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial counter value and sequence number, which can be retrieved by hooking CCCryptorCreateWithMode. The sequence number is xor-ed with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 random token at index 0x12 when FaceTime constructs a counter, so by xor-ing this location with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial sequence number and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n a packet’s sequence number, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 counter value for that packet can be calculated. The key can also be retrieved by hooking CCCryptorCreateWithMode.This allowed me to dispense with queuing cryptors, as I now had all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information I needed to construct a cryptor for any packet. This allowed for packets to be encrypted faster and more accurately.

Sequence numbers still posed a problem though, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial sequence number of an RTP stream is randomly generated at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call, and is different between subsequent calls. Also, sequence numbers are used to reconstruct video streams in order, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y need to be correct. I altered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replay tool determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 starting sequence number of each stream, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difference between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 starting sequence number of each logged stream and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence number of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packet and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n add it to this value. These two changes finally made cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replay tool work, though replay gets slower and slower as a stream is replayed due to dropped packets.   

Results


Using this setup, I was able to fuzz FaceTime calls and reproduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crashes. I reported three bugs in FaceTime based on this work. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues have been fixed in recent updates.

CVE-2018-4366 is an out-of-bounds read in video processing that occurs on Macs only.

CVE-2018-4367 is a stack corruption vulnerability that affects iOS and Mac. There are a fair number of variables on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 affected function before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack cookie, and several fuzz crashes due to this issue caused segmentation faults as opposed to stack_chk crashes, so it is likely exploitable.

CVE-2018-4384 is a kernel heap corruption issue in video processing that affects iOS. It is likely similar to this vulnerability found by Adam Donenfeld of Zimperium.

All of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues took less than 15 minutes of fuzzing to find on a live device. Unfortunately, this was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 limit of fuzzing that could be performed on FaceTime, as it would be difficult to create a command line fuzzing tool with coverage like we did for WebRTC as it is closed source.

In Part 3, we will look at video calling in WhatsApp.

Tuesday, December 4, 2018

Adventures in Video Conferencing Part 1: The Wild World of WebRTC

Posted by Natalie Silvanovich, Project Zero

Over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 past five years, video conferencing support in websites and applications has exploded. Facebook, WhatsApp, FaceTime and Signal are just a few of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 many ways that users can make audio and video calls across networks. While a lot of research has been done into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cryptographic and privacy properties of video conferencing, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is limited information available about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se platforms and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir susceptibility to vulnerabilities. We reviewed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 three most widely-used video conferencing implementations. In this series of blog posts, we describe what we found.

This part will discuss our analysis of WebRTC. Part 2 will cover our analysis of FaceTime. Part 3 will discuss how we fuzzed WhatsApp. Part 4 will describe some attacks against WhatsApp that didn’t work out. And finally, Part 5 will discuss cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future of video conferencing and steps that  developers can take to improve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir implementation.

Typical Video Conferencing Architecture


All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video conferencing implementations we investigated allow at least two peers anywhere on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Internet to communicate through audiovisual streams. Implementing this capability so that it is reliable and has good audio and video quality presents several challenges. First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peers need to be able to find each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and establish a connection regardless of NATs or ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r network infrastructure. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y need to be able to communicate, even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could be on different platforms, application versions or browsers. Finally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y need to maintain audio and video quality, even if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection is low-bandwidth or noisy.

Almost all video conferencing solutions have converged on a single architecture. It assumes that two peers can communicate via a secure, integrity checked channel which may have low bandwidth or involve an intermediary server, and it allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to create a faster, higher-bandwidth peer-to-peer channel.

The first stage in creating a connection is called signalling. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process through which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two peers exchange cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will need to create a connection, including network addresses, supported codecs and cryptographic keys. Usually, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calling peer sends a call request including information about itself to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving peer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving peer responds with similar information. SDP is a common protocol for exchanging this information, but it is not always used, and most implementations do not conform to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specification. It is common for mobile messaging apps to send this information in a specially formatted message, sent through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same channel text messages are sent. Websites that support video conferencing often use WebSockets to exchange information, or exchange it via HTTPS using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 webserver as an intermediary.

Once signalling is complete, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peers find a way to route traffic to each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 STUN, TURN and ICE protocols. Based on what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se protocols determine, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peers can create UDP, UDP-over-STUN and occasionally TCP connections based of what is favorable for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 network conditions.

Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection has been made, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peers communicate using Real-time Transport Protocol. Though this protocol is standardized, most implementations deviate somewhat from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 standard. RTP can be encrypted using a protocol called Secure RTP (SRTP), and some implementations also encrypt streams using DTLS. Under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption envelope, RTP supports features that allow multiple streams and formats of data to be exchanged simultaneously. Then, based on how RTP classifies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data, it is passed on to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r processing, such as video codecs.  Stream Control Transmission Protocol (SCTP) is also sometimes used to exchange small amounts of data (for example a text message on top of a call) during video conferencing, but it is less commonly used than RTP.

Even when it is encrypted, RTP often doesn’t include integrity protection, and if it does, it usually doesn’t discard malformed packets. Instead, it attempts to recover cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m using strategies such as Forward Error Correction (FEC). Most video conferencing solutions also detect when a channel is noisy or low-bandwidth and attempt to handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 situation in a way that leads to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best audio and video quality, for example, sending fewer frames or changing codecs. Real Time Control Protocol (RTCP) is used to exchange statistics on network quality and coordinate adjusting properties of RTP streams to adapt to network conditions.

WebRTC


WebRTC is an open source project that enables video conferencing. It is by far cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most commonly used implementation. Chrome, Safari, Firefox, Facebook Messenger, Signal and many ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r mobile applications use WebRTC. WebRTC seemed like a good starting point for looking at video conferencing as it is heavily used, open source and reasonably well-documented.

WebRTC Signalling


I started by looking at WebRTC signalling, because it is an attack surface that does not require any user interaction. Protocols like RTP usually start being processed after a user has picked up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video call, but signalling is performed before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user is notified of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. WebRTC uses SDP for signalling.

I reviewed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC SDP parser code, but did not find any bugs. I also compiled it so it would accept an SDP file on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 commandline and fuzzed it, but I did not find any bugs through fuzzing eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r. I later discovered that WebRTC signalling is not implemented consistently across browsers anyhow. Chrome uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main WebRTC implementation, Safari has branched slightly and Firefox uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own implementation. Most mobile applications that use WebRTC implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own signalling in a protocol that is not SDP as well. So it is not likely that a bug in WebRTC signalling would affect a wide variety of targets.

RTP Fuzzing


I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n decided to look at how RTP is processed in WebRTC. While RTP is not an interaction-less attack surface because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user usually has to answer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call before RTP traffic is processed, picking up a call is a reasonable action to expect a user to take. I started by looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC source, but it is very large and complex, so I decided fuzzing would be a better approach.

The WebRTC repository contains fuzzers written for OSS-Fuzz for every protocol and codec supported by WebRTC, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y do not simulate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interactions between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 various parsers, and do not maintain state between test cases, so it seemed likely that end-to-end fuzzing would provide additional coverage.

Setting up end-to-end fuzzing was fairly time intensive, so to see if it was likely to find many bugs, I altered Chrome to send malformed RTP packets. I changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 srtp_protect function in libsrtp so that it ran cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following fuzzer on every packet:

void fuzz(char* buf, int len){

int q = rand()%10;

if (q == 7){
int ind = rand()%len;
buf[ind] = rand();
}

if(q == 5){
for(int i = 0; i < len; i++)
buf[i] = rand();

}
RTP fuzzer (fuzzer q)

When this version was used to make a WebRTC call to an unmodified instance of Chrome, it crashed roughly every 30 seconds.

Most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crashes were due to divide-by-zero exceptions, which I submitted patches for, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were three interesting crashes. I reproduced cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m by altering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC source in Chrome so that it would generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packets that caused cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same crashes, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n set up a standalone build of WebRTC to reproduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, so that it was not necessary to rebuild Chrome to reproduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues.

The first issue, CVE-2018-6130 is an out-of-bounds memory issue related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of std::map find in processing VP9 (a video codec). In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value t10_pic_idx is pulled out of an RTP packet unverified (GOF stands for group of frames).

if (frame->frame_type() == kVideoFrameKey) {
   ...
   GofInfo info = gof_info_.find(codec_header.tl0_pic_idx)->second;
   FrameReceivedVp9(frame->id.picture_id, &info);
   UnwrapPictureIds(frame);
   return kHandOff;
 }


If this value does not exist in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 gof_info_ array, std::map::find returns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 map, which points to one element past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated values for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 map. Depending on memory layout, dereferencing this iterator will eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r crash or return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of unallocated memory.

The second issue, CVE-2018-6129 is a more typical out-of-bounds read issue, where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 index of a field is read out of an RTP packet, and not verified before it is used to index a vector.

The third issue, CVE-2018-6157 is a type confusion issue that occurs when a packet that looks like a VP8 packet is sent to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 H264 parser. The packet will eventually be treated like an H264 packet even though it hasn’t gone through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 necessary checks for H264. The impact of this issue is also limited to reading out of bounds.
There are a lot of limitations to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 approach of fuzzing in a browser. It is very slow, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues are difficult to reproduce, and it is difficult to fuzz a variety of test cases, because each call needs to be started manually, and certain properties, such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default codec, can’t change in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. After I reported cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC team suggested that I use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video_replay tool, which can be used to replay RTP streams recorded in a patched browser. The tool was not able to reproduce a lot of my issues because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y used non-default WebRTC settings configured through signalling, so I added cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to load a configuration file alongside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RTP dump to this tool. This made it possible to quickly reproduce vulnerabilities in WebRTC.

This tool also had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 benefit of enabling much faster fuzzing, as it was possible to fuzz RTP by fuzzing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RTP dump file and loading it into video_replay. There were some false positives, as it was also possible that fuzzing caused bugs in parsing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RTP dump file format, but most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bugs were actually in RTP processing.
Fuzzing with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video_replay tool with code coverage and ASAN enabled led to four more bugs. We ran cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fuzzer on 50 cores for about two weeks to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues.

CVE-2018-6156 is probably cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most exploitable bug uncovered. It is a large overflow in FEC. The buffer WebRTC uses to process FEC packets is 1500 bytes, but it does no size checking of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se packets once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are extracted from RTP. Practically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y can be up to about 2000 bytes long.

CVE-2018-6155 is a use-after-free in a video codec called VP8. It is interesting because it affects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VP8 library, libvpx as opposed to code in WebRTC, so it has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 potential to affect software that uses this library ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than WebRTC. A generic fix for libvpx was released as a result of this bug.

CVE-2018-16071 is a use-after-free in VP9 processing that is somewhat similar to CVE-2018-6130. Once again, an untrusted index is pulled out of a packet, but this time it is used as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upper bounds of a vector erase operation, so it is possible to delete all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 elements of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector before it is used.

CVE-2018-16083 is an out-of-bounds read in FEC that occurs due to a lack of bounds checking.

Overall, end-to-end fuzzing found a lot of bugs in WebRTC, and a few were fairly serious. They have all now been fixed. This shows that end-to-end fuzzing is an effective approach for finding vulnerabilities in this type of video conferencing solution. In Part 2, we will try a similar approach on FaceTime. Stay tuned!