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.
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:
pb_msgdesc_t
.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:
pb_istream_t
.pb_callback_t
structures)_count
fields for pointerspb_extension_t
structures)The following invariants are maintained during operation, even if the untrusted data has been maliciously crafted:
bytes_left
bytes from
pb_istream_t
.max_size
bytes to
pb_ostream_t
.pb_decode()
returns successfully, the message
structure will be internally consistent:
count
fields of arrays will not exceed the array
size.size
field of bytes will not exceed the allocated
size.NULL
or point to valid
datapb_encode()
returns successfully, the resulting
message is a valid protocol buffers message. (Except if user-defined
callbacks write incorrect data.)pb_decode()
will be released by
a subsequent call to pb_release()
on the same message.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:
pb_istream_t
to stop a denial of service attack from using
an infinite message.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.