Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANSI escape characters in kubectl output are not being filtered #101695

Closed
g3rzi opened this issue May 2, 2021 · 31 comments · Fixed by #112553
Closed

ANSI escape characters in kubectl output are not being filtered #101695

g3rzi opened this issue May 2, 2021 · 31 comments · Fixed by #112553
Assignees
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. sig/cli Categorizes an issue or PR as relevant to SIG CLI. triage/accepted Indicates an issue or PR is ready to be actively worked on.

Comments

@g3rzi
Copy link

g3rzi commented May 2, 2021

It is a security issue, but after contacting [email protected], Tim and the team confirmed that they are comfortable posting it publicly.

What happened:

Kubernetes doesn't sanitize the 'message' field in the Event JSON objects.
Notice that this is relevant only to JSON objects, not YAML objects.
By creating new event, we can insert ANSI escape characters inside the "message" field, like:

"\u001b[2J\u001b[3J\u001b[1;1H\u001b[m spoofed \u001b[60C\u001b[1;0m. Done"

This an example of such JSON request:

{
    "apiVersion": "v1",
    "involvedObject": {
        "kind": "Node",
        "name": "node01",
        "uid": "node01"
    },
    "kind": "Event",
    "message": "\u001b[2J\u001b[3J\u001b[1;1H\u001b[m spoofed \u001b[60C\u001b[1;0m. Done",
    "metadata": {
        "name": "spoofEvent",
        "namespace": "default"
    },
    "source": {
        "component": "kubelet",
        "host": "node01"
    },
    "type": "Normal"
}

The codes:
\u001b[2J -> Clean the screen and history
\u001b[3J -> Clean the entire screen and delete all lines saved in the scrollback buffer
\u001b[1;1H -> Moves the cursor position to row 1, column 1 (beginning).
\u001b[m -> Set the colors
\u001b[60C -> Move the cursor forward 60 steps
\u001b[1;1m -> Set the text colors to white

The result is that the text was spoofed, and we could spoof the events, create hidden events, or hide other events.

What you expected to happen:

The ANSI escape characters will be filtered so they couldn't affect the terminal (i.e. using embeded ANSI colors won't do anything to the terminal).
Or maybe some message that says that you can't use ANSI escape characters.

How to reproduce it (as minimally and precisely as possible):

  1. Run this code:

kubectl create -f - <<EOF
{
    "apiVersion": "v1",
    "involvedObject": {
        "kind": "Node",
        "name": "node01",
        "uid": "node01"
    },
    "kind": "Event",
    "message": "\u001b[2J\u001b[3J\u001b[1;1H\u001b[m spoofed \u001b[60C\u001b[1;0m. Done",
    "metadata": {
        "name": "spoofEvent",
        "namespace": "default"
    },
    "source": {
        "component": "kubelet",
        "host": "node01"
    },
    "type": "Normal"
}
EOF

It will create a new event.

  1. Run kubectl get events, you will see that the screen was clear, you will get a "spoof" message, and all the rest events or columns were gone.

Anything else we need to know?:

It might look like a low severity issue, but there are other variety of things we can do, from DoS by using colors to hide all the events, changing the title of the terminal window, and spoof the data.

It can affect other systems that are using Kubernetes events, such as monitoring applications. It doesn't have to be only the Kubernetes events. There might be other vulnerable objects that we didn't find or other systems that create new objects that count on this mechanism.

ANSI escape characters were used to abuse terminals emulators and even cause code execution if the terminal is vulnerable (like CVE-2003-0069).

Environment:

  • Kubernetes version (use kubectl version):
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:12:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:20:00Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
  • Cloud provider or hardware configuration:
  • OS (e.g: cat /etc/os-release):
NAME="Ubuntu"
VERSION="16.04.7 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.7 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
  • Kernel (e.g. uname -a):
Linux manager1 4.15.0-140-generic #144~16.04.1-Ubuntu SMP Fri Mar 19 21:24:12 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  • Install tools: minikube
minikube version: v1.19.0
commit: 15cede53bdc5fe242228853e737333b09d4336b5
  • Network plugin and version (if this is a network-related bug):
  • Others: we also reproduced it in Kubernetes (not minikube) version 1.18
@g3rzi g3rzi added the kind/bug Categorizes issue or PR as related to a bug. label May 2, 2021
@k8s-ci-robot k8s-ci-robot added needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels May 2, 2021
@g3rzi g3rzi changed the title ANSI escape characters in Event JSON objects are not being filtered ANSI escape characters in JSON Event objects are not being filtered May 2, 2021
@g3rzi
Copy link
Author

g3rzi commented May 5, 2021

/sig api-machinery

@k8s-ci-robot k8s-ci-robot added sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. and removed needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels May 5, 2021
@pacoxu
Copy link
Member

pacoxu commented May 6, 2021

[root@daocloud print]# kubectl get event > test.events &&  cat --show-nonprinting  test.events
LAST SEEN   TYPE     REASON           OBJECT                                  MESSAGE
44s         Normal   SandboxChanged   pod/nginx-deployment-7969cc74c6-9b9z7   Pod sandbox changed, it will be killed and re-created.
103s        Normal   SandboxChanged   pod/nginx-deployment-7969cc74c6-f87gt   Pod sandbox changed, it will be killed and re-created.
54s         Normal   SandboxChanged   pod/nginx-deployment-7969cc74c6-fpnnb   Pod sandbox changed, it will be killed and re-created.
<unknown>   Normal                    node/node01                             ^[[2J^[[3J^[[1;1H^[[m spoofed ^[[60C^[[1;0m. Done

I think the problem should be kubectl doesn't handle non-printing Characters.

I built an image daocloud.io/daocloud/test-escape:0.1.

  • The log contains the escape chars as well.

kubectl logs would have the same problem as well.
/sig cli

@k8s-ci-robot k8s-ci-robot added the sig/cli Categorizes an issue or PR as relevant to SIG CLI. label May 6, 2021
@caesarxuchao
Copy link
Member

We'll let the sig-cli to take a pass first. Please re-tag sig-apimachinery if needed.

/remove-sig api-machinery

@k8s-ci-robot k8s-ci-robot removed the sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. label May 6, 2021
@g3rzi
Copy link
Author

g3rzi commented May 20, 2021

Any update on this issue?

@g3rzi
Copy link
Author

g3rzi commented May 31, 2021

Any updates?

@soltysh
Copy link
Contributor

soltysh commented Jun 7, 2021

@g3rzi apologies, this slipped my attention, I'll have a look at it later this week
/assign

@g3rzi
Copy link
Author

g3rzi commented Jun 21, 2021

Hi @soltysh, did you have time to look at this issue?

@g3rzi
Copy link
Author

g3rzi commented Jun 28, 2021

Any update?

@g3rzi
Copy link
Author

g3rzi commented Jul 18, 2021

Hi @soltysh, did you have time to look at this issue?

@g3rzi
Copy link
Author

g3rzi commented Aug 11, 2021

Hi @soltysh, did you have time to look at this issue?
@caesarxuchao maybe you know?

@palnabarun
Copy link
Member

cc: @RinkiyaKeDad

@RinkiyaKeDad
Copy link
Member

I can also help with this 🙂

/assign

@pacoxu
Copy link
Member

pacoxu commented Sep 10, 2021

/triage accepted

@k8s-ci-robot k8s-ci-robot added triage/accepted Indicates an issue or PR is ready to be actively worked on. and removed needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Sep 10, 2021
@soltysh
Copy link
Contributor

soltysh commented Sep 10, 2021

I spoke with @RinkiyaKeDad, he'll be looking at the this. In short I'm proposing to update

func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
// we use reflect.Indirect here in order to obtain the actual value from a pointer.
// we need an actual value in order to retrieve the package path for an object.
// using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers.
if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) {
return fmt.Errorf(InternalObjectPrinterErr)
}
switch obj := obj.(type) {
case *metav1.WatchEvent:
if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj.Object.Object)).Type().PkgPath()) {
return fmt.Errorf(InternalObjectPrinterErr)
}
data, err := json.Marshal(obj)
if err != nil {
return err
}
_, err = w.Write(data)
if err != nil {
return err
}
_, err = w.Write([]byte{'\n'})
return err
case *runtime.Unknown:
var buf bytes.Buffer
err := json.Indent(&buf, obj.Raw, "", " ")
if err != nil {
return err
}
buf.WriteRune('\n')
_, err = buf.WriteTo(w)
return err
}
if obj.GetObjectKind().GroupVersionKind().Empty() {
return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type")
}
data, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return err
}
data = append(data, '\n')
_, err = w.Write(data)
return err
}
to properly handle escape chars handling. Looking at JSON spec I'd suggest using strconv.QuoteToASCII which was also proposed in this golang issue.

@tallclair tallclair changed the title ANSI escape characters in JSON Event objects are not being filtered ANSI escape characters in kubectl output are not being filtered Nov 19, 2021
@tallclair
Copy link
Member

IMO this should apply to all arbitrary strings output to a terminal by command line tools. It's probably simpler to just put a catch-all around kubectl output to escape control characters, but I'm not sure if kubectl intentionally uses control characters anywhere. I am neutral on whether the escaping should still be applied when the kubectl output is piped to another command.

I do NOT think the escaping should be applied server side. This is only an issue for tools outputting the data to a terminal.

@BenTheElder
Copy link
Member

but I'm not sure if kubectl intentionally uses control characters anywhere.

kubectl uses ansi escape codes (color, bold ...) when printing warnings since #73032

@RSAlderman
Copy link

@RinkiyaKeDad that related issue #104962 (comment) closed waiting on solution design

Am I correct that there is currently no fix for this issue, assigned CVE-2021-25743?

@RinkiyaKeDad
Copy link
Member

@RSAlderman from what I'm aware of, #104962 was the only PR out to fix this.

@RSAlderman
Copy link

@RinkiyaKeDad thanks for the prompt response. You said last week in #104962

The issue still needs to be fixed ...
will open a new PR once we've decided how to fix it exactly.

I presume that PR will be referenced from this issue when it is produced and then backported to 1.22 and 1.21 too?

@RinkiyaKeDad
Copy link
Member

and then backported to 1.22 and 1.21 too

Sorry I'm afraid I don't know if this will happen or not. Let's wait for what others have to say 🙂
Also, just as an fyi, I'm not working on this currently and I don't think anyone else is too.

@liggitt
Copy link
Member

liggitt commented Jan 19, 2022

As noted in #107617, this also applies to display of annotations

@p-rog
Copy link

p-rog commented Jan 21, 2022

Are there any news regarding potential patch to this vulnerability?
It seems that some fix in kubectl is the best option right now.

@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Apr 21, 2022
@tallclair
Copy link
Member

/lifecycle frozen

@k8s-ci-robot k8s-ci-robot added lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Apr 22, 2022
@alexanther1012
Copy link

there is currently no fix for this issue?, assigned to CVE-2021-25743

@sayananavya
Copy link

sayananavya commented Jun 29, 2022

Team, Any fix for this vulnerability?
What packages need to be changed/updated??

Thanks in advance.

@pacoxu
Copy link
Member

pacoxu commented Sep 21, 2022

@dgl is working on this. #112553 is open.

@DamianSawicki
Copy link
Contributor

@buckaroogeek asked about it already in the PR, but got no response for 11 months, so I'll ask again here: will the fix be applied to 1.25 and 1.24? @dgl @g3rzi

@buckaroogeek
Copy link

@DamianSawicki - thanks for checking again. I suspect this is almost moot. 1.24 is no longer supported and 1.25 end-of-life was supposed to be 2023.10.27.

@dgl
Copy link
Contributor

dgl commented Oct 30, 2023

It's unlikely this will be backported now. Note that a 1.25 cluster can be used with kubectl 1.26 per version skew policy and 1.24 on the cluster is likely fine too in this case, so given those are out of support it doesn't make sense to backport, just use a newer kubectl.

@DamianSawicki
Copy link
Contributor

I see, thank you both for the answers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. sig/cli Categorizes an issue or PR as relevant to SIG CLI. triage/accepted Indicates an issue or PR is ready to be actively worked on.
Projects
None yet
Development

Successfully merging a pull request may close this issue.