Pdfium – Out-of-Bounds Read with Shading Pattern Backed by Pattern Colorspace

  • 作者: Google Security Research
    日期: 2018-02-15
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44083/
  • Related toissue 1490 .
    
    When parsing ShadingPatterns; according to the specification they shouldn't be permitted to have a pattern colorspace as their base colorspace, but this is not validated, leading to out-of-bounds reads when rendering using the malformed shading pattern.
    
    bool CPDF_ShadingPattern::Load() {
    
    // ... snip ...
    
    CPDF_Object* pCSObj = pShadingDict->GetDirectObjectFor("ColorSpace");
    if (!pCSObj)
    return false;
    
    // No validation here on the type of colorspace.
    
    // ... snip ...
    
    return true;
    }
    
    If we now look at the code called during rendering of this pattern, we call through DrawFreeGouraudShading (cpdf_renderstatus.cpp), which will call CPDF_MeshStream::ReadVertex for each vertex in the shading pattern, which will call CPDF_MeshStream::ReadColor.
    
    std::tuple<float, float, float> CPDF_MeshStream::ReadColor() {
    ASSERT(ShouldCheckBPC(m_type));
    
    float color_value[kMaxComponents];
    for (uint32_t i = 0; i < m_nComponents; ++i) {
    color_value[i] = m_ColorMin[i] + m_BitStream->GetBits(m_nComponentBits) *
     (m_ColorMax[i] - m_ColorMin[i]) /
     m_ComponentMax;
    }
    
    // NB: color_value has only been initialised for the first m_nComponents elements
    
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;
    if (m_funcs.empty()) {
    m_pCS->GetRGB(color_value, &r, &g, &b); // <-- we're interested in this call here
    return std::tuple<float, float, float>(r, g, b);
    }
    
    // ... snip ...
    }
    
    This call to GetRGB will be into the pattern cs
    
    bool CPDF_PatternCS::GetRGB(float* pBuf, float* R, float* G, float* B) const {
    if (m_pBaseCS) {
    ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN);
    PatternValue* pvalue = (PatternValue*)pBuf;
    // pvalue->m_Comps is now pointing 5 dwords into an 8 dword sized buffer, and p_pBaseCS expects to be able to read 8 dwords from it. 
    if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B))
    return true;
    }
    *R = 0.75f;
    *G = 0.75f;
    *B = 0.75f;
    return false;
    }
    
    Originally reported without 90 day deadline as https://bugs.chromium.org/p/chromium/issues/detail?id=795251, since it wasn't clear that there was an easy way to use the oob-read to leak information in a way that was useful, deadline applied as of 15/12 after working out how to use this as an information leak forissue 1489 . 
    
    
    Proof of Concept:
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44083.zip