应用侧漏洞与CTF题解:https://wnagzihxa1n.gitbook.io

大土豆安全笔记 | 求求你慢点泄露,我学不过来了

最近看了HITCON 2014一个议题

分享其中一页,五年前看是一种心态,现在看又是另一番滋味,或许再过五年,一切又都变了,大家现在应该更推崇知识付费吧

IMAGE

这两周接二连三的出现大厂数据泄露,前脚英伟达,后脚三星就跟上了,泄露的内容大家可以自行阅读下面这张截图

IMAGE

请有缘人自取

希望今年Pwn2Own能带出很多好的漏洞与攻击手法

IMAGE

我这几天主要是在看iMessage那个Zero-Click的漏洞,PJ0也发布了一篇博客《A deep dive into an NSO zero-click iMessage exploit: Remote Code Execution》

简单讲讲漏洞细节,先描述下JBIG2的原理,对于黑白图像的文本来说,扫描完之后相同的符号对应的图像大体上都差不多,但是落实在数据上尤其是像素级别就会有差异,JBIG2会维护一个位图表,将扫描到的符号对应到位图表里的位图,如果存在对应的位图,就记录位图表偏移,如果不存在则添加这个符号对应的位图,再记录偏移,最后再对位图表进行压缩,如此一来即可实现对扫描数据的压缩效果

如图所示,一共有六个符号e出现,但是每个符号细节上的像素都有所差异,如果全都存储一遍很占空间

IMAGE

如果我们将其全部使用第一个符号e来替代,并且记录下每个符号e所在坐标,就可以只存储一次符号e所对应的位图,极大实现压缩效果

IMAGE

然后是Segment,如果要仔细分析的话是一定要理解JBIG2Stream里的Segment含义,一段JBIG2Stream由非常多的Segment组成,每个Segment表现为一段二进制数据,其实对应出来就是一个渲染指令,还有位图表,通过Segment类型字段分发到不同的分支里去对页面做处理

当进行文本区域解码的时候,会先处理引用的位图Segment,将所有引用到的位图数据全部导入,然后再去解码,在计算位图数量的时候,存在整数溢出漏洞,导致申请的堆空间偏小,后续循环写入位图数据时导致堆溢出

void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
                                    GBool lossless, Guint length,
                                    Guint *refSegs, Guint nRefSegs)
{
    ...

    // get symbol dictionaries and tables
    codeTables = new GList();
    numSyms = 0;  // 位图计数器
    for (i = 0; i < nRefSegs; ++i)  // 引用的Segment数量
    {
        if ((seg = findSegment(refSegs[i])))  // 通过Segment序号找到对应的对象
        {
            if (seg->getType() == jbig2SegSymbolDict)  // 类型为位图表的Segment
            {
                numSyms += ((JBIG2SymbolDict *)seg)->getSize();  // 将当前Segment的位图数量叠加到位图计数器 <-- 此处发生整数溢出
            }
            else if (seg->getType() == jbig2SegCodeTable)
            {
                codeTables->append(seg);
            }
        }
        else
        {
            error(errSyntaxError, getPos(),
                  "Invalid segment reference in JBIG2 text region");
            delete codeTables;
            return;
        }
    }
    
    ...

    // get the symbol bitmaps
    syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));  // 在整数溢出的情况下,位图计数器numSyms会变成一个较小的值,申请下来的堆空间也相对较小
    kk = 0;
    for (i = 0; i < nRefSegs; ++i)  // 遍历引用的Segment
    {
        if ((seg = findSegment(refSegs[i])))  // 通过Segment序号获取到对应的对象
        {
            if (seg->getType() == jbig2SegSymbolDict)  // 类型为位图表的Segment
            {
                symbolDict = (JBIG2SymbolDict *)seg;  // 转换类型为位图表
                for (k = 0; k < symbolDict->getSize(); ++k)
                {
                    syms[kk++] = symbolDict->getBitmap(k);  // 将位图指针写入申请的堆空间 <-- 此处发生堆溢出
                }
            }
        }
    }

    ...
}

利用过程我这里不描述了,有兴趣可以等待PJ0的第二篇文章,非常天才的利用

Saelo前段时间在今年的BlueHat上也讲了一个相关的议题,不过和文章的内容差不多,没有新增太多跟漏洞利用相关的内容

这个漏洞要理解整个流程其实还是有点难度的,首先要清楚PDF的格式,如何将JBIG2Stream嵌入到PDF里,然后是Segment的格式,不然解析过程那些字段位移取值判断操作很难明白是在做什么

推荐看看JBIG2的文档,顺带看下后面的样例讲解,理解了之后再去看源码就清楚多了

同时今年BlueHat还有一个议题,DAY ONE晚上九点二十五到十点零五那个,不知道什么时候会有Slides放出来,我倒是很期待学习下,不敢贴细节,放个带锚点的导航

这两天有一个玄武的瓜,想不到在我划水咸鱼的日子里,别人家的世界这么精彩

每年安全圈都有那么几个瓜让人热闹一下,前年有,去年有,今年也有,在圈子里混了这么多年,通常有瓜的时候,两头我都认识,也知道背后的真实情况(这次我两头都不熟),所以站在这样的角度去看大家的反应,还挺有趣的,有的人啥都不知道就口无遮拦评价别人的样子还真是让人讨厌

也给各位提了个醒,如果你离职的时候老板让你上交你这些年的研究成果与技术文档,或者是你写的Fuzzer,漏洞扫描器,甚至是0day,你是交呢?还是不交呢?

最后说点题外话

北方的战斗民族公开了一份文档,各位如有兴趣可翻阅

我直接贴一张大家最关心的,右下角那位Doctor,不知道现在是不是正在被查水表

Оригинал.png

附上这位Doctor的个人介绍,还真是专业对口

IMAGE