-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
JSON module: reading arbitrary process memory #65728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
(Copy paste from the security list) Python 2 and 3 are susceptible to arbitrary process memory reading by The sole prerequisites of this attack are that the attacker is able to The bug is caused by allowing the user to supply a negative index Let me clarify: This is Python-3.4.0/Modules/_json.c: 1035 static PyObject * As you can see on line 1047, ParseTuple takes an 'n' as an argument
This means it accepts a SIGNED integer value, thus allowing a negative Then onto scanstring_unicode_once to which execution gets transferred 922 static PyObject * Here we see that 'length' is set to the length of the string 949 switch (PyUnicode_READ(kind, str, idx)) { PyUnicode_READ is defined as follows ( in 516 /* Read a code point from the string's canonical representation. No checks Here we can see that index, which is negative in our example, is used So, if a certain negative value (such as -0x7FFFFFFF) is supplied and But there's more. Instead of making it point to an invalid page, let's 1 from json import JSONDecoder Output of this script is: Difference is -0x30 The difference between the address of 'a' and the address of 'b' is We can use this harvester to scan memory for valid JSON strings: 1 from json import JSONDecoder There is one drawback, however. We cannot decode strings in this manner because: 296 static PyObject *
297 scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict,
Py_ssize_t *next_end_ptr)
298 {
299 /* Read the JSON string from PyUnicode pystr.
300 end is the index of the first character after the quote.
301 if strict is zero then literal control characters are allowed
302 *next_end_ptr is a return-by-reference index of the character
303 after the end quote
304
305 Return value is a new PyUnicode
306 */
307 PyObject *rval = NULL;
308 Py_ssize_t len;
309 Py_ssize_t begin = end - 1;
310 Py_ssize_t next /* = begin */;
311 const void *buf;
312 int kind;
313 PyObject *chunks = NULL;
314 PyObject *chunk = NULL;
315
316 if (PyUnicode_READY(pystr) == -1)
317 return 0;
318
319 len = PyUnicode_GET_LENGTH(pystr);
320 buf = PyUnicode_DATA(pystr);
321 kind = PyUnicode_KIND(pystr);
322
323 if (end < 0 || len < end) {
324 PyErr_SetString(PyExc_ValueError, "end is out of bounds");
325 goto bail; this code actually performs a bounds check by asserting that end However, I succesfully ran harvesting tests that could extract Given the ubiquity of JSON parsing in Python applications and the Here is a patch for 3.4.0: --- _json_old.c 2014-04-12 17:47:08.749012372 +0200 - if (idx >= length) {
+ if ( idx < 0 || idx >= length) {
raise_stop_iteration(idx);
return NULL;
} And here is a patch for 2.7.6: --- _json_old.c 2014-04-12 17:57:14.365015601 +0200
+++ _json.c 2014-04-12 18:04:25.149017898 +0200
@@ -1491,7 +1491,7 @@
PyObject *res;
char *str = PyString_AS_STRING(pystr);
Py_ssize_t length = PyString_GET_SIZE(pystr);
- if (idx >= length) {
+ if ( idx < 0 || idx >= length) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
@@ -1578,7 +1578,7 @@
PyObject *res;
Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
- if (idx >= length) {
+ if ( idx < 0 || idx >= length) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
} Here is a script that checks whether the Python binary that executes 1 from json import JSONDecoder Please let me know what your thoughts on this are and when you think Note: I haven't shared this vulnerability with anyone and I won't do Guido Vranken |
Fixed also in 3.2 (b9913eb96643), 3.3 (4f15bd1ab28f), 3.4 (7b95540ced5c) and 3.5 (3a414c709f1f). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: