mirror of
https://github.com/google/pebble.git
synced 2025-03-19 02:21:21 +00:00
92 lines
4 KiB
Markdown
92 lines
4 KiB
Markdown
# Nanopb: Security model
|
|
|
|
Importance of security in a Protocol Buffers library
|
|
----------------------------------------------------
|
|
|
|
In the context of protocol buffers, security comes into play when
|
|
decoding untrusted data. Naturally, if the attacker can modify the
|
|
contents of a protocol buffers message, he can feed the application any
|
|
values possible. Therefore the application itself must be prepared to
|
|
receive untrusted values.
|
|
|
|
Where nanopb plays a part is preventing the attacker from running
|
|
arbitrary code on the target system. Mostly this means that there must
|
|
not be any possibility to cause buffer overruns, memory corruption or
|
|
invalid pointers by the means of crafting a malicious message.
|
|
|
|
Division of trusted and untrusted data
|
|
--------------------------------------
|
|
|
|
The following data is regarded as **trusted**. It must be under the
|
|
control of the application writer. Malicious data in these structures
|
|
could cause security issues, such as execution of arbitrary code:
|
|
|
|
1. Callback, pointer and extension fields in message structures given
|
|
to pb_encode() and pb_decode(). These fields are memory pointers,
|
|
and are generated depending on the message definition in the .proto
|
|
file.
|
|
2. The automatically generated field definitions, i.e.
|
|
`pb_msgdesc_t`.
|
|
3. Contents of the `pb_istream_t` and `pb_ostream_t` structures
|
|
(this does not mean the contents of the stream itself, just the
|
|
stream definition).
|
|
|
|
The following data is regarded as **untrusted**. Invalid/malicious data
|
|
in these will cause "garbage in, garbage out" behaviour. It will not
|
|
cause buffer overflows, information disclosure or other security
|
|
problems:
|
|
|
|
1. All data read from `pb_istream_t`.
|
|
2. All fields in message structures, except:
|
|
- callbacks (`pb_callback_t` structures)
|
|
- pointer fields and `_count` fields for pointers
|
|
- extensions (`pb_extension_t` structures)
|
|
|
|
Invariants
|
|
----------
|
|
|
|
The following invariants are maintained during operation, even if the
|
|
untrusted data has been maliciously crafted:
|
|
|
|
1. Nanopb will never read more than `bytes_left` bytes from
|
|
`pb_istream_t`.
|
|
2. Nanopb will never write more than `max_size` bytes to
|
|
`pb_ostream_t`.
|
|
3. Nanopb will never access memory out of bounds of the message
|
|
structure.
|
|
4. After `pb_decode()` returns successfully, the message structure will
|
|
be internally consistent:
|
|
- The `count` fields of arrays will not exceed the array size.
|
|
- The `size` field of bytes will not exceed the allocated size.
|
|
- All string fields will have null terminator.
|
|
- bool fields will have valid true/false values (since
|
|
nanopb-0.3.9.4)
|
|
- pointer fields will be either `NULL` or point to valid data
|
|
5. After `pb_encode()` returns successfully, the resulting message is a
|
|
valid protocol buffers message. (Except if user-defined callbacks
|
|
write incorrect data.)
|
|
6. All memory allocated by `pb_decode()` will be released by a subsequent
|
|
call to `pb_release()` on the same message.
|
|
|
|
Further considerations
|
|
----------------------
|
|
|
|
Even if the nanopb library is free of any security issues, there are
|
|
still several possible attack vectors that the application author must
|
|
consider. The following list is not comprehensive:
|
|
|
|
1. Stack usage may depend on the contents of the message. The message
|
|
definition places an upper bound on how much stack will be used.
|
|
Tests should be run with all fields present, to record the maximum
|
|
possible stack usage.
|
|
2. Callbacks can do anything. The code for the callbacks must be
|
|
carefully checked if they are used with untrusted data.
|
|
3. If using stream input, a maximum size should be set in
|
|
`pb_istream_t` to stop a denial of service attack from using an
|
|
infinite message.
|
|
4. If using network sockets as streams, a timeout should be set to stop
|
|
denial of service attacks.
|
|
5. If using `malloc()` support, some method of limiting memory use
|
|
should be employed. This can be done by defining custom
|
|
`pb_realloc()` function. Nanopb will properly detect and handle
|
|
failed memory allocations.
|