해킹 기록 – 깃헙에 구글 클라우드 API KEY가 노출된지 13분만에 50만원 청구당함.

열심히 일하고 잠시 쉬고있던 점심시간에 갑자기 이메일로 내 계정이 아마도 크립토 마이닝에 사용되고 있다는 정보를 받았다.

비슷한 이메일을 SendGrid에서도 받았다.

내용인 즉, 내 SendGrid API Key가 Github 저장소에 노출되었다는 것이다. SendGrid에서 찾아준 저 저장소를 살펴보니 예전에 같이 팀프로젝트를 하던 중국 친구가 나한테 한마디 말도 없이 같이 작업하던 본래 private로 되어있던 소스코드를 아마도 자신의 포트폴리오로 사용한다고 깃헙에 퍼블릭으로 올린 모양이다. 그래서 아마도 해커가 새로 올라오는 깃헙 소스코드에 대해서 검사를 시작해서 서비스 어카운트로 추정되는 키를 모두 탈취하고 해킹 작업을 돌리는 것 같았다.

구글 클라우드도 함께 사용했으니 당연히 노출됬겠지 싶어서 일단 서비스 계정부터 없애기로 했다.
그런데 이게 왠일? 왠 구글 클라우드 인스턴스가 240개가 있는 것이다. 난 이 프로젝트를 사용하지도 않는데.. 놀라서 일단 서비스 계정부터 없애고 활동기록을 살펴보니
12:59쯤 노출된 저 서비스 계정을 탈취한 해커가 1:21에 이 서비스 키로 다른 서비스 계정을 만들고, 온갖 정책을 만든 다음에 원격으로 VM (compute instance)을 만들 수 있도록 Google API를 설정, 또한 방화벽 규칙까지 외부로 모든 아이피를 다 오픈. 이후에 1:22부터 2:16까지 240개의 VM을 만들었다.

그리고 나는 이를 2:29발견해서 2:30에 즉각 VM들을 중지. 왠일인지 VM이 바로 삭제가 안되더라. 보니깐 모든 VM에 삭제방지가 걸려있음.. ㅎㅎㅎ 일단 중지를 해뒀다.

https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion

하.. 짜증나던 찰나, 구글링을 해보니 누가 쉘스크립트를 만들어 둔 것이 있었다. 물론 이건 중단된 인스턴스들을 한번에 지우는 shell이긴 했으나.

https://stackoverflow.com/questions/36581688/delete-all-stopped-instances-from-google-compute-engine

그래서 쉘에 친근하지는 않지만 내가 대충 deletion protection을 없애고 삭제하고, 관련된 디스크를 지우는 스크립트를 만들었다.

for terminated_instance_uri in $(gcloud compute instances list --uri --filter="status:TERMINATED" 2> /dev/null); do
    terminated_instance_name=${terminated_instance_uri##*/}
    terminated_instance_zone_uri=${terminated_instance_uri/\/instances\/${terminated_instance_name}/}
    terminated_instance_zone=${terminated_instance_zone_uri##*/}

    # set the no deletion protection
    gcloud compute instances update ${terminated_instance_name} --no-deletion-protection --zone ${terminated_instance_zone}

    # delete terminated instances
    if [ -n "${terminated_instance_name}" ] && [ -n "${terminated_instance_zone}" ] && gcloud compute instances delete ${terminated_instance_name} --zone ${terminated_instance_zone} --delete-disks all --quiet; then
        echo "deleted: ${terminated_instance_zone}/${terminated_instance_name}"
    fi
done

# delete orphaned disks (filter for disks without a user)
for orphaned_disk_uri in $(gcloud compute disks list --uri --filter="-users:*" 2> /dev/null); do
    orphaned_disk_name=${orphaned_disk_uri##*/}
    orphaned_disk_zone_uri=${orphaned_disk_uri/\/disks\/${orphaned_disk_name}/}
    orphaned_disk_zone=${orphaned_disk_zone_uri##*/}
    if [ -n "${orphaned_disk_name}" ] && [ -n "${orphaned_disk_zone}" ] && gcloud compute disks delete ${orphaned_disk_name} --zone ${orphaned_disk_zone} --quiet; then
        echo "deleted: ${orphaned_disk_zone}/${orphaned_disk_name}"
    fi
done

vim등에서 delete.sh로 저장 후, chmod 777 delete.sh (707도 됨) 로 권한 준 다음, ./delete.sh 실행하면 됨. 하지만 시간은 한 40분 정도 걸린듯..

어쨋든 그 경과, 예상컨데 해커가 2:16 – 2:29까지 약 13분간 사용한 내역까지는 못봐도, 청구한 내역을 살펴보니

하하.. 42만원에 가까운 금액 청구 ㅎㅎㅎㅎ
SKU 별로 내역을 확인해보니 GPU와 RAM사용량이 많았다. 이는 즉, 최대한 빠른 속도로 크립토 마이닝을 했다는 추측이 가능하다.

여하튼 금액에 놀라서 이걸 내야하나.. 하던 생각에 일단 GCP에서 이메일 온 [email protected] 로 혹시 환불 되냐고 물어봄. 나름 GCP를 7년간 사용한 로열 커스토머라면서.. (ㅎㅎㅎ)

오 아마도 가능하다고 한다? 그리고 빌링 팀으로 넘기더니,

28일 저녁 9시쯤에, 즉 한 하루 반나절 정도 걸려서 환불을 받았다.

하 물론 잘 사용하지는 않는 클라우드 계정이긴 하지만 여기서 key takeways는:

  • 절대 API키를 어드민으로 만들지 않는다. 관련된 권한만 허용한다.
  • API키에 최대 할당량을 만들어 둔다. 뭐 분당 10번 요청 이런.
  • 내 카드랑 연결되어 있는 어카운트는 꼭 관리를 하고, 사용을 안할 경우에는 카드정보를 삭제하거나 삭제 요청한다.

여튼 개인적으로 꽤나 놀랐다. 단 13분만에 42만원이 청구가 되다니, 만약 더 손놓고 있었으면 몇천만원이 청구되었을지도 모르는 상황. 이에 대한 한도를 설정 안해둔 나도 참 바보같고 무엇보다 공용 프로젝트에 개인 서비스 키를 사용한것도 문제인 것 같다. 특히 팀플 같은 것에 내 개인 키를 바보처럼 놔뒀으니, 깃헙에 올린 그 친구를 마냥 욕할 수도 없는 노릇이다. 그래서 따로 연락은 하지 않았지만 나중에 기회가 되면 얘기를 해둬야 할 것 같다. 아마도 지금은 취준으로 바쁜 것 같으니..

그런데 사실 저게 대부분 신입들이 겪는 메이저한 문제이기도 하다. 해커들에게 노출된 포인트를 남겨서 취약점으로 만들고 SQL injection이나 Man-in-the-middle등의 웹상에서의 어텍을 당하기도 한다. 젤 중요한 것은 취약점에 대해서 꾸준히 공부를 하고 (이런 부분은 대부분의 tech블로그에 많이 올라온다 네이버 D2라던가.. 그리고 사수 입장에서도 그런 키를 주는건 위험하다. 그래서 내가 일하는 곳에서는 정말 권한 하나 얻는 과정이 몇 일씩 걸린다. 그래서 스타트업에서 일하던 입장에서 보면 상당히 느리긴 한데, 보안이란게 정말 금액과 직결되는 만큼 당연히 신경써야 하는 부분인 것은 맞다.

어쨌든 구글 클라우드의 이런 발빠른 대응을 보면서 사실 좀 감동했다. (Thanks Hanna & Czarina!) 매년 유라임을 운영하면서 얼마 안되는 지출을 꽤 오랬동안 해오긴 했는데, 사실 나도 보안에 엄청 신경쓰면서 개발을 해서 6년간 이렇다 할 노출이나 해킹 그런것은 없었는데 (간혹 DDOS와 같은 공격을 받긴 했지만 서버 차원에서 해결했고, public IP들은 모두 private이라서 크게 문제는 없었다. 그리고 최근에는 VPN을 사용하기 시작.) 정말 생각지도 못한 부분에서, 서비스 계정이 당연히 민감한 것임을 알면서도 내가 당할줄은 꿈에도 몰랐다.

결국, 살아가면서 사람은 긴장을 늦추면 안되는 것이 맞다. 그래도 이렇게 ‘위험’을 감지하고 즉각 알려줄 수 있는 것. (웃기게도 내가 해당 팀이긴 하다. 난 페이먼트 쪽이긴 하지만.) 그런 실무적 사례를 정말 우연찮게 배우게 되었다. 클라우드, 꺼진 인스턴스도 다시보자.