เรื่องเล็กๆ แต่ยิ่งใหญ่ ของ Database กับ Text Box


อัปเดท : 15 พฤษภาคม พ.ศ.2547 , แสดง : 41,777 , ความคิดเห็น : 7

การพัฒนาเวบไซต์ ไม่ว่าจะใช้ asp,asp.net,php,jsp หรือภาษาอื่น ๆ พัฒนาเวบแอบปลิเคชั่นร่วมกับฐานข้อมูล ต่าง ๆ โดยมีการแสดงผล และรับข้อมูลผ่าน FROM ที่จัดเตรียมไว้ มีเริ่องเล็ก ๆที่ควรใส่ใจซึ่งจะพูดถึงในบทความนี้คือ "การรับค่าจาก TextBox แล้วเก็บลงฐานข้อมูล หรือนำไปประมวลผลต่อ" มันมีตรงไหนที่ควรระวัง ควรใส่ใจ ? ที่เจอบ่อยมีอยู่ 2 แบบ ก็คือ HTML Syntax และ Query String(SQL) Syntax เนื่องจากมันมีผลกับการประมวลผล นอกจากนี้ยังมีผลต่อความมั่นคง(Security)ของข้อมูลด้วย โดยเฉพาะอย่างยิ่งตรง Query String(SQL) ซึ่งมันมีช่องโหว่นึงที่สามารถทำ SQL Injections คือเป็นการ Hack หรือเจาะระบบผ่าน SQL Command ได้

HTML Syntax

มาดู HTML Syntax ที่มีผลต่อการแสดงผลก่อนเช่น <hr>, <br>, <table> </table> ,<td></td> และอื่น ๆ (ก็ทุก Syntax อ่ะครับ) ลองคิดดูถ้าเราเขียนเวบขึ้นมาแล้วให้ผู้ใช้กรอกค่าผ่าน TextBox แล้วเก็บลงฐานข้อมูล จะเกิดอะไรขี้นถ้าผู้ใช้พิพพ์ HTML Syntax ลงมาโดยตั้งใจหรือไม่ก็ตาม หลังจาก Submit ผลที่เกิดก็คือข้อมูลนั้นก็จะเก็บลงฐานข้อมูลปรกติ ไม่มีอะไรผิดปรกติ แต่ก้าเราดึงข้อมูลที่ Submit แล้วนั้นมาแสดงผล ก็จะเห็นการเปลี่ยนแปลงหน้าตาเวบ ทั้งนี้หน้าตาเวบจะเปลี่ยนไปมากน้อยหรือไม่เปลี่ยนเลยขึ้นอยู่กับ HTML Syntax นั้น เช่น ถ้าผู้ใช้พิมพ์ "<hr" ตอนดึงฐานข้อมูลมาแสดงผล ก็จะเกิดแนวนอน 1 เส้น ถือว่ายังดีอยู่พอรับได้ แต่ถ้า ถ้าผู้ใช้พิมพ์ "</table" ล่ะ จะเกิดอะไรขึ้น ? ถ้าเวบหน้านั้นมีการใช้ตาราง <Table> Browser ก็จะตีความว่าสิ้นสุดตาราง ทั้งที่จริง ๆ แล้วยังไม่สิ้นสุด ทำให้การแสดงผลผิดเพี้ยนไปดังตัวอย่าง Code ด้านล่าง

<table border="1" >
<tr> <td colspan="2"><%=txtValue1%></td></tr>
<tr> <td><%=txtValue2%></td><td><%=txtValue3%></td></tr>
</table>

 

สมมุติ ค่าตัวแปร txtValue1 , txtValue2 , txtValue3 เป็นค่าที่ดึงจากจากฐานข้อมูลหรือค่าที่รับจาก TextBox ตรง ๆ ก็ได้

txtValue1="Hello</Table>"
txtValue2="
[email protected]"
txtValue3="15-05-47 12:23"


ตอนแสดงผลจะได้ Code ด้านล่าง

<table border="1" >
<tr> <td colspan="2">Hello</Table></td></tr>
<tr> <td>[email protected]</td><td>[email protected]</td></tr>
</table>

สังเกตุน่ะครับ ตรง </Table> ถ้าให้ Web Browser แสดงผลก็จะเพี้ยนทันทีซึ่งตรงนี้ต้องระวังน่ะครับ

แนวทางแก้ไข/ป้องกัน
ต้องแทนที่อักขระเช่น"<",">" หรือคอนโทรลโค๊ดอื่น ๆด้วย โค๊ดบางตัวก่อนโดยแทกโค๊ดตัวอย่างด้านล่าง ก่อน Submit ลงฐานข้อมูล

Value1= Request("Value1") ' ค่าที่รับมาจาก TextBox
Value1=Replace(Value1,chr(32),"&nbsp;")
Value1=Replace(Value1,chr(13,"<BR>"))
Value1=Replace(Value1,"<","&lt;")
Value1=Replace(Value1,">","&gt;") 'Value1 นำไปเก็บลงฐานข้อมูลได้
 

Query String Syntax

  
 

สำหรับ ปัญหาของ Query String Syntax ก็คล้าย ๆ กับ HTML แต่ปัญหาของ Query String Syntax จะอยู่ที่เครื่องหมาย" '" เกิดอะไรขึ้นถ้า ผู้ใช้กรอกค่าผ่าน TextBox แล้วเก็บลงฐานข้อมูล แล้วค่านั้นมี " ' " เป็นส่วนประกอบ ผลก็คือ Syntax Error ไม่สามารถ Add ฐานข้อมูลได้  เนื่องจาก Query Analyser ตีความผิดพลาด เพราะอ่านเจอ " ' " ดัง ตัวอย่าง นอกจากนี้ยังเป็นช่องทางที่ Hacker จะใช้ SQL Injections ได้

ตัวอย่าง Script  SQL ที่ใช้เพิ่มข้อมูลใน Table

SQL= "[[insert]] into myTable (myMessage,MyEmail,MyDate) values('& txtmyMessage &','& txtMyEmail &','& MyDate &')"

ถ้าค่าที่กรอกคือ

txtmyMessage="hello' "
txtMyEmail="
[email protected]"
MyDate="15-05-47 12:23"

เมื่อโปรแกรมประมวลผลก็จะได้ SQL ทั้งหมดคือ

[[insert]] into myTable (myMessage,MyEmail,MyTime) values('hello' ','[email protected]','15-05-47 12:23')

ซึ่งตรง txtmyMessage ="hello ' " จะมีเครื่องหมาย ' อยู่ ทำให้ Syntax Error

แนวทางแก้ไข/ป้องกัน
แทกโค๊ดตัวอย่างด้านล่าง ก่อน Submit ลงฐานข้อมูล

Value1= Request("Value1") ' ค่าที่รับมาจาก TextBox
Value1=Replace(Value1,"'",")  ' Replace เอา '  ออกหรือเอาแบบที่ใช้กับ HTML Syntax มาใช้เลยก็ได้ คือ Replace คอนโทรลโค๊ดที่สำคัญออกทั้งหมด 
 

SQL Injections


เป็นการ Hack ผ่าน SQL ครับ ขอยกตัวอย่างที่เจอบ่อย ๆ เกิดจากความไม่ระวังของ Programmer เองขอยกตัวอย่างหน้า Login น่ะครับที่เปิด DB เพื่อตรวจสอบ Username และ Password

SQL="[[select]] * from tableUser Where username='" & txtUsername & "' and password='" & txtPassword & "'"

โดย SQL ด้านบนจะ Run ผ่านหน้า Login เมือผู้ใช้กรอก Username และ Password แล้ว
สมมุติน่ะครับ ว่าถ้า User กรอกข้อมูลดังนี้

txtUsername= "user"
txtPassword= "pass' or 'x'='x'"

ตอนที่นำมาประมวลผลก็จะได้ Query String เต็ม ๆ คือ

SQL="[[select]] * from tableUser Where username='user' and password=pass' or 'x'='x' "

จุดที่น่าสนใจของ Query String ด้านบนคือ 'x'='x'  ถ้าเปรียบเทียบทางลอจิกมันจะเท่ากัน ดังนั้นเงื่อนไขก็เป็นจริง และเมื่อนำ 'x'='x' ไป OR กับ เงื่อนไขอื่น ๆ ก็เป็นจริงไปด้วย ดังนั้น Query String ด้านบนมันก็จะไม่สนใจแล้วว่า username และ password จะถูกต้องหรือไม่ เพราะ Query String เป็นจริงแล้วก็เข้าสู่ระบบต่อได้

แนวทางแก้ไข/ป้องกัน
แทกโค๊ดตัวอย่างด้านล่าง ก่อน Submit ลงฐานข้อมูล

Value1= Request("Value1") ' ค่าที่รับมาจาก TextBox
Value1= Replace(Value1,"'","") ' Replace เอา '  ออกหรือเอาแบบที่ใช้กับ HTML Syntax มาใช้เลยก็ได้ คือ Replace คอนโทรลโค๊ดที่สำคัญออกทั้งหมด 

อีกวิธีที่ควรใช้ร่วมกันกับวิธีแรก คือเทคนิคการเขียนโปรแกรมเช่น

DBCommand = New OleDBDataAdapter( "[[select]] * from tableUser Where username='" & txtUsername &"' and password='" & txtPassword & "'"
)" ,myConnection)
DBCommand.Fill(DSPageData,"tableUser")
' อ่านค่าจากฐานข้อมูลที่ได้ มาใส่ตัวแปรอีกครั้ง
DBusername = DSPageData.Tables("tableUser").Rows(0).Item("username")
DBpassword = DSPageData.Tables("tableUser").Rows(0).Item("password")

' แล้วก็เช็คกับ TextBox อีกที ว่าตรงกัน TextBox หรือไม่ เพราะถ้าตรงกันแสดงว่าเค้าได้กรอก
' ข้อมูลจริง ๆ เพราะไม่มี DBPassword และ DBusername ในตาราง มีค่าเป็น"pass' or 'x'='x' "
' มีช่องโหว่อีกนิดเป็นตอนสมัคร/Add ข้อมูล ต้อง Replace คอนโทรลโค๊ดออกด้วย เพราะ Hacker
' อาจใช้ username="user" ,และ password="pass' or 'x'='x' " ในตอนสมัคร/Add เลยก็ได้
' เพราะต่อให้ตรวจสอบแบบนี้มันก็ ผ่านได้

if DBusername = txtUsername.text and DBpassword = txtPassword.text then
' ตรงกันเข้าหน้า Admin ได้
else
' ไม่ตรงกัน
end if


Code ด้านบนก็พอที่จะป้องกันการ SQL Injections ได้ระดับนึงเท่านั้น
อีกอย่างที่ควรทำคือการกำหนดให้ TextBox กรอกข้อมูลได้ เฉพาะ a-z,0-9 ด้วยก็ได้ ทั้งนี้ขึ้นอยู่กับนโยบายหรือแผนที่คุณวางไว้ว่าจะป้องกันแค่ไหนดี

Code ด้านบนที่อ้างถึงเป็น asp.net ถ้าคุณใช้ภาษาอื่น Concept ก็คล้าย ๆ กัน ลองดู Function "Replace" ของภาษานั้นใช้ยังงัยนะครับ

บทความนี้เขียนจากประสบการณ์และการศึกษาเพิ่มเติมครับ มีคำแนะนำหรือเทคนิคอื่น ๆ เขียนไว้ตรง Comment ได้เลยนะครับ


ผู้เขียน/อ้างอิง : จักรกฤษณ์ แร่ทอง

เวบ/อินเตอร์เน็ตเทคโนโลยี

ความคิดเห็น/แนะนำ/ติชม/อื่นๆ

  • ViperZX [24 May 2005 , 02:24 AM]

    $sql = "SELECT uid,username,passwd FROM users WHERE username='carnix';"; ... if($db_password == $html_password){ return true; }

  • อรรถวุฒิ [19 Jun 2005 , 09:37 PM]

    ผมขอสอบถามหน่อยนะคับ คืนผมจะทำเวปที่มีการทำข้อสอบออนไลร์ มีการเก็บคะแนน แล้วส่งเข้าเก็บในฐานข้อมูล ผมจะสามาถรทำได้รึปล่าวคับ แล้วผมจะต้องทำยังไงดี แล้วจะใช้VB.netเขียนจะดีรึปล่าวคับ

  • apisak [09 พ.ค. 2549 , 09:06 AM]

    ผมขอถามเรื่องการกรอกข้อมูลของ TextBox ใน vb.net ครับ เพราะว่าผมอยากจะเช็คการกรอกข้อมูลอย่างเช่น ผมอยากกรอกข้อมูลได้เฉพาะภาษาไทย หรือภาษาอังกฤษ หรือกรอกทั้งภาษาไทยและภาษาอังกฤษจะต้องทำการเช็คค่าในการกรอกข้อมูลได้อย่างไรครับ

  • M [18 ส.ค. 2551 , 02:37 PM]

    พี่ๆ ที่รู้เรื่องนี้ครับ Error Type: Microsoft OLE DB Provider for ODBC Drivers (0x80004005) [Microsoft][ODBC Microsoft Access Driver] Operation must use an updateable query. /ynaddnews.asp, line 56 มันคืออะไรครับ

  • M [18 ส.ค. 2551 , 02:37 PM]

    พี่ๆ ที่รู้เรื่องนี้ครับ Error Type: Microsoft OLE DB Provider for ODBC Drivers (0x80004005) [Microsoft][ODBC Microsoft Access Driver] Operation must use an updateable query. /ynaddnews.asp, line 56 มันคืออะไรครับ

  • หนึ่ง [02 ส.ค. 2554 , 08:55 AM]

    ขอบคุณสำหรับบทความดีๆนะครับ

  • y [30 เม.ย. 2555 , 12:01 PM]

    คือจะให้ส่ง e-mail ทีละ 2 คน แล้วเก็บid ของเทเบิ้ลหนึ่ง เป็น lastlist ของอีกเทเบิ้ลไว้เพื่อ ส่งอีก 3-4 แล้วทำไปเรื่อยๆๆจนหมด แล้วก็ให้ค่ากลับไปเป้น 0 ตอนสุดท้าย