4 ms·
The PoC is mostly correct, but basically is testing for a side effect of the fix, not the presence of the vulnerability. Either which way it's probably still u
by darren0 8y ago
The PoC is mostly correct, but basically is testing for a side effect of the fix, not the presence of the vulnerability. Either which way it's probably still useful, but since we are all geeks here might as well talk about the minutia.
The PoC basically tests that if you create a websocket request that results in non-101 response the socket is closed by the server. That is a side effect of the fix. The way the proxy code works is that on presence of the Upgrade header it first hijacks the HTTP request and dials the target. It then starts a copy loop but reads the first bytes into a http.Response. If the response is not 101 it will exit.
The a side effect is that it just so happens to be that because the connection is hijacked the golang server will not reuse the TCP connection and will close it. But according to the HTTP spec that TCP connection is still valid for reuse so the server does not have to actually close the connection (but it happens to). Where this PoC could fall apart is if you are running kube-apiserver behind a particularly pedantic LB (ALB might apply here). Most LBs will not reuse any TCP connection that had an Upgrade header in it, but if they are smart and read the response they can if it didn't result in a 101. From that perspective a load balancer (or reverse proxy) is not obligated to close the TCP connection to the client.
To fully test the vulnerability you need to find a pod you can exec to and another pod on the same node you are not authorized to exec to. First send a malformed pod exec and get the open socket. Then send another request using the kubelet API to exec to a pod you are not authorized for. Then see if you get a valid response (which I believe is a callback URL for the actually tty stream).
The PoC is still basically valid because it could just give you a false negative that you are vulnerable (not a false positive all is swell).
- kevin_nisbet 8y agoYou're analysis is correct. I did briefly consider this when originally throwing together the PoC. It seemed reasonable at the time to test for the behaviour of the kubernetes apiserver as implemented, not how it could theoretically behave if implemented differently. In the ALB/L7 type use case, I'm not sure a reliable PoC can ever exist, because even if you do successfully exploit it, the second request can be load balanced elsewhere. Also, I don't believe you would necessarily need a separate pod, the PoC could work by using different endpoints, such as exec vs logs, or even better, try and hit a non pod related API endpoint within kubelet. Unfortunately I tried to get the PoC working quickly, and didn't have a chance to revisit this today to see if it can be enhanced.