ลองแล้วสำเร็จ เลยต้องมาเขียนโน๊ตไว้เตือนตัวเองซะหน่อย
HTTP Splitting
เรื่องของเรื่องก็คือ HTTP เนี่ย เป็น protocol ที่ใช้ส่งข้อมูล โดยใช้ระบบตัวหนังสือส่งเป็นหลัก ทั้งคำสั่งและข้อมูล
และใช้เครื่องหมายขึ้นบรรทัดใหม่เป็นตัวแบ่งคำสั่งต่างๆ
ดังนั้น ถ้าเราสามารถส่งข้อมูลไปที่เวปserver แล้วเมื่อwebserverส่งข้อมูลนั้นกลับมา คำสั่งที่แทรกอยู่บนนั้นก็จะหลอกเครื่องเป้าหมายให้ทำงานผิดพลาดได้หรือไม่
โจทย์อันนี้เลยเริ่มมาจากว่า ให้เรากรอกข้อมูลซึ่งเป็นภาษาลงไป เพื่อที่จะ redirect user ไปหาหน้าเวปที่ตรงกับภาษานั้น
ยกตัวอย่างเช่น ถ้าเรากรอก en (ภาษาอังกฤษ) ลงไป
หน้า redirect จะส่งผุ้ใช้ไปที่
ก็คือเอาคำว่า en ไปต่อท้าย redirect URL อย่างที่เห็น
มาเริ่มต้นเนื้อหากัน
Stage 1
ด่านแรกของโจทย์นี้คือ
ให้ทดลองส่งคำสั่งพวกนี้ไป เพื่อจำลองว่าเราสามารถแทรกคำสั่งHTTPลงไปในinputได้
ซึ่งในช่อง input เราจะใส่ไอ้นี่ไป
en Content-Length: 0 HTTP/1.1 200 OK Content-Type: text/html Content-Length: 30 <html>Hacked by anidear</html>
ชุดแรกหมายถึง
en คือเป็นinputปกติ คือเราจะตอบคำถามที่ทาง web application หน้านั้นถามเรา
Content-Length: 0 คือไม่มีข้อความอะไรต่อจากตรงนี้แล้วในrequest header
เพื่อที่จะบอกว่าหมดrequest headerแล้วด้วย
แต่เราดันเว้นว่างบรรทัดนึง แล้วแทรกข้อความresponseต่อเลย
โดยข้อความresponseมีเนื้อหาว่า
HTTP/1.1 200 OK :บอกว่าข้อความresponseนี้ใช้การส่งแบบHTTP version 1.1 และหน้าที่คุณร้องขอมีอยู่จริงและเรากำลังจะส่งข้อมูลให้
Content-Type: text/html :ข้อมูลต่อไปนี้เป็นtext/html
Content-Length: 30 :ข้อความเนื้อหาต่อไปนี้ยาว30ตัวอักษร
แล้วก็ตามด้วยข้อความที่เราอยากจะโชว์ขึ้นที่หน้า user (ซึ่งมีความยาว30ตัวอักษร อยากได้ยาวกว่านี้ก็แก้เลข30เอาเอง)
ปัญหาก็คือว่า การส่งคำสั่งพวกนี้ซึ่งมีเครื่องหมายขึ้นบรรทัดใหม่อยู่ มันไม่สามารถส่งเข้าไปในURLได้
ดังนั้นเราจึงต้องทำการแปลงให้มันอยู่ในรูปแบบของURIซะก่อน
ซึ่งจะใช้อะไรก็ได้ ตั้งแต่ javascript(คำสั่ง encodeURI('string')) หรือว่าเครื่องมืออื่นๆ
ในที่นี้(จากเฉลย) เขาแนะนำให้ใช้จากเวปนี้ http://yehg.net/encoding/ ซึ่งรวมวิธีการencodingไว้หลายแบบด้วย
โดยเมื่อกรอกข้อความที่ต้องการencodeลงไปแล้ว ให้กดปุ่ม encodeURIComponent ก็จะได้ผลออกมา
** สำหรับผู้ใช้ที่เป็นwindows เนื่องจากระบบของwindowsจะมองการขึ้นบรรทัดใหม่เป็น \r\n
ดังนั้นจึงจะต้องแปลงตัวอักษรขึ้นบรรทัดใหม่เป็น %0D%0A ด้วย
แทนที่จะเป็นแค่ \n หรือ %0A อย่างเดียวของบนLinux
ตรงนี้จะเพิ่มเองด้วยมือก็ได้ หรือถ้าใช้หน้านั้นให้เข้า Text FX, Convert, from %0A to %0D%0A
แปลงเป็น URI format แล้วจะได้เป็น
en%0AContent-Length%3A%200%0A%0AHTTP%2F1.1%20200%20OK%0AContent-Type%3A%20text%2Fhtml%0AContent-Length%3A%2030%0A%3Chtml%3EHacked%20by%20anidear%3C%2Fhtml%3E
ก็จะทำให้ได้ผลลัพธ์แบบนี้
ถึงตรงนี้จะเห็นว่าทุกอย่างมันรวมกันไปอยู่บรรทัดเดียว
แต่ว่าเวลาbrowserตีความ ก็จะแปลงข้อความตรงนี้ออกมาตีความ
แล้วก็จะเห็นว่าหน้านี้ไม่ต้องredirectแล้ว เพราะมีข้อความมาเรียบร้อยแล้วอยู่บ้างในตามที่เราได้ใส่เอาไว้ก่อนหน้า
Stage 2
ด่านสองของโจทย์นี้คือการทำ Cache Poisoning
นั่นคือว่า การโจมตีแบบนี้จะไม่ได้ผลอะไรเท่าไหร่ เพราะว่าเราต้องกรอกเองถึงจะได้เห็นเอง
หรือไม่ก็ต้องส่งURLเป็นparameterแบบยาวๆนั่น ก็จะลำบาก เพราะมันง่ายต่อผู้ใช้ในการสังเกตุURLยาวๆนั่น
แต่ cache poisoning เป็นการทำไว้ทีเดียวเลย
โดยอาศัยหลักการที่ว่า Web Cache (หรือ WebProxy) จะเช็คดูในresponse HTTP message ว่าหน้าเวปเวปนี้ถูกแก้ไขครั้งล่าสุดเมื่อไหร่
cache ก็จะเช็คข้อมูลของตัวเองว่าตัวเองมีข้อมูลที่เก่าหรือว่าใหม่แล้ว ถ้าcacheมีข้อมูลเก่าแล้ว (คือLast Modified เป็นวันที่ในอดีต) cache ก็จะเอาข้อมูลใหม่ทับลงไป ในทางตรงกันข้ามถ้าเกิดว่าข้อมูลของ cacheยังใหม่อยู่ cacheก็จะไม่มีการเรียกไปหน้าเวปใหม่ แต่จะใช้ข้อมูลที่ถูกเก็บเอาไว้ ทั้งนี้เพื่อที่จะประหยัดbandwidthการส่งข้อมูลลงไป เพราะไม่ต้องrequestไปหาserverใหม่ทุกครั้งที่ต้องการหน้านั้น(ที่ยังไม่ได้มีการแก้ไข)
ดังนั้น ถ้าเราเขียน Last Modified เป็นวันที่ในอนาคตล่ะ?
cacheก็จะมองว่า ข้อมูลนี้มันไม่เก่าซักทีน่ะสิ ก็จะทำให้ส่งข้อมูลเดิมให้กับผู้ใช้ตลอด
นี่แหละที่จะทำให้การattackด้วย HTTP Splitting นี่ส่งผลได้รุนแรงที่สุด
ดังนั้นเราก็จะเพิ่มบรรทัด Last-Modified: Mon, 1 Jan 2100 11:11:11 GMT
เอาไปศตวรรษหน้าไปเลย ฮ่าๆๆ
requestที่ต้องส่งไปก็จะเป็น
en Content-Length: 0 HTTP/1.1 200 OK Content-Type: text/html Last-Modified: Mon, 1 Jan 2100 11:11:11 GMT Content-Length: 30 <html>Hacked by anidear</html>
เมื่อแปลงเป็น URI แล้ว จะได้เป็น
en%0AContent-Length%3A%200%0A%0AHTTP%2F1.1%20200%20OK%0AContent-Type%3A%20text%2Fhtml%0ALast-Modified%3A%20Mon%2C%201%20Jan%202100%2011%3A11%3A11%20GMT%0AContent-Length%3A%2030%0A%3Chtml%3EHacked%20by%20anidear%3C%2Fhtml%3E
และแล้วก็จะได้ผลลัพธ์เป็นแบบนี้
และแล้วก็ทำให้ผ่านโจทย์นี้ไปได้ซักที เฮ้อ..
ขอได้รับความขอบคุณจาก
yehg.net ผู้ทำเฉลยดีๆให้ดู
OWASP ผู้สร้างwebgoat
และ Google Chrome สำหรับการดักจับHTTP packets
No comments:
Post a Comment