Приключения в S3 Scraping — часть 1

Nov 29 2022
Вы не поверите, какими странными файлами люди делятся в корзинах S3. Вещи, которые они, вероятно, не должны.

Вы не поверите, какими странными файлами люди делятся в корзинах S3. Вещи, которые они, вероятно, не должны. Вещи, которые они определенно не должны.

АВС, S3

Только в этом месяце я видел такие файлы, как:

  • Лицензионные ключи к программному обеспечению компании.
  • Документ Excel с конференции по СМИ, содержащий имена, адреса электронной почты и номера телефонов сотрудников местных СМИ в 9 разных штатах.
  • Документ Powerpoint для латиноамериканского подразделения крупной технологической компании с пометкой «Проприетарно и конфиденциально» (мой испанский немного заржавел), в котором, как я полагаю, указаны затраты/сборы/доходы за предлагаемые услуги.
  • 45 000–50 000 документов в формате PDF, содержащих персональные данные клиентов (полные имена, адреса электронной почты, номера телефонов и местонахождение) для компании, которая прекратила свою деятельность за последние 2 года. (Я сообщил о корзине в службу поддержки AWS и обсудим проблему более подробно, ЕСЛИ они примут меры и защитят данные в ближайшем будущем.)
  • Скан в высоком разрешении чьих-то водительских прав, страховой карты и регистрации транспортного средства за 2015–2016 годы. (В попытке приличия я попытался связаться с этим человеком, найдя его в LinkedIn и Google, только чтобы найти человека с таким же именем, датой рождения и адресом, который был осужден в 2021 году за довольно серьезное преступление и сейчас отбывает срок, таким образом Я не потеряю сон из-за того, что его документы 7-летней давности находятся в Интернете).

В течение последних 10 лет я предполагал, что люди будут лучше оснащены и будут иметь лучшие инструменты, чтобы заблокировать свой контент и делиться только тем, чем следует делиться. Я был неправ. Так зачем через 10 лет повторять эту деятельность? Для развлечения и осознания. Также прошло несколько лет с тех пор, как я написал сколько-нибудь существенное количество кода, поэтому я хотел вернуться и отточить некоторые навыки.

Как просмотреть файлы корзины?

Во-первых, я хотел идентифицировать существующие корзины S3, которые могут быть в определенном регионе AWS (us-east, us-west и т. д.). Если бы у меня было действительное имя для корзины, я мог бы затем попробовать его в веб-браузере и посмотрите, указано ли в нем содержимое ведра. Это не означает, что сами файлы можно просмотреть, но, по крайней мере, позвольте мне увидеть пути к файлам для дальнейшего изучения этих файлов.

Например, если имя корзины «MyObviciousFakeBucket» было общедоступным и находилось в регионе AWS «Восток США 1», вы потенциально могли бы увидеть содержимое в своем веб-браузере, посетив https://myobviciousfakebucket.s3.us-east-1. amazonaws.com/

Это вернет список, аналогичный следующему частично отредактированному изображению.

Файлы, содержащиеся в корзине myobviciousfakebucket S3.

В XML-документе, который отображается в результате, вы можете увидеть записи файлов под каждым тегом «Содержание». Для каждого узла «Содержание» есть узел
«Ключ», который отображает путь к файлу и имя каждого файла. Таким образом, для файла «interesting-text-file.txt» вы потенциально можете проверить доступ к файлу, добавив путь в конец URL-адреса корзины, например:

https://myobviciousfakebucket.s3.us-east-1.amazonaws.com/interesting-text-file.txt

Если файл можно было просмотреть, он откроется в браузере или запустит автоматическую загрузку (в зависимости от типа файла и вашего браузера). Если бы у вас не было доступа, вы бы увидели результат XML, по существу отображающий сообщение «Отказано в доступе».

Несмотря на все усилия AWS, все еще есть люди, которые делают контент общедоступным, когда этого делать не следует. Я не работал с S3 несколько лет, поэтому, возможно, я что-то упускаю, но, похоже, требуется НЕСКОЛЬКО шагов, прежде чем ваш сегмент можно будет легко перечислить и просмотреть в веб-браузере.

При создании новой корзины по умолчанию установлен флажок «Блокировать весь публичный доступ». Вы должны снять флажок, а затем установить флажок «Я подтверждаю» ниже. Смотри ниже.

Настройки конфиденциальности для нового сегмента S3.

Даже когда моя корзина настроена так, чтобы не «блокировать весь публичный доступ», когда я добавлял два образца текстовых файлов, я все еще не мог перечислить содержимое корзины в своем веб-браузере, пока не добавил политику корзины JSON, явно предоставляющую публичный доступ.

{
    "Version": "2012-10-17",
    "Id": "Policy1669653712601",
    "Statement": [
        {
            "Sid": "Stmt1669653708988",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::myobviouslyfakebucket"
        }
    ]
}

Общий подход

Итак, как составить список содержимого корзины, не угадывая случайным образом? Моими основными двумя вариантами достижения этого помимо одного имени корзины моего собственного изобретения было использование файла словаря в паре либо с AWS SDK, либо с простым HTTP GET.

Для первой версии я решил написать Java-код, используя простой HTTP GET. Это избавило от необходимости изучать обновленный AWS Java SDK v2. В последний раз, когда я использовал AWS Java SDK, это была версия 1, и в нем было достаточно изменений, поэтому я не хотел, чтобы кривая обучения задерживала мой прогресс. Я также мог избежать необходимости настраивать учетные данные AWS для использования SDK и любых ошибок или странностей, связанных с SDK, которые возникали во время тестирования. Будь проще.

Я начал с существующего файла словаря, который был у меня из предыдущего личного проекта. Это был простой текстовый файл с одним словом в строке. В какой-то момент я разбил его на 8 или 10 отдельных файлов, каждый из которых содержал записи для 1–3 букв в зависимости от количества записей. Это позволило мне легче обрабатывать меньшее количество записей за раз. Вы можете поискать файл словаря в Интернете, так как их много.

Я набросал шаги, необходимые для программирования, на двух стикерах. Они были следующими:

  • Проанализируйте файл словаря, чтобы получить каждую запись слова.
  • Для каждого слова в списке создайте URL-адрес для проверки, используя слово в качестве имени корзины и региона AWS (сейчас жестко запрограммировано на «Восток США 1»).
  • Попробуйте подключиться к URL-адресу, чтобы выполнить операцию GET.
  • Получите код ответа, отправленный с сервера.
  • Если код ответа указывает на успех (ведро существует), добавьте слово в структуру данных.
  • Сохраните успешные слова в структуре данных в простой текстовый файл для дальнейшего изучения.

Разобрать файл словаря

private void populateList(List<String> words, String dictionaryFile) {

   BufferedReader br = null;
   try {
      br = new BufferedReader(new FileReader(new File(dictionaryFile)));
      String line;
      while ((line = br.readLine()) != null) {
         words.add(line);
      }

   } catch (Exception e) {
      e.printStackTrace();
   } finally {
      try {
         if (br != null) {
            br.close();
         }
      } catch (Exception e) { }
   }
}

Создайте URL-адрес

String currentRegion = "us-east-1";
int wordSize = words.size();

for (int i = 0; i < wordSize; i++) {

   String bucketName = words.get(i);
   
   String sUrl = "https://" + bucketName + ".s3." + currentRegion + ".amazonaws.com";
   URL url = new URL(sUrl);

   // do something with the URL
}

Выполнить операцию ПОЛУЧИТЬ

String sUrl = "https://" + bucketName + ".s3." + currentRegion + ".amazonaws.com/";
URL url = new URL(sUrl);

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();

Получить код ответа и сохранить его

int respCode = connection.getResponseCode();

if (respCode == 200) {
   code200s.add(bucketName + "," + currentRegion);
}

Сохраните допустимые имена сегментов

private void writeCode200s(List<String> validBuckets, String parentDirectory) {

   if(validBuckets == null || validBuckets.isEmpty()) {
      return;
   }
        
   BufferedWriter bw = null;
   
   try {
      File parentDirectory = new File(parentDirectory);
      if (!parentDirectory.exists()) {
         parentDirectory.mkdirs();
      }

      FileWriter writer = new FileWriter(new File(parentDirectory, "valid_buckets_" + System.currentTimeMillis()+ ".txt"));
      bw = new BufferedWriter(writer);
      
      for (int i = 0; i < validBuckets.size(); i++) {
         String bucketName = validBuckets.get(i);

         bw.write(bucketName);
         bw.newLine();
      }

   } catch (Exception e) {
      e.printStackTrace();
   } finally {
      try {
         if (bw != null) {
            bw.close();
         }
      } catch (Exception e) { }
   }
}

Вот и все. Просто и понятно. Возможно, это было не самое элегантное решение, но оно сработало и послужило основой, позволившей мне расширить и улучшить его. Я идентифицировал тысячи действительных сегментов S3, просто соскребая несколько букв алфавита. Всего за несколько первых попыток я нашел каталоги файлов MP3, миллионы изображений, бесчисленное количество файлов журналов и многое другое.

С тех пор я удалил свою тестовую корзину «myobviiouslyfakebucket», так что не стесняйтесь претендовать на это имя, если хотите. В следующих нескольких частях этой серии статей я расскажу о дополнительных шагах по улучшению этого решения, таких как:

  • Обработка и хранение кодов ответов для сегментов, кроме 200 (ОК), их значение и действия с этой информацией.
  • Использование списка допустимых имен корзин, чтобы увидеть, можете ли вы перечислить список файлов в этой корзине.
  • Разбор списка файлов корзины для захвата пути и имени отдельных файлов.
  • Фильтруйте файлы по расширению файла, чтобы игнорировать нежелательный шум.
  • Разбивка результатов файлов на страницы для корзин S3 с более чем 1000 файлов.
  • Проверка списков файлов на предмет возможности загрузки отдельных файлов.