Skip to content

Commit

Permalink
feat(evaluate): output all mount info and more colorfu (#64)
Browse files Browse the repository at this point in the history
* feat(evaluate): output all mount info and more colorful

Co-authored-by: QiQi <[email protected]>

* perf(mount): string function with format major:minor root mountPoint opts - Fstype device SuperBlockOptions

Co-authored-by: neargle <[email protected]>
Co-authored-by: QiQi <[email protected]>
  • Loading branch information
3 people authored Jul 31, 2022
1 parent c8336b0 commit cace22d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 49 deletions.
76 changes: 28 additions & 48 deletions pkg/evaluate/check_mount_escape.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
Copyright 2022 The Authors of https://github.com/CDK-TEAM/CDK .
Expand All @@ -18,23 +17,14 @@ limitations under the License.
package evaluate

import (
"bufio"
"fmt"
"github.com/cdk-team/CDK/pkg/errors"
"io"
"log"
"os"
"regexp"
"strings"
"syscall"
)

type Mount struct {
Device string
Path string
Filesystem string
Flags string
}
"github.com/cdk-team/CDK/pkg/errors"
"github.com/cdk-team/CDK/pkg/util"
)

// The checkClose function calls close on a Closer and panics with a
// runtime error if the Closer returns an error
Expand All @@ -44,48 +34,38 @@ func checkClose(c io.Closer) {
}
}

func GetMounts() ([]Mount, error) {
readPath := "/proc/self/mounts"
file, err := os.Open(readPath)
if err != nil {
log.Printf("[Err] Open %s failed.", readPath)
return nil, err
}
defer checkClose(file)
mounts := []Mount(nil)
reader := bufio.NewReaderSize(file, 64*1024)
for {
line, isPrefix, err := reader.ReadLine()
if err != nil {
if err == io.EOF {
return mounts, nil
}
return nil, err
}
if isPrefix {
return nil, syscall.EIO
}
parts := strings.SplitN(string(line), " ", 5)
if len(parts) != 5 {
return nil, syscall.EIO
}
mounts = append(mounts, Mount{parts[0], parts[1], parts[2], parts[3]})
}
}

func MountEscape() {
mounts, _ := GetMounts()

mounts, _ := util.GetMountInfo()

for _, m := range mounts {
if strings.Contains(m.Device, "/") || strings.Contains(m.Filesystem, "ext") {
matched, _ := regexp.MatchString("/kubelet/|/dev/[\\w-]*?\\blog$|/etc/host[\\w]*?$|/etc/[\\w]*?\\.conf$", m.Path)

// TODO: why so may null byte in the Mounts
// [Information Gathering - Mounts]
// : -
if m.Major == "" {
continue
}


// ? why match those mount points?
if strings.Contains(m.Device, "/") || strings.Contains(m.Fstype, "ext") {
matched, _ := regexp.MatchString("/kubelet/|/dev/[\\w-]*?\\blog$|/etc/host[\\w]*?$|/etc/[\\w]*?\\.conf$", m.Root)
if !matched {
fmt.Printf("Device:%s Path:%s Filesystem:%s Flags:%s\n", m.Device, m.Path, m.Filesystem, m.Flags)
m.Root = util.RedBold.Sprint(m.Root)
m.Fstype = util.RedBold.Sprint(m.Fstype)
}
}
if m.Device == "lxcfs" && strings.Contains(m.Flags,"rw"){
fmt.Println("Find mounted lxcfs with rw flags, run `cdk run lxcfs-rw` or `cdk run lxcfs-rw-cgroup` to escape container!")
fmt.Printf("Device:%s Path:%s Filesystem:%s Flags:%s\n", m.Device, m.Path, m.Filesystem, m.Flags)

// find lxcfs mount point for escape exploit
if m.Device == "lxcfs" && util.StringContains(m.Opts, "rw"){
fmt.Printf("Find mounted lxcfs with rw flags, run `%s` or `%s` to escape container!\n", util.RedBold.Sprint("cdk run lxcfs-rw"), util.RedBold.Sprint("cdk run lxcfs-rw-cgroup"))
m.Device = util.RedBold.Sprint(m.Device)
m.MountPoint = util.RedBold.Sprint(m.Device)
}

fmt.Println(m.String())

}
}
10 changes: 9 additions & 1 deletion pkg/util/cgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ const cgroupInfoPath string = "/proc/self/cgroup"
// MountInfo
// Sample: 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
// Sample2: 1659 1605 253:1 /var/lib/kubelet/pods/cc76265f-d44d-4624-91c8-6f6812f85c7e/etc-hosts /etc/hosts rw,noatime - ext4 /dev/vda1 rw
// format: mountID parentID major:minor root mountPoint opts fstype
// Sample3: 52 36 0:47 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:26 - cgroup cgroup rw,memory
// format: mountID parentID major:minor root mountPoint opts - Fstype device SuperBlockOptions
type MountInfo struct {
Device string
Fstype string
Expand All @@ -48,6 +49,13 @@ type MountInfo struct {
SuperBlockOptions []string
}

// String format: major:minor root mountPoint opts - Fstype device SuperBlockOptions
func (mi MountInfo) String() string {
optStr := strings.Join(mi.Opts, ",")
superBlockOptionsStr := strings.Join(mi.SuperBlockOptions, ",")
return fmt.Sprintf("%s:%s %s %s %s - %s %s %s", mi.Major, mi.Minor, mi.Root, mi.MountPoint, optStr, mi.Fstype, mi.Device, superBlockOptionsStr)
}

// find block device id
func FindTargetDeviceID(mi *MountInfo) bool {
if mi.MountPoint == hostDeviceFlag {
Expand Down

0 comments on commit cace22d

Please sign in to comment.