📑

K8s の脆弱性 CVE-2021-25735 について

2021/04/15に公開

脆弱性

CVE-2021-25735 が公開されました。Validating Admission Webhookにて validation をすり抜けてしまう脆弱性です。
https://github.com/kubernetes/kubernetes/issues/100096

具体例

早速具体例を見ていきましょう。この例は Node を UPDATE する際に、 label のチェックを行うValidating Admission Webhookです。既存の label editAllowedtrueであれば UPDATE を許可し、それ以外であれば拒否します。

var https = require('https');
var fs =  require('fs');

var options = {
  key: fs.readFileSync('/tls/tls.key'),
  cert: fs.readFileSync('/tls/tls.crt'),
  requestCert: false,
  rejectUnauthorized: false
};

var server = https.createServer(options);
server.on('request', doRequest);
server.listen(8080);
console.log('HTTPS Server running!');

function doRequest(req, res) {
  if (req.headers['content-type'] !== 'application/json') {
    console.log('content-type is not application/json:' + req.headers['content-type']);
    return
  }

  if (req.method !== 'POST') {
    console.log('method is not POST:' + req.method);
    return
  }

  var body = '';
  req.on('data', function(chunk) {
    body += chunk;
  });
  req.on('end', function() {
    const requestedAdmissionReview = JSON.parse(body);
    isAllowed = requestedAdmissionReview.request.oldObject.metadata.labels['editAllowed'] === 'true';

    responseAdmissionReview = {
      'apiVersion': 'admission.k8s.io/v1',
      'kind': 'AdmissionReview',
      'response': {
        'uid': requestedAdmissionReview.request.uid,
        'allowed': isAllowed,
        'status': {
          'message': (isAllowed ? 'Validation succeeded' : 'Validation failed')
        }
      }
    };

    res.writeHead(200, {'Content-Type': 'application/json'});
    res.write(JSON.stringify(responseAdmissionReview));
    res.write('\n');
    res.end();
  });
}

では下記コマンドで実際に Node を変更してみましょう。

$ kubectl edit nodes nodename
...
  labels:
    editAllowed: "false"
...

ここにdummy: dummyというラベルを追記します。

  labels:
    dummy: dummy
    editAllowed: "false"

当然、Validating Admission Webhookのチェックに引っかかり、エラーとなります。

error: nodes "nodename" could not be patched: admission webhook "sample-validating-webhook.hoge.fuga.local" denied the request: Validation failed
You can run `kubectl replace -f /tmp/kubectl-edit-9e91t.yaml` to try this update again.

ここで、editAllowedtrueに変更した場合はどうでしょうか。

  labels:
    dummy: dummy
    editAllowed: "true"

こうすることでValidating Admission WebhookのチェックがOKとなりdummy: dummyラベルを追加できてしまうのです。

原因

kube-apiserverrequest.objectrequest.oldObjectというオブジェクトをValidating Admission Webhookに渡します。request.object には新しい設定が入り、request.oldObjectには古い設定が入りますが、request.objectrequest.oldObjectの一部を上書きしてしまう不具合があるため、このようなことが起こります。

影響範囲

これまで見てきたように、

  1. Node に対してValidating Admission Webhookを使用している
  2. 既存データを条件としたValidating Admission Webhookを使用している

という条件の場合に当脆弱性の影響を受けます。

また、下記バージョンのkube-apiserverが影響を受けます。

  • kube-apiserver v1.20.0 - v1.20.5
  • kube-apiserver v1.19.0 - v1.19.9
  • kube-apiserver <= v1.18.17

Discussion