gatekeeper-library icon indicating copy to clipboard operation
gatekeeper-library copied to clipboard

Cve 2020 8554

Open AbirHamzi opened this issue 4 years ago • 6 comments

AbirHamzi avatar Jan 03 '21 18:01 AbirHamzi

This policy would deny all usage of LoadBalancers IPs, which may be a bit too restrictive. Consider adding a whitelist option through an allowedUsers parameter. Something similar is done in the externalIP constraint template to whitelist IPs (allowedIPs).

The system service account that normally updates Load Balancer IPs through services/status requests is system:serviceaccount:kube-system:service-controller, it should probably be included in the allowedUsers whitelist, if you choose to implement it.

yuvalavra avatar Jan 04 '21 10:01 yuvalavra

This policy would deny all usage of LoadBalancers IPs, which may be a bit too restrictive. Consider adding a whitelist option through an allowedUsers parameter. Something similar is done in the externalIP constraint template to whitelist IPs (allowedIPs).

The system service account that normally updates Load Balancer IPs through services/status requests is system:serviceaccount:kube-system:service-controller, it should probably be included in the allowedUsers whitelist, if you choose to implement it.

I checked the following scenario and it works fine:

  1. Create clusterip service
  2. Update the service type to loadbalancer

After few seconds a public ip was assigned to the service, which means the policy has no impact on the work of the service controller. Please let me know if we have more scenarios to test.

AbirHamzi avatar Jan 04 '21 10:01 AbirHamzi

@AbirHamzi The service controller is able to assign a Load Balancer IP because template.yaml misses the first assignment of a Load Balancer IP. You can verify that by patching the status of a LoadBalancer service just after creating it, before the service controller managed to assign it a Load Balancer IP.

To prevent this bypass, replace the following line in template.yaml:

request.oldObject.status.loadBalancer.ingress != request.object.status.loadBalancer.ingress

With:

newLoadBalancerIPs := {ips | ips := request.object.status.loadBalancer.ingress[_].ip} - {oldips | oldips := input.review.oldObject.status.loadBalancer.ingress[_].ip}
count(newLoadBalancerIPs) > 0     

yuvalavra avatar Jan 04 '21 15:01 yuvalavra

@AbirHamzi The service controller is able to assign a Load Balancer IP because template.yaml misses the first assignment of a Load Balancer IP. You can verify that by patching the status of a LoadBalancer service just after creating it, before the service controller managed to assign it a Load Balancer IP.

To prevent this bypass, replace the following line in template.yaml:

request.oldObject.status.loadBalancer.ingress != request.object.status.loadBalancer.ingress

With:

newLoadBalancerIPs := {ips | ips := request.object.status.loadBalancer.ingress[_].ip} - {oldips | oldips := input.review.oldObject.status.loadBalancer.ingress[_].ip}
count(newLoadBalancerIPs) > 0     

Yes indeed you are right. I'm working on that, thank you for your feedback.

AbirHamzi avatar Jan 04 '21 19:01 AbirHamzi

Thank you for the submission!

Is this the same CVE that this template was meant to address?

https://github.com/open-policy-agent/gatekeeper-library/pull/39

Referenced in this k8s issue

maxsmythe avatar Jan 09 '21 05:01 maxsmythe

Thank you for the submission!

Is this the same CVE that this template was meant to address?

#39

Referenced in this k8s issue

@maxsmythe yes it's the same CVE, but restricting service externalIPs/loadbalancerIPs to an allowlist is not enough because the hacker still can patch the service status and intercept the traffic.

AbirHamzi avatar Jan 09 '21 11:01 AbirHamzi

Is this PR still needed now we have https://github.com/open-policy-agent/gatekeeper-library/tree/master/library/general/externalip?

sathieu avatar Nov 29 '22 09:11 sathieu