From claude.zou.work at gmail.com Tue Jun 9 00:33:23 2020 From: claude.zou.work at gmail.com (Claude Zou) Date: Mon, 8 Jun 2020 10:33:23 -0400 Subject: [c-lightning] Security issue in c-lightning Message-ID: Hi, I found a bug in c-lightning which allows a local user to leak near-arbitrary memory through the JSON RPC, which, in the case that the socket is configured to be globally accessible, could allow an attacker to leak sensitive information. The bug lies in the iterator for JSON objects . The code assumes that every key in the json has a corresponding value (that is, every key has a size field >= 1). Now, for valid JSONs, this is clearly true. However, the JSON library used in c-lightning, jsmn, doesn't seem to enforce this, even in strict mode. For example, if jsmn is passed the string '{""""}', it will return a jsmn_tok list that essentially says the JSON has two keys, "" and "", each of size 0 (and thus no corresponding value). While it could be argued that the bug lies with jsmn, similar parsing issues have been mentioned before on their repo but have yet to be fixed despite a rather long time since discovery. Then, when json_for_each_obj is passed the jsmn_tok array, it sees that the JSON object has size 2 (as it has 2 keys), so it iterates over it twice. But in the first iteration, it will already pass over the two valid jsmn_tok values because the size of the key is assumed to be greater than 0. As a result, the next iteration will be out of bounds. An attacker can manipulate the heap using previous JSON commands to forge jsmn_tok structs. By controlling the start and end values of the token, the attacker can leak arbitrary data relative to the buffer storing the JSON string through error messages . To replicate this bug, one simply has to pass a JSON such as '{""""}' to the JSON RPC of c-lightning. During my testing, the heap layout was rather inconsistent, so it's probably more reliable to send a JSON with more double quotes such as '{""""""""""""""""""""}' to get a proper segfault (if that doesn't work, keep adding an even number of double quotes). To fix this, a simple check in the iterator to make sure the size of a jsmn_tok is greater than 0 is likely sufficient to prevent any memory corruption. I hope this was helpful and that the issue gets resolved soon! Sincerely, Claude Zou -------------- next part -------------- An HTML attachment was scrubbed... URL: From ZmnSCPxj at protonmail.com Tue Jun 9 02:09:32 2020 From: ZmnSCPxj at protonmail.com (ZmnSCPxj) Date: Mon, 08 Jun 2020 16:09:32 +0000 Subject: [c-lightning] Security issue in c-lightning In-Reply-To: References: Message-ID: Good morning Claude, Thank you for the bug report. I will check for now. Regards, ZmnSCPxj > Hi, > > I found a bug in c-lightning which allows a local user to leak near-arbitrary memory through the JSON RPC, which, in the case that the socket is configured to be globally accessible, could allow an attacker to leak sensitive information. > > The bug lies in the iterator for JSON objects. The code assumes that every key in the json has a corresponding value (that is, every key has a size field >= 1). Now, for valid JSONs, this is clearly true. However, the JSON library used in c-lightning, jsmn, doesn't seem to enforce this, even in strict mode. For example, if jsmn is passed the string '{""""}', it will return a jsmn_tok list that essentially says the JSON has two keys, "" and "", each of size 0 (and thus no corresponding value). While it could be argued that the bug lies with jsmn, similar parsing issues have been mentioned before on their repo but have yet to be fixed despite a rather long time since discovery. > > Then, when json_for_each_obj is passed the jsmn_tok array, it sees that the JSON object has size 2 (as it has 2 keys), so it iterates over it twice. But in the first iteration, it will already pass over the two valid jsmn_tok values because the size of the key is assumed to be greater than 0. As a result, the next iteration will be out of bounds. > > An attacker can manipulate the heap using previous JSON commands to forge jsmn_tok structs. By controlling the start and end values of the token, the attacker can leak arbitrary data relative to the buffer storing the JSON string through error messages. > > To replicate this bug, one simply has to pass a JSON such as '{""""}' to the JSON RPC of c-lightning. During my testing, the heap layout was rather inconsistent, so it's probably more reliable to send a JSON with more double quotes such as '{""""""""""""""""""""}' to get a proper segfault (if that doesn't work, keep adding an even number of double quotes). > > To fix this, a simple check in the iterator to make sure the size of a jsmn_tok is greater than 0 is likely sufficient to prevent any memory corruption. > > I hope this was helpful and that the issue gets resolved soon! > > Sincerely, > Claude Zou From ZmnSCPxj at protonmail.com Tue Jun 9 02:25:37 2020 From: ZmnSCPxj at protonmail.com (ZmnSCPxj) Date: Mon, 08 Jun 2020 16:25:37 +0000 Subject: [c-lightning] Security issue in c-lightning In-Reply-To: References: Message-ID: I attached a simple program to help investigate this issue. Compile with jsmn.c, then use: $ ./a.out '{""""}' Here are some sample outputs: $ ./a.out '{"xxx": 2. ""}' [0] type = JSMN_OBJECT start = 0 end = 17 size = 1 [1] type = JSMN_STRING start = 2 end = 5 size = 2 [2] type = JSMN_PRIMITIVE start = 8 end = 10 size = 0 [3] type = JSMN_STRING start = 15 end = 15 size = 0 $ ./a.out '{"xxx": 2,""}' [0] type = JSMN_OBJECT start = 0 end = 13 size = 2 [1] type = JSMN_STRING start = 2 end = 5 size = 1 [2] type = JSMN_PRIMITIVE start = 8 end = 9 size = 0 [3] type = JSMN_STRING start = 11 end = 11 size = 0 $ ./a.out '{"x""y""z"}' [0] type = JSMN_OBJECT start = 0 end = 11 size = 3 [1] type = JSMN_STRING start = 2 end = 3 size = 0 [2] type = JSMN_STRING start = 5 end = 6 size = 0 [3] type = JSMN_STRING start = 8 end = 9 size = 0 I am now horribly confused what "size" is supposed to mean in jsmn at this point. jsmn also has relatively minimal documentation about what "size" is.... Can we assume that every valid key in a valid object is a string key and has a "size" of 1? I would suggest using some kind of filter wrapper around `json_parse_input` to protect against such strange behavior from jsmn. There are only two callers to `jsmn_parse` in our production non-test code. One is the `json_parse_input` wrapper. The other is inside `lightning-cli`; due to its expected use, we do not expect such issues to arise with `lightning-cli` (though it might do best for `lightning-cli` to switch to using `json_parse_input`, this is lower priority). Regards, ZmnSCPxj -------------- next part -------------- A non-text attachment was scrubbed... Name: main.c Type: text/x-csrc Size: 1233 bytes Desc: not available URL: From ZmnSCPxj at protonmail.com Tue Jun 9 03:04:26 2020 From: ZmnSCPxj at protonmail.com (ZmnSCPxj) Date: Mon, 08 Jun 2020 17:04:26 +0000 Subject: [c-lightning] Security issue in c-lightning In-Reply-To: References: Message-ID: <29BrVzwc5cc3r0Xq8Bu22JaGmVCp426ubIpPx4fAyK_-Xh9nMsXuEkVRpAUTfGLB5-aYKOclgT9bBJqnkQvsyJ8WBE_jkzVgk3gEf0xSOoo=@protonmail.com> Good morning list, I created a function that could potentially be used to check if the result of `jsmn_parse` is valid, specifically that objects always have string keys and the keys have a size of exactly 1. I added it to the previous program so we can get some hands-on trial on whether the function gets any false-positives / false-negatives. The new function is `validate_jsmn_result`, and it requires a support function `find_jsmn_bounds`. Please see attached code. It is probably a good idea to feed the program into some kind of fuzzer at this point. The intent is that instead of `*valid = true` in `json_parse_input`, we should use `*valid = validate_jsmn_result(toks, toks + ret);` I will enter into cyclic reduced-power state soon, sorry. Regards, ZmnSCPxj -------------- next part -------------- A non-text attachment was scrubbed... Name: main.c Type: text/x-csrc Size: 2980 bytes Desc: not available URL: