irsl / gcp-dhcp-takeover-code-exec

Google Compute Engine (GCE) VM takeover via DHCP flood - gain root access by getting SSH keys added by google_guest_agent
533 stars 35 forks source link

Bad math? #3

Closed dedworks closed 3 years ago

dedworks commented 3 years ago

Attack #2: Targeting a VM on the same subnet (~same project), while it is refreshing the lease (so no reboot is needed). This takes place every half an hour (1800s), making 48 windows/attempts possible a day. Since an F class VM has ~170.000 pps (packet per second), and a day of unixtime + potential pids makes ~86420 potential XIDs, this is a feasible attack vector.

Where you have a day of unixtime + potential pids, shouldn't you have a day of unixtime * potential pids, thus 2,160,000 instead of ~86420?

And why a day and not a week or a month or a year?

irsl commented 3 years ago

The number of all potential inputs is indeed the product of them, but the vast majority of the result of the formula is overlapping, hence the final set of potential XIDs is correct in the write up. Why a day? In that section I was estimating the speed of the process to find the right uptime value of the targeted VM; without knowing the uptime it is not fast at all, but possible, still.

dedworks commented 3 years ago

You're burying a lot of assumptions there to inflate the probability of this particular attack variation working.

You've done a lot of magnificent work here, there is really no need to debase it with distortion like this.

irsl commented 3 years ago

You can verify that the ranges are indeed overlapping by comparing the output of randr.c with the original, unoptimized version:

  if(argc != 6) {
     printf("Usage: %s ipaddress min_pid max_pid min_unixtime max_unixtime\n", argv[0]);
     return -1;
  }

  char* ipaddress_str = argv[1];
  int min_pid = atoi(argv[2]);
  int max_pid = atoi(argv[3]);
  int min_unixtime = atoi(argv[4]);
  int max_unixtime = atoi(argv[5]);
  int ipaddress = inet_addr(ipaddress_str);
  for(int pid = min_pid; pid <= max_pid; pid++) {
    for(int unixtime = min_unixtime; unixtime <= max_unixtime; unixtime++) {
       unsigned seed = ipaddress + unixtime + pid;
       fprintf(stderr, "Seed for pid %d and unixtime %d is: %08x\n", pid, unixtime, seed);
       srandom(seed);
       long int l = random();
       printf("%08x\n", l);
    }
  }

If I made a mistake somewhere, please show me an example and I gonna correct the write up.

dedworks commented 3 years ago

I'm not able to look into this closer but I expect I misinterpreted something