【问题标题】:Prevent integer underflow/overflow when receiving integer over TCP通过 TCP 接收整数时防止整数下溢/溢出
【发布时间】:2021-10-01 16:16:19
【问题描述】:

例如,我有一个 TCP 服务器需要在接收所述数据之前知道一些任意数据的无符号整数 (uint32_t) 大小。为了接收任意数据,客户端首先必须发送使用htonl 编码的uint32_t 无符号整数的大小字节,例如(客户端):

uint32_t size_int = // some size integer calculated before
uint32_t nbo_data = htonl(size_int);
// send nbo_data to server...

为了解码字节,服务器将执行以下操作:

// First receive nbo_bytes into receive_buffer...
uint32_t nbo_data;
memcpy(&nbo_data, receive_buffer, sizeof(uint32_t));


uint32_t size_int = ntohl(nbo_data);

现在假设攻击者发送了超过UINT32_MAX值/4294967295的htonl编码的uint32_t字节。如何防止发生整数上溢/下溢?将简单转换为更大的数据类型,即long long 和边界检查就足够了吗?像这样:

char receive_buffer[1024];
// First receive nbo_bytes into receive_buffer...
uint32_t nbo_data;
memcpy(&nbo_data, receive_buffer, sizeof(uint32_t));


long long size_int = (long long)ntohl(nbo_data);
// Check if size_int > UINT32_MAX or size_int < 0 here
// If true raise error.

或者有没有更好的方法/这种方法是否有缺陷且无效?

【问题讨论】:

  • 32 位的数量不可能超过 UINT32_MAX。
  • @Mat 所以换句话说,转换为long long 并检查边界/范围是多余的?
  • 不仅冗余,而且容易出错。 (而且一开始就没有意义。)
  • 无符号整数永远不会溢出,它们只是环绕。

标签: c security tcp integer-overflow


【解决方案1】:

现在假设攻击者发送了编码为 uint32_t 的字节 htonl 超过了 UINT32_MAX 值/4294967295。

正如在 cmets 中所表达的那样,这是不可能的。

htonl() 只是将一个四字节序列转换为另一个,使得结果序列是参数值的大端(网络顺序)表示。如果主机本身使用 big-endian 顺序,那么这是无操作的。

uint32_t 表示具有 32 个值位且没有填充位的无符号整数类型。这种值的解释是由语言规范规定的,它没有为不能解释为uint32_t 的 32 位模式留下空间。 UINT32_MAX 的值由此而来。

即使通过恶意旋转位,攻击者也不能发送一个 32 位值,该值不能解释为介于 0 和 UINT32_MAX 之间的 uint32_t(包括 0 和 UINT32_MAX)。接收到的uint32_t 也不会诱导ntohl() 尝试返回超出范围的值,因为同样,对于类型uint32_t,没有超出范围或无效的值是可表达的。

我怎么可能 防止发生整数上溢/下溢?

您无需采取任何措施来避免这种情况。相反,您应该专注于如何检测或处理收到的值完全错误或不一致的可能性。

【讨论】:

    猜你喜欢
    • 2018-02-28
    • 2022-06-22
    • 2022-01-21
    • 2022-01-07
    • 2011-10-22
    • 2014-01-24
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多