Are there any security measures that must be done for pdu's set or get functions?
MrHulu opened this issue · comments
Hello, I'm here again, I found a small problem, I do not know if it is considered a bug?
Environment
-
libcoap version (run
git describe --tags
to find it): v4.3.1-154-gcca6b5f -
Build System: [Make|CMake]
-
Operating System: [Any]
-
Operating System Version: [ ]
-
Hosted Environment: [None|Contiki|LwIP|ESP-IDF|Other (which?)]
Problem Description
I found in the pdu.c file that the information about getting pdu is not secured, which can lead to a serious exception.
Code to reproduce this issue
In
typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session.
const coap_pdu_t *sent.
const coap_pdu_t *received.
const coap_mid_t mid);
function, if it is a pushback, then sent is actually a NULL, in which case, use coap_pdu_get_mid
or coap_pdu_get_token
or something else? will cause an exception. I browsed the pdu.c
file for the implementation of these functions and found that there is no security for the parameter const coap_pdu_t *pdu
to access directly. This would be a big risk
In the pdu.c
coap_pdu_code_t
coap_pdu_get_code(const coap_pdu_t *pdu) {
return pdu->code;
}
void
coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code) {
assert(code <= 0xff);
pdu->code = code;
}
coap_pdu_type_t coap_pdu_get_type(const coap_pdu_t *pdu) {
return pdu->type;
}
void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type) {
assert(type <= 0x3);
pdu->type = type;
}
coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu) {
return pdu->actual_token;
}
coap_mid_t coap_pdu_get_mid(const coap_pdu_t *pdu) {
return pdu->mid;
}
void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid) {
assert(mid >= 0 && mid <= 0xffff);
pdu->mid = mid;
}
@MrHulu Thanks for raising this. What is considered is a critical bug is when libcoap internally calls a function which causes the application to crash. The challenge we have here is when an application passes in information that is malformed that causes libcoap to crash. In particular, when buffers are passed in that are not properly formed in terms of size and location, they are virtually impossible to detect without running some sort of memory usage checker.
In the case of the pdu
being NULL as you highlighted above, it is easy to add in pdu == NULL
checks and either return a dummy value (which does not necessarily indicate an error) or have assert(pdu != NULL)
which will give an assertion error (no real difference to a crash) as the application code really needs to be handling the pdu == NULL
scenario.
coap_response_handler_t
is only called when libcoap is confident that the received pdu
is a genuine match for a previously sent pdu
. Thus the token
for the received pdu
will be one that matches a previously sent pdu
. According to RFC7252, matching mid
at the application layer is not safe to do and tokens
should be matched. So, if you want to do this matching, then you need to maintain a list of sent
pdu tokens to match against, rather than relying on sent
pdu being set.
Hi, @mrdeep1
I understand that the function is badly handled and can only be used by the caller to determine if the data is NULL.
But my suggestion is to mark it in the comments?
Now I have a new challenge, when I use the libcoap-minimal project, I find that the server can't respond to the client's request. Can you tell me why?
Environment
- libcoap version: v4.3.1-154-gcca6b5f
- Build System: [Make|CMake]
- Operating System: [Window]
Code to reproduce this issue
diff --git a/client.cc b/client.cc
index a37d80f..91d9004 100644
--- a/client.cc
+++ b/client.cc
@@ -22,10 +22,10 @@ main(void) {
coap_startup();
/* Set logging level */
- coap_set_log_level(LOG_WARNING);
+ coap_set_log_level(LOG_DEBUG);
/* resolve destination address where server should be sent */
- if (resolve_address("coap.me", "5683", &dst) < 0) {
+ if (resolve_address("192.168.5.149", "5688", &dst) < 0) {
coap_log(LOG_CRIT, "failed to resolve address\n");
goto finish;
}
diff --git a/server.cc b/server.cc
index 1d02cbe..bf8f235 100644
--- a/server.cc
+++ b/server.cc
@@ -20,7 +20,7 @@ main(void) {
coap_startup();
/* resolve destination address where server should be sent */
- if (resolve_address("localhost", "5683", &dst) < 0) {
+ if (resolve_address("192.168.5.149", "5688", &dst) < 0) {
coap_log(LOG_CRIT, "failed to resolve address\n");
goto finish;
}
Debug Logs
In client.exe
Jun 06 10:59:38.274 DEBG ***192.168.5.149:63076 <-> 192.168.5.149:5688 UDP : session 00EEB2C8: created outgoing session
Jun 06 10:59:38.276 DEBG ***192.168.5.149:63076 <-> 192.168.5.149:5688 UDP : session connected
v:1 t:CON c:GET i:5bfa {} [ Uri-Path:hello ]
Jun 06 10:59:38.277 DEBG * 192.168.5.149:63076 <-> 192.168.5.149:5688 UDP : netif: sent 16 bytes
v:1 t:CON c:GET i:5bfa {} [ Uri-Path:hello, Request-Tag:0xe28057 ]
Jun 06 10:59:38.277 DEBG ** 192.168.5.149:63076 <-> 192.168.5.149:5688 UDP : mid=0x5bfa: added to retransmit queue (2344ms)
In server.exe
v:1 t:CON c:GET i:5bfa {} [ Uri-Path:hello, Request-Tag:0xe28057 ]
v:1 t:ACK c:2.05 i:5bfa {} [ ] :: 'world'
Jun 06 10:59:38.279 CRIT coap_socket_send: An invalid argument was supplied.
Please raise this as a separate issue, as well as provide the libcoap-minimal git version and enable debug logging on the server.