เมื่อไม่กี่วันก่อน ฉันเจอบริการที่ตรวจสอบลายเซ็นของคำขอทางฝั่งเซิร์ฟเวอร์ เป็นคาสิโนออนไลน์เล็กๆ แห่งหนึ่งที่ตรวจสอบค่าที่ผู้ใช้ส่งมาจากเบราว์เซอร์สำหรับคำขอทุกคำขอ ไม่ว่าคุณจะทำอะไรในคาสิโน: วางเดิมพันหรือฝากเงิน พารามิเตอร์เพิ่มเติมในคำขอแต่ละคำขอคือค่า "เครื่องหมาย" ซึ่งประกอบด้วยชุดอักขระที่ดูเหมือนสุ่ม ไม่สามารถส่งคำขอได้หากไม่มีค่านี้ เว็บไซต์ส่งข้อผิดพลาดกลับมา ซึ่งทำให้ฉันไม่สามารถส่งคำขอที่กำหนดเองได้
หากไม่นับค่านี้ ฉันคงออกจากเว็บไซต์ไปแล้วและไม่คิดถึงมันอีกเลย แต่ถึงแม้จะมีอุปสรรคมากมาย แต่สิ่งที่ทำให้ฉันตื่นเต้นไม่ใช่ความรู้สึกที่ได้กำไรอย่างรวดเร็ว แต่เป็นความสนใจในการค้นคว้าและความท้าทายที่คาสิโนมอบให้ฉันด้วยการป้องกันความโง่เขลา
ไม่ว่านักพัฒนาจะคิดไว้ว่าจะเพิ่มพารามิเตอร์นี้เพื่อจุดประสงค์ใด ฉันคิดว่ามันเป็นการเสียเวลาเปล่า เพราะลายเซ็นนั้นสร้างขึ้นบนฝั่งไคลเอ็นต์เอง และการดำเนินการใดๆ บนฝั่งไคลเอ็นต์ก็สามารถย้อนกลับวิศวกรรมได้
ในบทความนี้ ฉันจะพูดถึงวิธีที่ฉันจัดการเพื่อ:
บทความนี้จะสอนคุณถึงวิธีการประหยัดเวลาอันมีค่าและปฏิเสธโซลูชันที่ไร้ประโยชน์หากคุณเป็นนักพัฒนาที่สนใจทำโปรเจ็กต์ที่ปลอดภัย และหากคุณเป็นผู้ทดสอบการเจาะระบบ หลังจากอ่านบทความนี้แล้ว คุณจะได้เรียนรู้บทเรียนที่มีประโยชน์บางประการเกี่ยวกับการดีบัก รวมถึงการเขียนโปรแกรมส่วนขยายของคุณเองสำหรับมีดสวิสแห่งความปลอดภัย กล่าวโดยสรุป ทุกคนต่างก็มีด้านดี
มาเข้าเรื่องกันเลยดีกว่า
ดังนั้นบริการนี้จึงเป็นคาสิโนออนไลน์ที่มีเกมคลาสสิกชุดหนึ่ง:
การโต้ตอบกับเซิร์ฟเวอร์จะทำงานโดยอิงตามคำขอ HTTP ไม่ว่าคุณจะเลือกเกมใด คำขอ POST ทุกคำขอไปยังเซิร์ฟเวอร์จะต้องได้รับการลงนาม มิฉะนั้น เซิร์ฟเวอร์จะสร้างข้อผิดพลาด คำขอลงนามในแต่ละเกมทำงานบนหลักการเดียวกัน ฉันจะใช้เกมเดียวในการตรวจสอบเพื่อไม่ต้องทำงานเดียวกันสองครั้ง
แล้วผมจะไปเล่นเกมที่ชื่อว่า Dragon Dungeon
แก่นแท้ของเกมนี้คือการเลือกประตูในปราสาทตามลำดับในบทบาทของอัศวิน ด้านหลังประตูแต่ละบานจะมีสมบัติหรือมังกรซ่อนอยู่ หากผู้เล่นพบมังกรอยู่หลังประตู เกมจะหยุดลงและผู้เล่นจะเสียเงิน หากพบสมบัติ จำนวนเดิมพันเริ่มต้นจะเพิ่มขึ้นและเกมจะดำเนินต่อไปจนกว่าผู้เล่นจะชนะ แพ้ หรือผ่านทุกด่าน
ก่อนที่จะเริ่มเกมผู้เล่นจะต้องระบุจำนวนเงินเดิมพันและจำนวนมังกร
ฉันใส่ตัวเลข 10 เป็นผลรวม ปล่อยมังกรหนึ่งตัวไว้แล้วดูคำขอที่จะถูกส่งไป ซึ่งสามารถทำได้จากเครื่องมือสำหรับนักพัฒนาในเบราว์เซอร์ใดก็ได้ ใน Chromium แท็บเครือข่ายจะรับผิดชอบในส่วนนี้
ที่นี่คุณจะเห็นว่าคำขอดังกล่าวถูกส่งไปยังจุดสิ้นสุด /srv/api/v1/dungeon
แท็บ Payload จะแสดงเนื้อหาคำขอในรูปแบบ JSON
พารามิเตอร์สองตัวแรกนั้นชัดเจน - ฉันเลือกจาก UI ส่วนพารามิเตอร์สุดท้าย ซึ่งคุณอาจเดาได้ คือ timestamp
หรือเวลาที่ผ่านไปตั้งแต่วันที่ 1 มกราคม พ.ศ. 2513 โดยมีความแม่นยำของ Javascript ทั่วไปที่ระดับมิลลิวินาที
นั่นทำให้เหลือพารามิเตอร์ที่ยังไม่ได้แก้ไขหนึ่งตัว และนั่นก็คือลายเซ็นนั่นเอง เพื่อทำความเข้าใจว่าลายเซ็นนั้นถูกสร้างขึ้นมาอย่างไร ฉันจึงไปที่แท็บ Sources ซึ่งจะมีทรัพยากรทั้งหมดของบริการที่เบราว์เซอร์โหลดขึ้นมา รวมถึง Javascript ซึ่งรับผิดชอบตรรกะทั้งหมดของส่วนไคลเอนต์ของไซต์
การจะเข้าใจโค้ดนี้ไม่ใช่เรื่องง่ายเลย เพราะโค้ดถูกย่อขนาดลงแล้ว คุณสามารถลองถอดรหัสทั้งหมดได้ แต่อย่างไรก็ตาม โค้ดนี้ใช้เวลานานและน่าเบื่อมาก (เมื่อพิจารณาจากจำนวนโค้ดต้นฉบับ) ฉันไม่พร้อมที่จะทำ
ตัวเลือกที่สองซึ่งง่ายกว่าคือค้นหาส่วนที่จำเป็นของโค้ดโดยใช้คีย์เวิร์ดและใช้ดีบักเกอร์ นั่นคือสิ่งที่ฉันจะทำ เพราะฉันไม่จำเป็นต้องรู้ว่าไซต์ทั้งหมดทำงานอย่างไร ฉันแค่ต้องรู้ว่าลายเซ็นถูกสร้างขึ้นมาอย่างไร
ดังนั้นในการค้นหาส่วนของโค้ดที่รับผิดชอบในการสร้างโค้ด คุณสามารถเปิดการค้นหาในแหล่งข้อมูลทั้งหมดได้โดยใช้แป้น CTRL+SHIFT+F
ร่วมกันและค้นหาการกำหนดค่าให้กับคีย์ sign
ที่ส่งมาในคำขอ
โชคดีที่มีแมตช์เดียวซึ่งหมายความว่าฉันกำลังอยู่ในเส้นทางที่ถูกต้อง
หากคุณคลิกที่การจับคู่ คุณจะเข้าถึงส่วนโค้ดที่สร้างลายเซ็นได้ โค้ดถูกทำให้คลุมเครือเช่นเดิม ดังนั้นจึงยังคงอ่านยากอยู่
ตรงข้ามกับบรรทัดโค้ด ฉันใส่จุดพัก รีเฟรชหน้า และสร้างการเสนอราคาใหม่ใน “dragons” ตอนนี้สคริปต์จะหยุดทำงานพอดีในช่วงเวลาของการสร้างลายเซ็น และคุณสามารถดูสถานะของตัวแปรบางตัวได้
ฟังก์ชันที่เรียกใช้ประกอบด้วยตัวอักษรหนึ่งตัว รวมถึงตัวแปรด้วย - แต่ไม่มีปัญหา คุณสามารถไปที่คอนโซลและแสดงค่าของแต่ละตัวได้ สถานการณ์เริ่มชัดเจนขึ้น
ค่าแรกที่ฉันส่งออกคือค่าของตัวแปร H
ซึ่งเป็นฟังก์ชัน คุณสามารถคลิกที่ค่าดังกล่าวจากคอนโซลแล้วเลื่อนไปยังตำแหน่งที่ประกาศไว้ในโค้ด ด้านล่างนี้คือรายการ
นี่คือโค้ดตัวอย่างขนาดใหญ่ที่ฉันเห็นเบาะแส - SHA256 นี่คืออัลกอริทึมแฮช คุณจะเห็นได้ว่ามีการส่งพารามิเตอร์สองตัวไปยังฟังก์ชัน ซึ่งบ่งบอกว่านี่อาจไม่ใช่แค่ SHA256 แต่เป็น HMAC SHA256 ที่มีความลับ
อาจเป็นตัวแปรที่ถูกส่งมาที่นี่ (ส่งออกไปยังคอนโซลด้วย):
10;1;6693a87bbd94061678473bfb;1732817300080;gRdVWfmU-YR_RCuSkWFLCUTly_GZfDx3KEM8
- โดยตรงค่าที่การดำเนินการ HMAC SHA256 ถูกนำไปใช้31754cff-be0f-446f-9067-4cd827ba8707
เป็นค่าคงที่คงที่ซึ่งทำหน้าที่เป็นความลับ
เพื่อให้แน่ใจในเรื่องนี้ ฉันจึงเรียกใช้ฟังก์ชันและรับลายเซ็นที่สันนิษฐานไว้
ตอนนี้ฉันไปที่ไซต์ที่นับ HMAC SHA256 และส่งค่าเข้าไป
และเปรียบเทียบกับอันที่ส่งมาในคำขอตอนที่ฉันยื่นประมูล
ผลลัพธ์เหมือนกัน ซึ่งหมายความว่าการเดาของฉันถูกต้อง - จริงๆ แล้วใช้ HMAC SHA256 พร้อมข้อมูลลับคงที่ ซึ่งส่งสตริงที่สร้างขึ้นเป็นพิเศษพร้อมอัตรา จำนวนมังกร และพารามิเตอร์อื่นๆ ซึ่งฉันจะเล่าให้คุณฟังในตอนต่อไปของบทความ
อัลกอริทึมนั้นค่อนข้างเรียบง่ายและตรงไปตรงมา แต่ก็ยังไม่เพียงพอ หากเป้าหมายภายในโครงการงานของการทดสอบการเจาะระบบเพื่อค้นหาช่องโหว่ ฉันจะต้องเรียนรู้วิธีส่งแบบสอบถามของตัวเองโดยใช้ Burp Suite
และสิ่งนี้ต้องการระบบอัตโนมัติอย่างแน่นอน ซึ่งเป็นสิ่งที่ฉันจะพูดถึงตอนนี้
ฉันได้คิดอัลกอริทึมการสร้างลายเซ็นแล้ว ตอนนี้ถึงเวลาเรียนรู้วิธีสร้างอัลกอริทึมโดยอัตโนมัติเพื่อแยกสิ่งที่ไม่จำเป็นทั้งหมดออกไปเมื่อส่งคำขอ
คุณสามารถส่งคำขอโดยใช้ ZAP, Caido, Burp Suite และเครื่องมือ pentest อื่นๆ ได้ บทความนี้จะเน้นที่ Burp Suite เนื่องจากฉันพบว่าเป็นเครื่องมือที่ใช้งานง่ายที่สุดและเกือบจะสมบูรณ์แบบที่สุด คุณสามารถ ดาวน์โหลด Community Edition ได้ฟรีจากเว็บไซต์อย่างเป็นทางการ ซึ่งเพียงพอสำหรับการทดลองทั้งหมด
Burp Suite ไม่ทราบวิธีสร้าง HMAC SHA256 ดังนั้น หากต้องการทำเช่นนี้ คุณสามารถใช้ส่วนขยายที่เสริมฟังก์ชันการทำงานของ Burp Suite ได้
ส่วนขยายเหล่านี้ถูกสร้างโดยสมาชิกชุมชนและโดยนักพัฒนาเอง ส่วนขยายเหล่านี้จะถูกแจกจ่ายผ่าน BApp Store, Github หรือคลังเก็บซอร์สโค้ดอื่นๆ ที่มีให้ใช้งานฟรี
มีสองทางเลือกสำหรับคุณ:
เส้นทางแต่ละเส้นทางนี้มีข้อดีและข้อเสีย ฉันจะแสดงให้คุณเห็นทั้งสองทาง
วิธีการที่ใช้ส่วนขยายสำเร็จรูปนั้นง่ายที่สุด โดยดาวน์โหลดจาก BApp Store และใช้ฟีเจอร์ต่างๆ เพื่อสร้างค่าสำหรับพารามิเตอร์ sign
ส่วนขยายที่ฉันใช้เรียกว่า Hackvertor ซึ่งช่วยให้คุณสามารถใช้งานไวยากรณ์แบบ XML ได้ เพื่อให้สามารถเข้ารหัส/ถอดรหัส เข้ารหัสลับ/ถอดรหัส และแฮชข้อมูลต่างๆ ได้อย่างไดนามิก
เพื่อติดตั้ง Burp จำเป็นต้องมี:
ไปที่แท็บส่วนขยาย
พิมพ์ Hackvertor ในการค้นหา
เลือกส่วนขยายที่พบในรายการ
คลิกติดตั้ง
เมื่อติดตั้งแล้ว จะมีแท็บที่มีชื่อเดียวกันปรากฏขึ้นใน Burp คุณสามารถเข้าไปที่แท็บนั้นและประเมินความสามารถของส่วนขยายและจำนวนแท็กที่มีอยู่ โดยแต่ละแท็กสามารถรวมเข้าด้วยกันได้
เพื่อเป็นตัวอย่าง คุณสามารถเข้ารหัสบางสิ่งด้วย AES แบบสมมาตรโดยใช้แท็ก <@aes_encrypt('supersecret12356','AES/ECB/PKCS5PADDING')>MySuperSecretText<@/aes_encrypt>
ความลับและอัลกอริทึมอยู่ในวงเล็บ และระหว่างแท็กคือข้อความที่ต้องเข้ารหัส แท็กใดๆ ก็สามารถใช้ได้ใน Repeater, Intruder และเครื่องมือ Burp Suite ในตัวอื่นๆ
ด้วยความช่วยเหลือของส่วนขยาย Hackvertor คุณสามารถอธิบายได้ว่าควรสร้างลายเซ็นในระดับแท็กอย่างไร ฉันจะอธิบายโดยใช้ตัวอย่างคำขอจริง
ดังนั้น ฉันจึงเดิมพันใน Dragon Dungeon สกัดกั้นคำขอเดียวกันที่ฉันสกัดกั้นไว้ในตอนต้นบทความนี้ด้วย Intercept Proxy และเน้นไปที่ Repeater เพื่อที่จะแก้ไขและส่งใหม่อีกครั้ง
ตอนนี้ แทนที่จะใช้ค่า ae04afe621864f569022347f1d1adcaa3f11bebec2116d49c4539ae1d2c825fc
เราต้องแทนที่อัลกอริทึมเพื่อสร้าง HMAC SHA256 โดยใช้แท็กที่ Hackvertor ให้มา
Формула генерации у меня получилась следующая <@hmac_sha256('31754cff-be0f-446f-9067-4cd827ba8707')>10;1;6693a87bbd94061678473bfb;<@timestamp/>000;MDWpmNV9-j8tKbk-evbVLtwMsMjKwQy5YEs4<@/hmac_sha256>
-
พิจารณาพารามิเตอร์ทั้งหมด:
10
- จำนวนเงินเดิมพัน1
- จำนวนมังกร6693a87bbd94061678473bfb
- รหัสผู้ใช้เฉพาะจากฐานข้อมูล MongoDB ฉันเห็นรหัสนี้ขณะวิเคราะห์ลายเซ็นจากเบราว์เซอร์ แต่ฉันไม่ได้เขียนถึงรหัสนี้ในตอนนั้น ฉันสามารถค้นหารหัสนี้ได้โดยค้นหาผ่านเนื้อหาของแบบสอบถามใน Burp Suite รหัสนี้กลับมาจากแบบสอบถามปลายทาง /srv/api/v1/profile/me
<@timestamp/>000
- การสร้างค่าประทับเวลา โดยเลขศูนย์สามตัวสุดท้ายจะปรับเวลาให้ละเอียดเป็นมิลลิวินาทีMDWpmNV9-j8tKbk-evbVLtwMsMjKwQy5YEs4
- โทเค็น CSRF ซึ่งส่งคืนจากจุดสิ้นสุด /srv/api/v1/csrf
และแทนที่ในแต่ละคำขอในส่วนหัว X-Xsrf-Token
<@hmac_sha256('31754cff-be0f-446f-9067-4cd827ba8707')>
และ <@/hmac_sha256>
- แท็กเปิดและปิดสำหรับสร้าง HMAC SHA256 จากค่าแทนที่ด้วยความลับเป็นค่าคงที่ 31754cff-be0f-446f-9067-4cd827ba8707
สิ่งสำคัญที่ต้องทราบ: พารามิเตอร์จะต้องเชื่อมต่อถึงกันผ่าน ;
ในลำดับที่เข้มงวด มิฉะนั้น ลายเซ็นจะถูกสร้างขึ้นไม่ถูกต้อง - เช่นเดียวกับในภาพหน้าจอนี้ที่ฉันได้สลับอัตราและจำนวนมังกร
นั่นคือที่ที่ความมหัศจรรย์ทั้งหมดอยู่
ตอนนี้ฉันสร้างแบบสอบถามที่ถูกต้อง โดยฉันระบุพารามิเตอร์ในลำดับที่ถูกต้อง และรับข้อมูลว่าทุกอย่างสำเร็จและเกมได้เริ่มต้นแล้ว นั่นหมายความว่า Hackvertor สร้างลายเซ็นแทนสูตร แทนที่ในแบบสอบถาม และทุกอย่างก็ทำงานได้
อย่างไรก็ตาม วิธีนี้มีข้อเสียที่สำคัญ นั่นคือ คุณไม่สามารถกำจัดงานด้วยตนเองได้หมดสิ้น ทุกครั้งที่คุณเปลี่ยนอัตราหรือจำนวนมังกรใน JSON คุณต้องเปลี่ยนในลายเซ็นเองเพื่อให้ตรงกัน
นอกจากนี้ หากคุณส่งคำขอใหม่จากแท็บ Proxy ไปยัง Intruder หรือ Repeater คุณต้องเขียนสูตรใหม่ ซึ่งไม่สะดวกเลยเมื่อคุณต้องใช้งานแท็บต่างๆ มากมายสำหรับกรณีทดสอบที่แตกต่างกัน
สูตรนี้ยังล้มเหลวในการสืบค้นอื่นๆ ที่ใช้พารามิเตอร์อื่นด้วย
ฉันจึงตัดสินใจเขียนส่วนขยายของตัวเองเพื่อเอาชนะข้อเสียเหล่านี้
คุณสามารถเขียนส่วนขยายสำหรับ Burp Suite ในภาษา Java และ Python ได้ ฉันจะใช้ภาษาการเขียนโปรแกรมที่สองเนื่องจากง่ายกว่าและมองเห็นได้ชัดเจนกว่า แต่คุณต้องเตรียมตัวล่วงหน้า: ก่อนอื่นคุณต้องดาวน์โหลด Jython Standalone จากเว็บไซต์อย่างเป็นทางการ จากนั้นจึงไปยังเส้นทางไปยังไฟล์ที่ดาวน์โหลดมาในการตั้งค่า Burp Suite
หลังจากนั้นคุณต้องสร้างไฟล์ที่มีโค้ดต้นฉบับและนามสกุล *.py
ฉันมีแผนงานที่กำหนดตรรกะพื้นฐานแล้ว นี่คือเนื้อหา:
ทุกสิ่งทุกอย่างนั้นเรียบง่ายและตรงไปตรงมาตามสัญชาตญาณ:
getActionName
- วิธีการนี้ส่งคืนชื่อของการดำเนินการที่ส่วนขยายจะดำเนินการ ส่วนขยายจะเพิ่มกฎการจัดการเซสชันที่สามารถนำไปใช้กับคำขอใดๆ ได้อย่างยืดหยุ่น แต่จะอธิบายเพิ่มเติมในภายหลัง สิ่งสำคัญคือต้องทราบว่าชื่อนี้อาจแตกต่างจากชื่อส่วนขยาย และสามารถเลือกได้จากอินเทอร์เฟซperformAction
- ตรรกะของกฎนั้นเอง ซึ่งจะนำไปใช้กับคำขอที่เลือก จะถูกระบุไว้ที่นี่
ทั้งสองวิธีได้รับการประกาศตามอินเทอร์เฟซ ISessionHandlingAction
ตอนนี้ไปที่อินเทอร์เฟซ IBurpExtender ซึ่งจะประกาศเมธอด registerExtenderCallbacks
ที่จำเป็นเพียงเมธอดเดียว ซึ่งจะดำเนินการทันทีหลังจากโหลดส่วนขยาย และจำเป็นสำหรับการทำงานทั้งหมด
นี่คือที่ที่การกำหนดค่าพื้นฐานทำ:
callbacks.setExtensionName(EXTENSION_NAME)
- ลงทะเบียนส่วนขยายปัจจุบันเป็นการดำเนินการเพื่อจัดการเซสชันsys.stdout = callbacks.getStdout()
- เปลี่ยนเส้นทางเอาท์พุตมาตรฐาน (stdout) ไปที่หน้าต่างเอาท์พุตของ Burp Suite (แผง "ส่วนขยาย")self.stderr = PrintWriter(callbacks.getStdout(), True)
- สร้างสตรีมสำหรับแสดงข้อผิดพลาดself.stdout.println(EXTENSION_NAME)
- พิมพ์ชื่อส่วนขยายใน Burp Suiteself.callbacks = callbacks
- บันทึกออบเจ็กต์คอลแบ็กเป็นแอตทริบิวต์ของ self ซึ่งจำเป็นสำหรับการใช้งาน Burp Suite API ในส่วนอื่นๆ ของโค้ดส่วนขยายในภายหลังself.helpers = callbacks.getHelpers()
- ยังรับวิธีการที่มีประโยชน์ที่จะต้องใช้เมื่อส่วนขยายทำงาน
เมื่อเตรียมการเบื้องต้นเรียบร้อยแล้ว ก็เสร็จเรียบร้อย ตอนนี้คุณก็สามารถโหลดส่วนขยายและตรวจสอบให้แน่ใจว่าใช้งานได้ โดยไปที่แท็บส่วนขยายแล้วคลิกเพิ่ม
ในหน้าต่างที่ปรากฏขึ้นให้ระบุ
และคลิกถัดไป
หากไฟล์ซอร์สโค้ดได้รับการจัดรูปแบบอย่างถูกต้อง ไม่ควรมีข้อผิดพลาดเกิดขึ้น และแท็บผลลัพธ์จะแสดงชื่อส่วนขยาย ซึ่งหมายความว่าทุกอย่างทำงานได้ดี
ส่วนขยายโหลดและใช้งานได้ แต่สิ่งที่โหลดมาเป็นเพียงแรปเปอร์ที่ไม่มีตรรกะใดๆ ตอนนี้ฉันต้องการโค้ดโดยตรงเพื่อลงนามในคำขอ ฉันได้เขียนไว้แล้วและแสดงไว้ในภาพหน้าจอด้านล่าง
วิธีการที่ส่วนขยายทั้งหมดทำงานคือ ก่อนที่คำขอจะถูกส่งไปยังเซิร์ฟเวอร์ คำขอจะถูกปรับเปลี่ยนโดยส่วนขยายของฉัน
ก่อนอื่นผมขอรับคำขอให้ส่วนขยายสกัดกั้น และได้รับอัตราและจำนวนมังกรจากตัวมัน
json_body = json.loads(message_body) amount_currency = json_body["amountCurrency"] dragons = json_body["dragons"]
จากนั้นฉันอ่าน Timestamp ปัจจุบันและรับโทเค็น CSRF จากส่วนหัวที่สอดคล้องกัน
currentTime = str(time.time()).split('.')[0]+'100' xcsrf_token = None for header in headers: if header.startswith("X-Xsrf-Token"): xcsrf_token = header.split(":")[1].strip()
ถัดไปคำขอจะได้รับการลงนามโดยใช้ HMAC SHA256
hmac_sign = hmac_sha256(key, message=";".join([str(amount_currency), str(dragons), user_id, currentTime, xcsrf_token]))
ฟังก์ชั่นและค่าคงที่ที่ระบุความลับและ ID ผู้ใช้ได้รับการประกาศไว้ล่วงหน้าที่ด้านบน
def hmac_sha256(key, message): return hmac.new( key.encode("utf-8"), message.encode("utf-8"), hashlib.sha256 ).hexdigest() key = "434528cb-662f-484d-bda9-1f080b861392" user_id = "zex2q6cyc4ba3gvkyex5f80m"
จากนั้นค่าจะถูกเขียนลงในเนื้อหาคำขอและแปลงเป็น JSON
json_body["sign"] = hmac_sign json_body["t"] = currentTime message_body = json.dumps(json_body)
ขั้นตอนสุดท้ายคือการสร้างคำขอที่ลงนามและแก้ไขแล้วส่งไปที่
httpRequest = self.helpers.buildHttpMessage(get_final_headers, message_body) baseRequestResponse.setRequest(httpRequest)
เท่านี้ก็เขียนโค้ดต้นฉบับเสร็จแล้ว ตอนนี้คุณสามารถโหลดส่วนขยายใหม่ใน Burp Suite ได้ (ควรทำหลังจากปรับเปลี่ยนสคริปต์แต่ละครั้ง) และตรวจสอบให้แน่ใจว่าทุกอย่างทำงานได้
ก่อนอื่นคุณต้องเพิ่มกฎใหม่สำหรับการประมวลผลคำขอ โดยไปที่การตั้งค่าในส่วนเซสชัน ที่นี่คุณจะพบกฎต่างๆ ทั้งหมดที่เกิดขึ้นเมื่อส่งคำขอ
คลิกเพิ่มเพื่อเพิ่มส่วนขยายที่จะทำงานกับคำขอบางประเภท
ในหน้าต่างที่ปรากฏขึ้น ฉันปล่อยทุกอย่างไว้ตามเดิมและเลือกเพิ่มในการดำเนินการกฎ
รายการดร็อปดาวน์จะปรากฏขึ้น ให้เลือกเรียกใช้ส่วนขยาย Burp ในนั้น
และระบุส่วนขยายที่จะเรียกใช้เมื่อส่งคำขอ ฉันมีส่วนขยายนั้นอยู่หนึ่งตัว ชื่อว่า Burp Extension
หลังจากเลือกส่วนขยายแล้ว ฉันคลิกตกลง และไปที่แท็บขอบเขต ซึ่งฉันระบุ:
ขอบเขตเครื่องมือ - Repeater (ส่วนขยายควรจะทริกเกอร์เมื่อฉันส่งคำขอด้วยตนเองผ่าน Repeater)
ขอบเขต URL - รวม URL ทั้งหมด (เพื่อให้ทำงานกับคำขอทั้งหมดที่ฉันส่ง)
มันควรจะทำงานเหมือนในภาพหน้าจอด้านล่าง
หลังจากคลิกตกลง กฎส่วนขยายจะปรากฏในรายการทั่วไป
ในที่สุด คุณสามารถทดสอบทุกอย่างได้ในขณะใช้งานจริง! ตอนนี้คุณสามารถเปลี่ยนแปลงแบบสอบถามและดูว่าลายเซ็นจะอัปเดตแบบไดนามิกอย่างไร และแม้ว่าแบบสอบถามจะล้มเหลว แต่ก็เป็นเพราะฉันเลือกอัตราติดลบ ไม่ใช่เพราะมีบางอย่างผิดปกติกับลายเซ็น (ฉันแค่ไม่อยากเสียเงินเปล่า 😀) ส่วนขยายนี้ใช้งานได้และลายเซ็นจะถูกสร้างขึ้นอย่างถูกต้อง
ทุกอย่างก็ดี แต่มีปัญหาอยู่สามประการ:
เพื่อแก้ไขปัญหานี้ เราจะต้องเพิ่มคำขอเพิ่มเติมอีกสองรายการ ซึ่งสามารถทำได้โดยใช้ไลบรารี Burp Suite ในตัว แทนที่จะใช้ requests
ของบุคคลที่สาม
เพื่อดำเนินการนี้ ฉันได้ห่อตรรกะมาตรฐานบางส่วนไว้เพื่อทำให้การค้นหาสะดวกยิ่งขึ้น ผ่านวิธีมาตรฐานของ Burp การโต้ตอบกับการค้นหาจะทำในรูปแบบข้อความธรรมดา
def makeRequest(self, method="GET", path="/", headers=None, body=None): first_line = method + " " + path + " HTTP/1.1" headers[0] = first_line if body is None: body = "{}" http_message = self.helpers.buildHttpMessage(headers, body) return self.callbacks.makeHttpRequest(self.request_host, self.request_port, True, http_message)
และเพิ่มฟังก์ชัน 2 อย่างในการดึงข้อมูลที่ฉันต้องการคือ โทเค็น CSRF และ ID ผู้ใช้
def get_csrf_token(self, headers): response = self.makeRequest("GET", "/srv/api/v1/csrf", headers) message = self.helpers.analyzeRequest(response) raw_headers = str(message.getHeaders()) match = re.search(r'XSRF-TOKEN=([a-zA-Z0-9_-]+)', raw_headers) return match.group(1) def get_user_id(self, headers): raw_response = self.makeRequest("POST", "/srv/api/v1/profile/me", headers) response = self.helpers.bytesToString(raw_response) match = re.search(r'"_id":"([a-f0-9]{24})"', response) return match.group(1)
และโดยการอัพเดตโทเค็นเองในส่วนหัวที่ส่ง
def update_csrf(self, headers, token): for i, header in enumerate(headers): if header.startswith("X-Xsrf-Token:"): headers[i] = "X-Xsrf-Token: " + token return headers
ฟังก์ชันลายเซ็นมีลักษณะดังนี้ สิ่งสำคัญที่ต้องทราบคือ ฉันจะนำพารามิเตอร์ที่กำหนดเองทั้งหมดที่ส่งมาในคำขอ เพิ่ม user_id
มาตรฐาน currentTime
และ csrf_token
ลงท้ายพารามิเตอร์เหล่านั้น และลงนามทั้งหมดพร้อมกันโดยใช้ ;
เป็นตัวคั่น
def sign_body(self, json_body, user_id, currentTime, csrf_token): values = [] for key, value in json_body.items(): if key == "sign": break values.append(str(value)) values.extend([str(user_id), str(currentTime), str(csrf_token)]) return hmac_sha256(hmac_secret, message=";".join(values))
พื้นหลักลดลงเหลือเพียงไม่กี่บรรทัด:
OrderedDict
ซึ่งสร้างพจนานุกรมในลำดับที่เข้มงวด เนื่องจากการรักษาไว้ระหว่างการลงนามเป็นสิ่งสำคัญ csrf_token = self.get_csrf_token(headers) final_headers = self.update_csrf(final_headers, csrf_token) user_id = self.get_user_id(headers) currentTime = str(time.time()).split('.')[0]+'100' json_body = json.loads(message_body, object_pairs_hook=OrderedDict) sign = self.sign_body(json_body, user_id, currentTime, csrf_token) json_body["sign"] = sign json_body["t"] = currentTime message_body = json.dumps(json_body) httpRequest = self.helpers.buildHttpMessage(final_headers, message_body) baseRequestResponse.setRequest(httpRequest)
ภาพหน้าจอเพื่อความแน่ใจ
ตอนนี้ หากคุณไปที่เกมอื่นที่มีพารามิเตอร์ที่กำหนดเองเป็น 3 แทนที่จะเป็น 2 และส่งคำขอ คุณจะเห็นว่าคำขอจะถูกส่งสำเร็จ ซึ่งหมายความว่าส่วนขยายของฉันเป็นแบบสากลและใช้งานได้กับคำขอทั้งหมดแล้ว
ตัวอย่างการส่งคำขอเติมเงินเข้าบัญชี
ส่วนขยายเป็นส่วนสำคัญของ Burp Suite บ่อยครั้งที่บริการต่างๆ จะนำฟังก์ชันการใช้งานแบบกำหนดเองที่ไม่มีใครเขียนไว้ล่วงหน้าได้นอกจากคุณ ดังนั้น ไม่เพียงแต่ต้องดาวน์โหลดส่วนขยายสำเร็จรูปเท่านั้น แต่ยังต้องเขียนส่วนขยายของคุณเองด้วย ซึ่งเป็นสิ่งที่ฉันพยายามสอนคุณในบทความนี้
ตอนนี้พอแค่นี้ก่อน ปรับปรุงตัวเองและอย่าเจ็บป่วย
ลิงค์ไปที่ซอร์สโค้ดของส่วนขยาย: *คลิก*