前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >CVE-2019-17498:libssh2整形溢出漏洞分析

CVE-2019-17498:libssh2整形溢出漏洞分析

作者头像
FB客服
发布2019-12-26 15:54:53
发布2019-12-26 15:54:53
1.3K00
代码可运行
举报
文章被收录于专栏:FreeBufFreeBuf
运行总次数:0
代码可运行

严重性与缓解方案

该漏洞并不是一个Openssh漏洞,所以它不会影响ssh。Libssh2是一个客户端C代码库,它能够帮助应用程序与SSH服务器建立连接。而且该漏洞也不是一个libssh漏洞,因为libssh并非C代码库,只不过它的功能跟libssh2类似而已。

该漏洞存在于libssh2 v1.9.0及更早版本之中,目前该漏洞已经在libssh2的master分支成功修复,但是官方并没有发布包含漏洞修复方案的正式版。

该漏洞涉及到越界读取的问题,并有可能导致目标服务出现拒绝服务或远程信息披露的风险。当libssh2被用来跟恶意SSH服务器建立连接时,便有可能触发该漏洞。当SSH服务器发送一条断开连接消息时,便会发生溢出。这也就意味着,该漏洞可以在连接过程的开始阶段,及身份认证完成之前被触发。

触发漏洞

该漏洞的原始位置位于packet.c:480处:

代码语言:javascript
代码运行次数:0
复制
if(message_len < datalen-13) {

datalen的值是一个不受信的值,它由远程SSH服务器控制。如果datalen==11,那么减法运算将会发生溢出,针对message_len的越界检测将会失效。Message_len是一个无符号的32位整型,它的值同样由远程SSH服务器控制,所以这将导致第485行代码发生越界读取:

代码语言:javascript
代码运行次数:0
复制
language_len =    _libssh2_ntohu32(data + 9 + message_len);

越界读取通常来说会导致分段错误,但是本文所描述的问题将有可能导致代码调用第499行的LIBSSH2_DISCONNECT:

代码语言:javascript
代码运行次数:0
复制
if(session->ssh_msg_disconnect) {        LIBSSH2_DISCONNECT(session, reason, message,                           message_len, language, language_len);    }

具体情况取决于libssh2库是如何被使用的,因为session->ssh_msg_disconnect是一个回调函数,默认为NULL,但是用户也可以通过调用libssh2_session_callback_set来自行设置。

我在这里专门写了一个漏洞利用PoC:

https://github.com/kevinbackhouse/SecurityExploits/tree/8cbdbbe6363510f7d9ceec685373da12e6fc752d/libssh2/out_of_bounds_read_disconnect_CVE-2019-17498。

它模拟了一个恶意SSH服务器,可以返回包含datalen==11和message_len==0x41414141的断开连接消息,这将导致libssh2出现分段错误并发生崩溃。

Liibssh2整型溢出变种分析

当我在将一个安全漏洞报告给厂商时,我通常会在报告中包含两个内容:

1、漏洞的漏洞利用代码PoC; 2、QL查询,识别所有我认为需要修复的代码位置;

在PoC中包含QL查询,个人认为有以下好处:

1、如果代码包含多个相似的漏洞,那么我们就可以编写一个查询请求来枚举它们。 2、QL查询可以帮助我快速判断漏洞是否成功被修复。 3、QL查询可以将结果以单独URL的形式呈现给我,便于我们进行后续分析。

创建一个PoC通常涉及到大量的工作,如果某个目标存在多个非常相似的漏洞,那我一般会针对其中一个漏洞写一个PoC,因为一个PoC足以证明漏洞的影响了。这个查询的目的并不是找到libssh2中所有的整形溢出漏洞,它的主要目的是找出该PoC触发的漏洞以及其他的相似变种。

Semmle QL查询代码如下:

代码语言:javascript
代码运行次数:0
复制
/**     * @kind path-problem     */    import cpp    import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis    import semmle.code.cpp.dataflow.TaintTracking    import DataFlow::PathGraph    class Config extends DataFlow::Configuration {      Config() { this = "_libssh2_ntohl bounds check overflow" }      override predicate isSource(DataFlow::Node source) {        source.asExpr().(FunctionCall).getTarget().getName().matches("_libssh2_ntoh%")      }      override predicate isSink(DataFlow::Node sink) {        convertedExprMightOverflowNegatively(sink.asExpr()) and        exists(RelationalOperation cmp | cmp.getAnOperand() = sink.asExpr())      }      override predicate isAdditionalFlowStep(DataFlow::Node source,                                              DataFlow::Node target) {        exists(Field f |          source.asExpr() = f.getAnAssignedValue() and          target.asExpr() = f.getAnAccess())        or        target.asExpr().(AddExpr).getAnOperand() = source.asExpr()        or        target.asExpr().(SubExpr).getAnOperand() = source.asExpr()      }    }    from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink    where cfg.hasFlowPath(source, sink)    select sink, source, sink,      "possible integer overflow of tainted expression in bounds check"

其中,isSource表示寻找到了针对_libssh2_ntohu32和 _libssh2_ntohu64的调用,它们主要用来进行网络至主机的字节顺序转义。这些函数一般都可以用来寻找那些“攻击者控制的数据”。但是我这里使用的isSink目的是寻找对比晕眩,其中包含可能发生溢出的子表达式。比如说,message_len < datalen-13是一个比较表达式,而datalen-13则有可能发生溢出。我的查询还会重写isAdditionalFlowStep选项,并自定义数据流边界集。

*参考来源:semmle,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 严重性与缓解方案
  • 触发漏洞
  • Liibssh2整型溢出变种分析
    • 在PoC中包含QL查询,个人认为有以下好处:
  • Semmle QL查询代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档