4.3.4 漏洞修复

官方针对此漏洞的补丁[1]很容易理解,即在API Server中增加了对后端服务器(如Kubelet)返回值的判断:


    //determine the http response code from the backend by reading from
     rawResponse+backendConn
    rawResponseCode, headerBytes, err := getResponseCode(io.MultiReader(bytes.
        NewReader(rawResponse), backendConn))
    //...
    if rawResponseCode != http.StatusSwitchingProtocols {
        //If the backend did not upgrade the request, finish echoing the response
         from the backend to the client and return, closing the connection.
        glog.V(6).Infof("Proxy upgrade error, status code %d", rawResponseCode)
        _, err := io.Copy(requestHijackedConn, backendConn)
        if err != nil && !strings.Contains(err.Error(), "use of closed network
            connection") {
            glog.Errorf("Error proxying data from backend to client: %v", err)
        }
        //Indicate we handled the request
        return true
    }
    //...
//getResponseCode reads a http response from the given reader, returns the
status code,
//the bytes read from the reader, and any error encountered
func getResponseCode(r io.Reader) (int, []byte, error) {
    rawResponse := bytes.NewBuffer(make([]byte, 0, 256))
    //Save the bytes read while reading the response headers into the rawResponse
buffer
    resp, err := http.ReadResponse(bufio.NewReader(io.TeeReader(r, rawResponse)),
        nil)
    if err != nil {
        return 0, nil, err
    }
    //return the http status code and the raw bytes consumed from the reader in
the process
    return resp.StatusCode, rawResponse.Bytes(), nil
}

增加的逻辑会判断后端返回码是否等于http.StatusSwitchingProtocols(即101状态码)。如果不等,则直接返回,关闭连接;只有在相等的情况下,代理通道才会建立。

这样一来,第一步中攻击者以出错方式调用/api/v1/namespaces/{namespace}/pods/{pod}/exec来建立到Kubelet的通道的尝试就会失败,后续攻击自然无法展开。

CVE-2018-1002105是云原生环境下少见的高危漏洞之一,CVSS 3.x评分达到了9.8,而2019年流传甚广的runC漏洞CVE-2019-5736的CVSS 3.x评分也不过8.6,其严重性可见一斑。这样一个漏洞,轻则泄露数据,重则允许攻击者接管集群。

更加值得注意的是,漏洞的触发过程完全在RESTful API层面进行,其行为特征并不明显,日志排查难度也很高。因此,除了及时更新补丁外,如何有效检测这一类隐蔽性高的云原生安全漏洞的利用行为,或进一步而言,如何针对云原生环境建立有效的API异常检测系统,是需要云安全从业者认真考虑的问题。

[1] https://github.com/kubernetes/kubernetes/pull/71412/commits/b84e3dd6f80af4016acfd891ef6cc50ce05d4b5b。