obgm / libcoap

A CoAP (RFC 7252) implementation in C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

#1128 The server has debug logging enabled