Security/Bug: Null Pointer Dereference in cJSONUtils_strdup leads to Denial of Service (DoS)
メンテナーはふだん 12 日以内に返信
評価
調査の方向性
cJSON_Utils.c の cJSONUtils_strdup と、ASan トレースに示された apply_patch パスから始めます。その NULL の処理を cJSON.c の cJSON_strdup と比較します。提供された不正なパッチの PoC を AddressSanitizer でコンパイルして実行します。NULL 入力がデリファレンスされなくなり、apply_patch や detach_path などの呼び出し元が NULL の結果を安全に処理できれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Issue Description:
A Null Pointer Dereference vulnerability exists in cJSON_Utils.c. The internal helper function cJSONUtils_strdup does not validate if the incoming pointer is NULL before passing it to strlen(). When processing a malformed JSON patch where critical string fields (like path) have a NULL value string, the application triggers a segmentation fault (Null Pointer Dereference), resulting in a Denial of Service (DoS).
Vulnerability Analysis:
The issue lies in cJSON_Utils.c:
static unsigned char* cJSONUtils_strdup(const unsigned char* const string)
{
size_t length = 0;
unsigned char *copy = NULL;
// Vulnerability: No check for string == NULL before calling strlen()
length = strlen((const char*)string) + sizeof("");
...
}
Root Cause:
Unlike cJSON_strdup in cJSON.c which checks if string is NULL, cJSONUtils_strdup completely lacks this safety guard.
When calling functions like cJSONUtils_ApplyPatches, if an attacker crafts a malicious patch object where the path or value item's valuestring is programmatically NULL or missing under certain edge cases, apply_patch() will eventually propagate this NULL pointer to cJSONUtils_strdup(). This results in strlen(NULL), leading to an immediate crash.
Steps to Reproduce
Proof of Concept (PoC)
Compile the following code with AddressSanitizer enabled (-fsanitize=address):
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#include "cJSON_Utils.h"
int main(void)
{
printf("[PoC 1] cJSONUtils_strdup NULL dereference\n");
printf("[*] Constructing malformed patch with path->valuestring = NULL\n");
/* Create target object: { "k": 1 } */
cJSON *obj = cJSON_CreateObject();
cJSON_AddNumberToObject(obj, "k", 1);
/* Construct patch: { "op": "remove", "path": "/k" } */
cJSON *patch = cJSON_CreateObject();
cJSON *op = cJSON_CreateString("remove");
cJSON *path = cJSON_CreateString("/k");
/* Critical: Force path->valuestring to be NULL to simulate a malformed/corrupted item */
path->valuestring = NULL;
cJSON_AddItemToObject(patch, "op", op);
cJSON_AddItemToObject(patch, "path", path);
cJSON *patches = cJSON_CreateArray();
cJSON_AddItemToArray(patches, patch);
printf("[*] Calling cJSONUtils_ApplyPatches()...\n");
/* Triggering vulnerability */
cJSONUtils_ApplyPatches(obj, patches);
cJSON_Delete(obj);
cJSON_Delete(patches);
return 0;
}
ASan Crash Log
==189825==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55ff3336e33a bp 0x7ffd5b0f7c30 sp 0x7ffd5b0f7b70 T0)
==189825==The signal is caused by a READ memory access.
==189825==Hint: address points to the zero page.
#0 0x55ff3336e33a in apply_patch /home/kali/Desktop/cjsson/cJSON_Utils.c:839
#1 0x55ff3336ebd4 in cJSONUtils_ApplyPatches /home/kali/Desktop/cjsson/cJSON_Utils.c:1056
#2 0x55ff333700f1 in main /home/kali/Desktop/cjsson/poc_1_strdup_null.c:60
Suggested Fix:
Align the behavior of cJSONUtils_strdup with cJSON_strdup by adding a NULL pointer check at the beginning of the function:
static unsigned char* cJSONUtils_strdup(const unsigned char* const string)
{
size_t length = 0;
unsigned char *copy = NULL;
if (string == NULL)
{
return NULL;
}
length = strlen((const char*)string) + sizeof("");
...
Additionally, upstream callers (like apply_patch or detach_path) should properly handle cases where cJSONUtils_strdup returns NULL.
- 主要言語
- C
- スター
- 13k
- フォーク
- 3.5k
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
DaveGamble/cJSON のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
DaveGamble/cJSON#1106 ·
メンテナーはふだん 12 日以内に返信
-
Undefined-Behavior in function cJSON_SetNumberHelper対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
DaveGamble/cJSON#1100 · リアクション 1 件 ·
メンテナーはふだん 12 日以内に返信
-
CMake config files contain absolute install paths対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
DaveGamble/cJSON#1094 · コメント 9 件 · リアクション 1 件 ·
メンテナーはふだん 12 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
DaveGamble/cJSON#1093 ·
メンテナーはふだん 12 日以内に返信
-
Use-after-free in cJSONUtils_ApplyPatches when a patch removes the patch array対応中かも @iliasabk が 36 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
DaveGamble/cJSON#1082 ·
メンテナーはふだん 12 日以内に返信
DaveGamble/cJSON の issue をすべて見る
似ている issue
-
priority:medium type:chore
難易度 1/5 1〜3時間 初心者へのやさしさ 84/100
crazy-goat/php-fpm-ng#1041 ·
メンテナーはふだん 1 日以内に返信
-
Test failure on FreeBSD: #26 unexpected system_clock source対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンlow priority rt_lib tests
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100