การผจญภัยใน S3 Scraping — ตอนที่ 1

Nov 29 2022
คุณจะไม่เชื่อว่ามีไฟล์แปลกๆ ที่ผู้คนแชร์ในบัคเก็ต S3 สิ่งที่พวกเขาอาจไม่ควร

คุณจะไม่เชื่อว่ามีไฟล์แปลกๆ ที่ผู้คนแชร์ในบัคเก็ต S3 สิ่งที่พวกเขาอาจไม่ควร สิ่งที่พวกเขาไม่ควรอย่างแน่นอน

AWS, S3

ในเดือนนี้ฉันได้เห็นไฟล์เช่น:

  • รหัสลิขสิทธิ์ซอฟต์แวร์ของบริษัท
  • เอกสาร Excel จากการประชุมเกี่ยวกับสื่อที่มีชื่อ อีเมล และหมายเลขโทรศัพท์ของพนักงานสื่อท้องถิ่นในรัฐต่างๆ 9 รัฐ
  • เอกสาร Powerpoint สำหรับแผนกละตินอเมริกาของบริษัทเทคโนโลยีรายใหญ่แห่งหนึ่งที่ระบุว่า "กรรมสิทธิ์และความลับ" (ภาษาสเปนของฉันค่อนข้างจะขึ้นสนิมเล็กน้อย) ซึ่งฉันเชื่อว่ามีการระบุต้นทุน/ค่าธรรมเนียม/ส่วนต่างสำหรับบริการที่เสนอ
  • เอกสาร PDF 45,000–50,000 รายการที่มี PII ของลูกค้า (ชื่อเต็ม ที่อยู่อีเมล หมายเลขโทรศัพท์ และที่ตั้ง) สำหรับบริษัทที่ปิดกิจการในช่วง 2 ปีที่ผ่านมา (ฉันได้รายงานบัคเก็ตนี้ไปยังฝ่ายสนับสนุนของ AWS แล้ว และจะหารือเกี่ยวกับปัญหาในรายละเอียดเพิ่มเติมหากพวกเขาดำเนินการและปกป้องข้อมูลในอนาคตอันใกล้นี้)
  • การสแกนใบขับขี่ บัตรประกัน และทะเบียนรถของใครบางคนที่มีความละเอียดสูงตั้งแต่ปี 2558-2559 (ด้วยความพยายามอย่างเหมาะสม ฉันพยายามติดต่อบุคคลนี้โดยค้นหาเขาใน LinkedIn และ Google เท่านั้นจึงพบคนที่ชื่อ วันเกิด และที่อยู่เหมือนกัน ถูกตัดสินว่ามีความผิดในปี 2021 ในคดีอาชญากรรมที่ค่อนข้างร้ายแรงและกำลังให้เวลา ดังนั้น ฉันจะไม่ละสายตาจากเอกสารอายุ 7 ขวบของเขาที่เผยแพร่บนอินเทอร์เน็ต)

ฉันคิดว่าในช่วง 10 ปีที่ผ่านมาผู้คนจะมีอุปกรณ์ที่ดีกว่าและมีเครื่องมือที่ดีกว่าในการล็อคเนื้อหาของพวกเขาและแบ่งปันเฉพาะสิ่งที่ควรแบ่งปัน ฉันผิดไป. เหตุใดจึงต้องกังวลอีก 10 ปีต่อมาที่จะทำกิจกรรมนี้ซ้ำ เพื่อความสนุกสนานและความรู้ เป็นเวลาไม่กี่ปีแล้วที่ฉันได้เขียนโค้ดจำนวนมาก ดังนั้นฉันจึงต้องการทบทวนและฝึกฝนทักษะบางอย่าง

คุณจะดูไฟล์ของ Bucket ได้อย่างไร?

อันดับแรก ฉันต้องการระบุบัคเก็ต S3 ที่มีอยู่ซึ่งอาจมีอยู่ในภูมิภาค AWS เฉพาะ (us-east, us-west เป็นต้น) ถ้าฉันมีชื่อที่ถูกต้องสำหรับบัคเก็ต ฉันสามารถลองใช้ในเว็บเบราว์เซอร์และ ดูว่ามันแสดงรายการเนื้อหาของถังหรือไม่ ไม่ได้หมายความว่าไฟล์เหล่านั้นจะดูได้ แต่อย่างน้อยให้ฉันดูเส้นทางไฟล์สำหรับการตรวจสอบไฟล์เหล่านั้นในอนาคต

ตัวอย่างเช่น หากบัคเก็ตชื่อ “MyObviouslyFakeBucket” สามารถดูได้แบบสาธารณะและอยู่ในภูมิภาค AWS “US East 1” คุณอาจเห็นเนื้อหาในเว็บเบราว์เซอร์ของคุณโดยไปที่ https://myobviouslyfakebucket.s3.us-east-1 amazonaws.com/

สิ่งนี้จะส่งกลับรายการที่คล้ายกับรูปภาพที่แก้ไขบางส่วนต่อไปนี้

ไฟล์ที่อยู่ในบัคเก็ต myobviouslyfakebucket S3

ในเอกสาร XML ที่แสดงเป็นผลลัพธ์ คุณจะเห็นรายการไฟล์ภายใต้แท็ก "เนื้อหา" แต่ละรายการ สำหรับแต่ละโหนด "เนื้อหา" จะมีโหนด
"คีย์" ที่แสดงเส้นทางไฟล์และชื่อของแต่ละไฟล์ ดังนั้นสำหรับไฟล์ “interest-text-file.txt” คุณอาจทดสอบการเข้าถึงไฟล์ได้โดยการต่อท้ายพาธต่อท้าย URL ที่ฝากข้อมูลดังต่อไปนี้:

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

หากสามารถดูไฟล์ได้ ไฟล์นั้นจะเปิดขึ้นในเบราว์เซอร์หรือทริกเกอร์การดาวน์โหลดอัตโนมัติ (ขึ้นอยู่กับประเภทไฟล์และเบราว์เซอร์ของคุณ) หากคุณไม่มีสิทธิ์เข้าถึง คุณจะเห็นผลลัพธ์ XML ซึ่งแสดงข้อความ "Access Denied"

แม้จะมีความพยายามอย่างเต็มที่ของ 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 เป็น v1 และเพียงพอแล้วที่จะเปลี่ยนแปลง ซึ่งฉันไม่ต้องการให้ช่วงการเรียนรู้มาทำให้ความคืบหน้าของฉันล่าช้า ฉันยังสามารถหลีกเลี่ยงความจำเป็นในการตั้งค่าข้อมูลรับรอง AWS เพื่อใช้ SDK และข้อผิดพลาดเฉพาะ SDK หรือความผิดปกติใดๆ ที่เกิดขึ้นระหว่างการทดสอบ ง่าย ๆ เข้าไว้.

ฉันเริ่มต้นด้วยไฟล์พจนานุกรมที่มีอยู่จากโปรเจ็กต์ส่วนตัวก่อนหน้านี้ นี่เป็นไฟล์ข้อความธรรมดาที่มีหนึ่งคำต่อบรรทัด มีอยู่ช่วงหนึ่งที่ฉันแยกไฟล์ออกเป็น 8 หรือ 10 ไฟล์โดยแต่ละไฟล์มีรายการ 1-3 ตัวอักษรขึ้นอยู่กับจำนวนรายการ สิ่งนี้ทำให้ฉันสามารถประมวลผลรายการจำนวนน้อยลงในแต่ละครั้งได้ง่ายขึ้น คุณสามารถค้นหาไฟล์พจนานุกรมทางออนไลน์ได้เนื่องจากมีอยู่มากมาย

ฉันร่างขั้นตอนที่จำเป็นในการเขียนโปรแกรมลงบนกระดาษโน้ต 2 แผ่น พวกเขามีดังนี้:

  • แยกไฟล์พจนานุกรมเพื่อดึงแต่ละรายการคำ
  • สำหรับแต่ละคำในรายการ ให้สร้าง URL เพื่อตรวจสอบโดยใช้คำนั้นเป็นชื่อบัคเก็ตและภูมิภาค AWS (ตอนนี้ฮาร์ดโค้ดเป็น “US East 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
}

ดำเนินการ GET

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 รูปภาพนับล้าน ไฟล์บันทึกจำนวนนับไม่ถ้วน และอื่นๆ อีกมากมาย

ฉันได้ลบที่เก็บข้อมูลการทดสอบ "myobviouslyfakebucket" แล้ว ดังนั้นอย่าลังเลที่จะอ้างสิทธิ์ชื่อหากคุณต้องการ ในสองสามส่วนถัดไปของชุดบทความนี้ ฉันจะเน้นขั้นตอนเพิ่มเติมเพื่อปรับปรุงโซลูชันนี้ เช่น:

  • การจัดการและจัดเก็บรหัสตอบกลับสำหรับที่เก็บข้อมูลนอกเหนือจาก 200 (ตกลง) และความหมายและสิ่งที่คุณสามารถทำได้กับข้อมูลนั้น
  • ใช้รายชื่อบัคเก็ตที่ถูกต้องเพื่อดูว่าคุณสามารถระบุรายการไฟล์ในบัคเก็ตนั้นได้หรือไม่
  • การแยกรายการไฟล์บัคเก็ตเพื่อบันทึกพาธและชื่อของแต่ละไฟล์
  • กรองไฟล์ตามนามสกุลไฟล์เพื่อละเว้นเสียงรบกวนที่ไม่ต้องการ
  • ผลลัพธ์ไฟล์การแบ่งหน้าสำหรับบัคเก็ต S3 ที่มีไฟล์มากกว่า 1,000 ไฟล์
  • การตรวจสอบรายการไฟล์เพื่อดูว่าแต่ละไฟล์สามารถดาวน์โหลดได้หรือไม่