xxxxxxxxxx
Sign in to import from GitHub:
Link to GitHub:
Or start with a template:
This document describes how a malicious entity may exploit a naive SSZ implementation to create multiple, distinct SSZ representations of the same object.
Note: this document is not comprehensive or guaranteed to be error-free. It should be considered a collection of informal notes.
Note: these potential attacks are not unavoidable flaws in SSZ; they will only be present in an imperfect implementation.
These potential exploits are only related to malicious offsets; data validation attacks are ignored (e.g., ensuring that exactly 8 bytes are provided to decode a uint64
).
First, some helper functions are described, then each exploit is listed along with some Python-esque psuedo-code providing potential safeguards.
We define helper functions where enc
is of type bytes
and is the SSZ encoding of some container, list or vector. These functions are assumed to operate in a magic context where they may access all information required to decode the object (e.g., the schema).
With each function we provide an example which references the following
struct (defined in Rust, sorry. It should be straight forward to understand – Vec
is a variable length list):
struct Example {
a: u16,
b: Vec<u8>
c: Vec<u8>,
}
let example_a = Example {
a: 42,
b: vec![5, 6],
c: vec![7, 8],
};
// schema: | a | b (offset) | c (offset) | b | c |
let enc = vec![42, 00, 10, 00, 00, 00, 12, 00, 00, 00, 05, 06, 07, 08];
// indices: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
assert_eq!(
ssz_encode(example_a),
enc
);
num_fixed_bytes(bytes)
Returns the length of the fixed-length portion of enc
.
Example:
num_fixed_bytes(ssz_encode(example_a)) == 10
offsets(bytes)
Returns a list containing any offsets in bytes
, each decoded as an int
.
Example:
offsets(ssz_encode(example_a)) == [10, 12]
An offset points “backwards” into the fixed-bytes portion of the message, essentially double-decoding bytes that will also be decoded as fixed-length.
Potential safeguard:
for offset in offsets(enc):
assert offset >= num_fixed_bytes(enc)
The first offset does not point to the byte that follows the fixed byte portion, essentially skipping a variable-length byte.
Potential safeguard:
offsets = offsets(enc)
if len(offsets) > 0:
assert offsets[0] == num_fixed_bytes(enc)
An offset points to bytes prior to the previous offset. Depending on how you look at it, this either double-decodes bytes or makes the first offset a negative-length.
offsets = offsets(enc)
for i in range(1, len(offsets)):
assert offsets[i] >= offsets[i - 1]
An offset references byte indices that do not exist in enc
.
for offset in offsets(enc):
assert offset <= len(enc)
Note: use <=
since a [[]]
is represented as [4, 0, 0, 0]
.
or
Do you really want to delete this template?
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Please sign in to GitHub and install the HackMD app on your GitHub repo. Learn more
Sign in to GitHubHackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
Syncing