Changes

Jump to navigation Jump to search
6,283 bytes added ,  08:05, 15 August 2019
versioning
Line 120: Line 120:  
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]]
 
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]]
 
|-
 
|-
|  TSEC firmware compromises itself
+
maconstack (TSEC firmware leaves MAC on the stack)
 
|  Package1ldr loads a firmware blob into TSEC early on boot. This piece of code runs on the TSEC in Authenticated Mode and has the sole purpose of generating the per-console TSEC key (see [[Cryptosystem]]).
 
|  Package1ldr loads a firmware blob into TSEC early on boot. This piece of code runs on the TSEC in Authenticated Mode and has the sole purpose of generating the per-console TSEC key (see [[Cryptosystem]]).
   −
As a way to mitigate attacks, the TSEC firmware blob is split into 3 stages: [[TSEC#Stage_0|Stage 0]] which is unencrypted and unsigned, [[TSEC#Stage_1|Stage 1]] which is unencrypted but signed and [[TSEC#Stage_2|Stage 2]] which is encrypted and signed.
+
As a way to mitigate attacks, the TSEC firmware blob is split into 3 stages: [[TSEC_Firmware#Boot|Boot]] which is unencrypted and unsigned, [[TSEC_Firmware#KeygenLdr|KeygenLdr]] which is unencrypted but signed and [[TSEC_Firmware#Keygen|Keygen]] which is encrypted and signed.
Stage 0 loads a static pre-generated signature into the Falcon's CPU crypto registers, loads Stage 1 into the Falcon's CODE region and jumps to it. Execution will proceed into Stage 1 in Authenticated Mode if, and only if, the loaded signature matches the one Falcon calculates internally for Stage 1.
+
Boot loads a static pre-generated signature into the Falcon's CPU crypto registers, loads KeygenLdr into the Falcon's CODE region and jumps to it. Execution will proceed into KeygenLdr in Heavy Secure Mode if, and only if, the loaded signature matches the one Falcon calculates internally for KeygenLdr.
   −
Among various things, Stage 1 will attempt to do a "backwards" security check by calculating a CMAC over Stage 0 and comparing it with a known hash stored in the TSEC firmware's key data (a small buffer stored after Stage 0's code). If the hashes don't match, execution aborts.
+
Among various things, KeygenLdr will attempt to do a "backwards" security check by calculating a CMAC over Boot and comparing it with a known hash stored in the TSEC firmware's key data (a small buffer stored after Boot's code). If the hashes don't match, execution aborts.
   −
Stage 1 stores the calculated Stage 0's CMAC in the stack, but forgets to clear it. Since the stack is located in Falcon's DATA region, loading the TSEC firmware blob and dumping the DATA region afterwards (via MMIO) will reveal the calculated hash.
+
KeygenLdr stores the calculated Boot's CMAC in the stack, but forgets to clear it. Since the stack is located in Falcon's DATA region, loading the TSEC firmware blob and dumping the DATA region afterwards (via MMIO) will reveal the calculated hash.
This allows using Stage 1 as an oracle to generate a valid CMAC for arbitrary Stage 0 code. Replacing the CMAC in the TSEC firmware's key data region results in Stage 1 accepting any Stage 0 code, thus rendering this security measure useless.
+
This allows using KeygenLdr as an oracle to generate a valid CMAC for arbitrary Boot code. Replacing the CMAC in the TSEC firmware's key data region results in KeygenLdr accepting any Boot code, thus rendering this security measure useless.
   −
Additionally, since signed Falcon code can't be revoked without an hardware revision, an attacker can always reuse the flawed Stage 1 code even if a fix is issued.
+
Additionally, since signed Falcon code can't be revoked without an hardware revision, an attacker can always reuse the flawed KeygenLdr code even if a fix is issued.
|  Running TSEC firmware's Stage 1 in a user controlled environment. Mostly useless, but may aid in side-channel attacks.
+
|  Running TSEC firmware's KeygenLdr in a user controlled environment.
 
|  None
 
|  None
 
|  [[5.0.2]]
 
|  [[5.0.2]]
 
|  January 2018
 
|  January 2018
 
|  April 29, 2018
 
|  April 29, 2018
|  [[User:Hexkyz|hexkyz]], probably others (independently).
+
|  [[User:Hexkyz|hexkyz]], [[User:Rei|Reisyukaku]] (independently), probably others (independently).
 +
|-
 +
|  Stack smash in TSEC firmware's KeygenLdr
 +
|  Given that we can control the [[TSEC_Firmware#Key_data|key data]] (which is not authenticated) and the [[TSEC_Firmware#Boot|Boot]] blob (see "maconstack"), as well as the fact Non-secure and Heavy Secure code share the same stack, we can use this to attack KeygenLdr. KeygenLdr uses memcpy to copy over a payload to DMEM to verify it, which can be abused to smash the stack (in DMEM) and write over the return address of said function.
 +
|  ROP under KeygenLdr in Heavy Secure mode.
 +
|  None
 +
|  [[8.0.1]]
 +
|  Early 2018
 +
|  May 21, 2019
 +
|  Everyone (independently).
 
|-
 
|-
 
|  pk1ldrhax
 
|  pk1ldrhax
Line 156: Line 165:  
|  November 20, 2018
 
|  November 20, 2018
 
|  Everyone
 
|  Everyone
|-
   
|}
 
|}
   Line 218: Line 226:  
| [[8.0.0]]
 
| [[8.0.0]]
 
| 2017 (when TrustZone code plaintext was first obtained).
 
| 2017 (when TrustZone code plaintext was first obtained).
| April 15, 2018
+
| April 15, 2019
 
| Everyone
 
| Everyone
 +
|-
 +
|  deja vu (insufficient system state validation on suspend leads to pre-sleep BPMP code execution)
 +
|  Jamais Vu was fixed in [[2.0.0]] by making the PMC secure-world only, blacklisting the BPMP's exception vectors from being mapped, and thoroughly checking for malicious behavior on deep sleep entry, since gaining pre-sleep code execution on the BPMP compromises the system.
 +
 +
However, the state validation performed by Nintendo's Secure Monitor was insufficient to prevent pre-sleep execution from being obtained.
 +
 +
Prior to [[6.0.0]], one could use a DMA controller that had access to IRAM and was not held in reset (there were multiple) to race TrustZone's writes to the BPMP firmware in IRAM, and thus overwrite Nintendo's firmware with an attacker's to gain pre-sleep code execution.
 +
 +
[[6.0.0]] addressed this by performing TrustZone state MAC writes and locking PMC scratch *before* turning on the BPMP, fixing the original Jamais Vu exploit entirely. In addition, the BPMP firmware in TrustZone's .rodata is now memcmp'd to the actual data after it is written to IRAM. This mitigates race attacks that modify the firmware.
 +
 +
However, Nintendo both forgot to validate the BPMP exception vectors after writing them, and forgot to hold in reset a DMA controller that can write to the BPMP's exception vectors.
 +
 +
AHB-DMA is not blacklisted by kernel mapping whitelist (Nintendo probably forgot it, because the TX1 TRM does not really document that it's present, although the MMIO works as documented in older (Tegra 3 and before) TRMs).
 +
 +
Thus, with kernel code execution (or some other way of accessing AHB-DMA, e.g. nspwn on <= 4.1.0, TSEC hax, or other arbitrary mmio access flaws), one can DMA to the BPMP's exception vectors as they are written, causing TrustZone to start the BPMP executing an attacker's firmware at a different location than TrustZone intends/validates.
 +
 +
This was fixed in [[8.0.0]] by blocking AHB-DMA arbitration and verifying it is held in reset during suspend, and thus there are no more devices that can write to the relevant MMIO at the right time.
 +
 +
|  Arbitrary TrustZone/BootROM code execution, by using either the original Jamais Vu flaw (prior to [[6.0.0]] or a warmboot bootrom exploit (any firmware where pre-sleep execution can be gained).
 +
|  [[8.0.0]]
 +
|  [[8.0.0]]
 +
|  December 2017
 +
|  April 15, 2019
 +
|  [[User:SciresM|SciresM]], [[User:motezazer|motezazer]] and ktemkin,  [[User:Naehrwert|naehrwert]] (independently), almost certainly others (independently)
 +
|-
 +
| TrustZone allows using imported RSA exponents with arbitrary modulus
 +
| TrustZone supports "importing" RSA private exponents for use by userland -- these are stored encrypted with TrustZone only keydata in NAND, and decrypted only to TZRAM. This prevents a console that has compromised userland from learning the private exponents of these keys and doing calculations with them offline. In practice, this is used for FS (gamecard communications), ES (drm), and SSL (console client cert communications).
 +
 +
However, the actual SMC API only imports the RSA exponent, and not the modulus, which is passed separately by userland in each call. There is no validation done on the modulus passed in -- this means that userland can pass in any message and modulus it chooses, and obtain the result of (message ^ private exponent) % modulus back from the secure monitor.
 +
 +
By choosing a prime number modulus P such that P has "smooth" order (totient(P) == P-1 is divisible only by "small" primes), one can efficiently use the [[wikipedia:Pohlig-Hellman algorithm|Pohlig-Hellman algorithm]] to calculate the discrete logarithm of such a result directly, and thus obtain the private exponent.
 +
 +
This is mostly useless in practice, given the general availability of other exploits to obtain these decrypted exponents.
 +
| With userland privileges sufficient to use an imported RSA key: obtaining that RSA key's private exponent.
 +
|  N/A
 +
|  [[8.1.0]]
 +
|  August 14, 2019
 +
|  August 14, 2019
 +
|  [[User:SciresM|SciresM]]
 
|}
 
|}
   Line 386: Line 433:  
| September 19, 2018
 
| September 19, 2018
 
| SciresM
 
| SciresM
 +
|-
 +
| System modules vulnerable to selective downgrade attacks
 +
| Horizon has no mechanism for specifying the specific title version to Loader on process creation.
 +
 +
Observing this, one can note that after a system update one could install a downgraded version of a specific system module (e.g. nvservices) while leaving the rest of the OS at the same version.
 +
 +
Unless there was some breaking API change, this allows one to make a console vulnerable once more to an exploit in a sysmodule by downgrading it and nothing else.
 +
 +
This was fixed in [[8.1.0]] by incrementing a version field in NPDM, and checking it against a hardcoded list for certain titles in Loader's process creation func.
 +
| With access to content installation commands (or a vulnerable lower version to selectively install newer titles), reintroducing bugs in vulnerable system modules on newer firmware versions.
 +
| [[8.1.0]]
 +
| [[8.1.0]]
 +
| When FIRM was first dumped in 2017.
 +
| June 17, 2019
 +
| Everyone
 
|-
 
|-
 
|}
 
|}
Line 402: Line 464:  
!  Public disclosure timeframe
 
!  Public disclosure timeframe
 
!  Discovered by
 
!  Discovered by
 +
|-
 +
| [[Applet_Manager_services#IStorage|AM IStorage]] infoleak
 +
| Originally the buffer allocated by [[Applet_Manager_services#CreateStorage|CreateStorage]] using the specified input size was not cleared. With [8.0.0+] this was fixed by adding a memset() for the buffer after successful allocation.
 +
 +
Hence, IStorage->IStorageAccessor->Read will return uninitialized memory when the Write cmd was not previously used with the specified region.
 +
| Infoleak from the main [[Applet_Manager_services#IStorage|AM]] heap, allowing defeating ASLR by reading addresses from previously allocated objects.
 +
| [[8.0.0]]
 +
| [[8.1.0]]
 +
| December 2018
 +
| August 9, 2019
 +
| [[User:Yellows8|yellows8]]
 
|-
 
|-
 
| Out-of-bounds array read for [[BCAT_Content_Container]] secret-data index
 
| Out-of-bounds array read for [[BCAT_Content_Container]] secret-data index

Navigation menu