ComBioLaw.De » Blog » เขียนโปรแกรม » เพิ่มความปลอดภัยให้เวบไซท์ง่ายๆด้วย SHA1

เพิ่มความปลอดภัยให้เวบไซท์ง่ายๆด้วย SHA1

introPicเจ้าของเวบไซท์ทุกท่านคงไม่มีใครอยากให้เวบไซท์ของตัวเองโดนโจมตี โดยเหล่าแครกเกอร์ทั้งหลาย (อย่าสับสนนะครับระหว่างแครกเกอร์และแฮกเกอร์) การโจมตีของเหล่าแครกเกอร์นั้นมีมากมายหลายอย่างด้วยกันครับ แล้วแต่ว่าจุดประสงค์ของผู้โจมตี แต่ส่วนมากแล้วตามหน้าเวบไซท์ต่างๆนั้นมักจะไม่ถูกโจมตีเพื่อแอบดูข้อมูล เนื่องจากเวบไซท์ส่วนมากมักเปิดเผยข้อมูลของตนอยู่แล้ว แต่การโจมตีที่เวบไซท์ต่างๆโดนกันบ่อยๆ เป็นประเภทการโจมตีเพื่อเปลี่ยนแปลงหรือทำลายข้อมูลของเวบไซท์

แล้วเราจะป้องกันการโจมตีของเหล่าแครกเกอร์เหล่านี้ได้อย่างไรบ้าง เชิญติดตามอ่านเลยครับ ยิ้มกว้าง .........

เขียนโปรแกรม เขียนโปรแกรม

bow_der_kleine bow_der_kleine

การป้องกันการโจมตีเพื่อเปลี่ยนแปลงหรือทำลายข้อมูลบนเวบไซท์ ขึ้นอยู่กับปัจจัยหลายอย่าง ยิ่งปัจจัยต่างๆมีมากเท่าไร ก็เท่ากับเป็นการเปิดช่องว่างเวบไซท์ของเรามากขึ้นเท่านั้น ปัจจัยดังกล่าวได้แก่ ระบบปฏิบัติการของเวบเซิพเวอร์ โปรแกรมที่ใช้เป็นเวบเซิพเวอร์ ระบบป้องกันความปลอดภัยของเวบเซิพเวอร์ โปรแกรมฐานข้อมูลที่ใช้ โปรแกรมที่ใช้บริหารเวบเซิพเวอร์ ฯลฯ ซึ่งปัจจัยต่างๆเหล่านี้ล้วนแล้วแต่อยู่นอกการควบคุมของเหล่าเวบมาสเตอร์ส่วนใหญ่ แต่มักตกเป็นหน้าที่ของผู้ให้บริการเวบเซิพเวอร์ (ยกเว้นว่าใครจะเช่าเวบเซิพเวอร์เอง อันนั้นก็เป็นอีกเรื่องนึงครับ) เหล่าผู้ให้บริการเหล่านี้ล้วนแต่เป็นมืออาชีพและทำหน้าที่ของตนเองได้ดี ยกตัวอย่างเจ้าของเวบเซิพเวอร์ที่ผมเช่าพื้นที่อยู่ตอนนี้ เขาก็ทำหน้าที่ตรงนี้ได้ดีมากๆครับ ชื่นชมๆ

แต่มีช่องว่างหนึ่งที่เหล่าเวบมาสเตอร์ต้องรับภาระแบกรับ โดยเฉพาะอย่างยิ่งเวบไซท์ที่เป็น dynamic ทั้งหลาย (เวบไซท์ที่สามารถแก้ไขเนื้อหาได้โดยไม่ต้องอัพโหลดเนื้อหาที่เป็น HTML ขึ้นไปยังเวบเซิพเวอร์ทุกครั้งที่มีการเปลี่ยนแปลงเนื้อหา) ซึ่งเวบไซท์เหล่านี้มักใช้โปรแกรมจำพวก CMS (Content Management System หรือโปรแกรมบริหารข้อมูลบนหน้าเวบไซท์) ที่สมาชิกหรือเวบมาสเตอร์สามารถลอกอินแล้วเข้าไปแก้ไขเนื้อหาบนหน้าเวบไซท์ได้โดยไม่ต้องสร้างเอกสาร HTML ใหม่ทุกครั้งที่ต้องการเพิ่มเติมเนื้อหา ในส่วนของการลอกอินนี้เองครับที่มักเป็นตัวสร้างปัญหา เรามาดูกันครับว่าเราจะมีวิธีการป้องกันการโจมตีจากจุดนี้ได้อย่างไร

ก่อนอื่นเรามาดูกันก่อนครับว่า การโจมตีเวบไซท์โดยใช้ช่องว่างของ CMS นั้นทำกันอย่างไร

ปกติแล้วการใช้งาน CMS ต้องมีการลอกอินเข้าสู่ระบบก่อน จึงจะสามารถแก้ไขเนื้อหาบนหน้าเวบไซท์ได้ หากมีใครสามรถรู้เชื่อลอกอิน และ รหัสผ่านของผู้ใช้งาน (โดยเฉพาะผู้บริหารระบบ) ก็สามารถเปลี่ยนแปลงแก้ไข หรือ แม้แต่ทำลายข้อมูลบนหน้าเวบไซท์ได้ตามต้องการ

ระบบลอกอินของ CMS ส่วนมากไม่ได้มีการป้องกันการ ดักฟัง ข้อมูลที่ส่งผ่านระหว่างเวบบราวเซอร์และเวบเซิพเวอร์ โดยข้อมูลที่ส่งกันไปมานี้จะเป็นข้อมูลเปลือย นั่นหมายความว่าหากใครสามารถดักฟังข้อมูลดังกล่าวได้ ก็สามารถแอบอ้างลอกอินเป็นผู้ใช้งาน CMS ได้ทันที

การป้องกันไม่ให้คนอื่นดักฟังข้อมูลนั้นเป็นเรื่องที่เป็นไปแทบไม่ได้เลยครับ แต่มีวิธีป้องกันคือ เปลี่ยนแปลงข้อมูลของเราให้เป็นข้อมูลที่เวบเซิพเวอร์เท่านั้นที่สามารถเข้าใจได้ หากคนอื่นได้ข้อมูลของเราไปก็ไม่สามารถนำข้อมูลของเราไปใช้งานได้ วิธีการเช่นนี้มีทฤษฎีทางคณิตศาสตร์รองรับ มีการศึกษาวิจัยเป็นเรื่องเป็นราว และตั้งชื่อสาขาว่า Cryptography

วิธีการทาง Cryptography นั้นมีมากมายหลายแบบ แต่ละแบบมีระดับความปลอดภัยที่แตกต่างกันไป Cryptography ที่มีความปลอดภัยสูงสุดคือ One-Time-Pod แต่เนื่องจากความยุ่งยากทำให้ One-Time-Pod ไม่ได้รับความนิยมมากนักในปัจจุบัน ส่วนวิธีที่ได้รับความนิยมในปัจจุบันได้แก่ DES, MD5, SHA1, RSA etc.

เกริ่นมาเสียยาวเหยียด บลอคนี้ผมจะมานำเสนอการเพิ่มความปลอดภัยให้เวบไซท์ด้วย SHA1 ครับ

SHA1 เป็น Cryptography แบบ Hash Function นั่นหมายความว่าหากเราใส่ข้อมูลจำนวนหนึ่งเข้าไปในฟังก์ชั่นดังกล่าว เราก็จะได้ตัวเลขจำนวนหนึ่งที่มีความยาวคงที่ออกมา ซึ่งตัวเลขเหล่านี้เปรียบเสมือนลายนิ้วมือของข้อมูลที่เราใส่เข้าไป ซึ่งความเป็นไปได้ที่ข้อมูลสองชุดจะมีค่าที่ได้จาก Hash Function เหมือนกันนั้น มีความเป็นไปได้พอๆกับการที่คนสองคนมีลายนิ้วมือเหมือนกัน (เข้าใกล้ศูนย์) แต่ข้อมูลชุดเดียวกันจะมีค่าที่ได้จาก Hash Function เท่ากันเสมอ และข้อมูลที่คล้ายกัน แต่ไม่เหมือนกันทั้งหมด (เช่น เหมือนกันร้อยละ 99.99999999999999999999999999999999%) ก็จะมีค่า Hash ต่างกันอย่างสิ้นเชิง เพื่อป้องกันการเดาค่าที่ได้จาก Hash Function

การใช้ Hash Function ในการซ่อนข้อมูลมีข้อดีคือไม่จำเป็นต้องใช้กุญแจในการซ่อนข้อมูล เหมือน Cryptography แบบอื่นๆ (ลองนึกภาพตู้เซพดูครับ เราใช้กุญแจปิดตู้เซพ คนที่จะเปิดตู้เซพได้ต้องเป็นคนที่มีกุญแจเท่านั้น) แต่มีข้อจำกัดคือ คนที่รับข้อมูลต้องมีข้อมูลที่ต้องการส่งมาก่อน แล้วทำการเปรียบเทียบค่า Hash ที่ได้จากข้อมูลที่ส่งมากับค่า Hash ที่มีว่าเท่ากันหรือไม่ หากเท่ากันแสดงว่าข้อมูลนั้นถูกต้อง ซึ่งคุณสมบัตินี้เองที่ทำให้ Hash Function เหมาะสำหรับการซ่อนรหัสผ่าน เนื่องเพราะบนเวบเซิพเวอร์มีข้อมูลรหัสผ่านของผู้ใช้งาน CMS อยู่แล้ว เมื่อผู้ใช้งานส่งรหัสผ่านมาในรูปของผลลัพธ์ Hash ที่ได้จากรหัสผ่าน ทางเวบเซิพเวอร์สามาถเปรียบเทียบค่า Hash สองค่าเข้าด้วยกันว่าตรงกันหรือไม่ จึงเป็นการปกปิดข้อมูลจากการดักฟังได้ดีระดับหนึ่งทีเดียว

มาดูการใช้งาน SHA1 บน CMS กันเลยดีกว่าครับ ซึ่งการใช้งาน SHA1 นี้ต้องการ 2 เทคโลยีครับ คือ JavaScript และ Script ทางฝั่งเซิพเวอร์ เช่น PHP, Perl, Python เป็นต้น โดยในตัวอย่างผมใช้ PHP ครับ เพราะเป็นภาษาที่ผมใช้เขียนเวบ BioLawCom.De อยู่แล้ว

ตัวอย่างแรกเป็นการส่งข้อมูลแบบธรรมดาครับ โดย form.html จะเป็นตัวรับค่าข้อมูลจากผู้ใช้ทั้งชื่อลอกอินและรหัสผ่าน ส่งไปให้ getpassword.php จากนั้น getpassword.php จะประมวลผลเปรียบเทียบว่ารหัสผ่านที่ส่งมานั้นถูกต้องหรือไม่

<!-- form.html-->
<form action='getpassword.php' method='POST'>
     <input name='loginname' />
     <input name='password' type='password' />
     <input type='submit'>
</form>
plain code

<?php
     //getpassword.php
     $name = "root";
     $password = "my_secret_password";
     if($_POST[loginname]== $name && $_POST[password] == $password){
          do_something();
     }
     else{
          echo("Hey you gave me wrong password!!!!!");
     }
?>
plain code

ทีนี้เรามาดูการส่งข้อมูลโดยใช้ SHA1 กันดีกว่าครับ การสร้างการสร้างค่า Hash จาก SHA1 ในฝั่งเวบบราวเซอร์โดยใช้ JavaScript นั้นไม่จำเป็นต้องเขียนเองทั้งหมดครับ สามารถยืมของที่เขาเขียนเอาไว้แล้วมาใช้ได้ เขาไม่หวงแถมยังภูมิใจอีกครับ ที่มีคนใช้ของเขาเยอะๆ ซึ่ง Script ที่ว่านี้สามารถไปดาวน์โหลดได้ที่ Paj's Home ซึ่งที่นี่เขาไม่ได้มี JavaScript สำหรับ SHA1 เท่านั้นครับ ยังมี Criptography แบบอื่นๆอีกมามายให้เราเลือกใช้ น่าสนใจทีเดียว

หลังจากได้ Script ดังกล่าวมาแล้วก็เซพไฟล์เป็น JavaScript ชื่อใดชื่อหนึ่ง ผมขอตั้งชื่อเป็น sha1.js ครับ จากนั้นเราก็ผนวก JavaScript ที่ได้มาเข้ากับโปรแกรมของเราได้เลยครับ

<!-- form.html-->
<script src="sha1.js" type="text/javascript" language="JavaScript1.2"></script>
<script>
     function crypt(){
          pass = document.getElementsByName("prepassword")[0].value;
          crypted = hex_sha1(pass);
          document.getElementsByName("password")[0].value=crypted;
          document.getElementsByName("prepassword")[0].value="";
     }
</script>
<form action='getpassword.php' method='POST' onSubmit="crypt()" >
     <input name='loginname' />
     <input type="hidden" name="password" />
     <input name='prepassword' type='password' />
     <input type='submit'>
</form>
plain code

ในส่วนของ form ผมได้เพิ่ม attribute onSubmit="cypt()" เข้าไปเพื่อตอนกดปุ่ม submit ส่งข้อมูลไปยังเวบเซิพเวอร์นั้น เวบบราวเซอร์จะเรียกฟังชั่น crypt() ขึ้นมา ในฟังก์ชั่น crypt() นี่เองรหัสผ่านจะถูกเปลี่ยนเป็นค่า Hash แล้วส่งไปยังเวบเซิพเวอร์ หากใครสังเกตดีๆ ก็จะเห็นว่าจริงๆแล้วค่า prepassword เกินความจำเป็น ใช่ครับ แต่ว่าผมได้ใส่มันลงไป เพื่อให้ตัวบราวเซอร์จำรหัสผ่านที่ถูกต้องไว้ (ในกรณีที่เปิดใช้ฟังก์ชั่นจำรหัสผ่าน) หากไม่มีตัว prepassword มาเป็นตัวแปรกลาง เจ้าเวบบราวเซอร์ก็จะเซ่อจำค่า Hash ที่ได้จากรหัสผ่านแทน ซึ่งอันนี้ทำให้ผู้ใช้งานบางท่านลำบากแน่นอน

<?php
     //getpassword.php
     $name = "root";
     $password = sha1("my_secret_password");
     if($_POST[loginname]== $name && $_POST[password] == $password){
          do_something();
     }
     else{
          echo("Hey you gave me wrong password!!!!!");
     }
?>
plain code

สำหรับฝั่ง PHP เราก็ไม่ต้องลำบากเขียน Hash Function เองเช่นกัน เพราะเขามีฟังก์ชั่นนี้เป็นค่าปริยายมาให้เราใช้กันอยู่แล้วครับ เพียงแค่เรียกฟังก์ชั่น sha1() มาใช้ เราก็จะได้ค่า Hash มาใช้งานทันทีครับ

ผล Hash ที่ได้จาก "my_secret_password" ก็คือ b21fd5acd32e3be75f82afaa623a39a668208295

แม้กระนั้นก็ตามระบบดังกล่าวก็ยังไม่ได้ดีกว่าระบบเดิมเท่าใดนัก (เอ..... แล้วจะเอามาให้ดูทำไมเนี่ย) เพราะว่าหากรหัสผ่านที่ใช้นั้นเหมือนเดิม ค่า Hash ที่ได้ก็เหมือนเดิม ดังนั้นคนที่ดักฟังก็ยังสามารถใช้ค่า Hash ที่ได้ปลอมตัวเข้ามาทำลายระบบได้เหมือนเดิม แต่ไม่เป็นไรครับ เราสามารถใช้คุณสมบัติข้อหนึ่งของ Hash Function มาแก้ปัญหานี้ได้ นั่นก็คือ ข้อมูลที่มีความคล้ายกันแต่ไม่เหมือนกัน ค่า Hash ที่ได้จะแตกต่างกันโดยสิ้นเชิง

โดยวิธีการก็คือเราต้องสุ่มข้อมูลขึ้นมาหนึ่งชุด ซึ่งข้อมูลชุดนนี้จะแตกต่างกันทุกครั้งที่มีการลอกอิน แล้วเก็บข้อมูลชุดนี้ไว้ทั้งสองที่ ทั้ง เวบบราวเซอร์ และ เวบเซิพเวอร์ จากนั้นก็รวมข้อมูลชุดนี้กับรหัสผ่าน แล้วนำผลลัพธ์ที่ได้ไปหาค่า Hash อีกครั้งหนึ่ง ซึ่งการเก็บข้อมูลสุ่มสามารถทำได้โดยใช้ Cookies หรือ Session ดังนั้นเราต้องเปลี่ยน form.html ให้เป็น PHP เพื่อทำให้เราเก็บข้อมูลสุ่มไว้ใน JavaScript ได้

<?php
     /////////////////// form.php //////////////////////////
     session_start();
     header('Content-Type: text/html; charset=TIS-620');
?>
<?php
     function generate_random_key(){
          $extrakey="";
          for($j=0;$j<50;$j++){
               while(true){
                    mt_srand((double)microtime()*1000000);
                    $zufall=mt_rand(48,122);
                    if(($zufall>=48 && $zufall<=57) || ($zufall>=65 && $zufall<=90) || ($zufall>=97 && $zufall<=122)){
                         $extrakey.=chr($zufall);
                         break;
                    }
               }
          }
          return $extrakey;
     }
     $_SESSION[extra_key] = generate_random_key()
?>
 
 
<script src="sha1.js" type="text/javascript" language="JavaScript1.2"></script>
<script>
     function crypt(){
          pass = document.getElementsByName("prepassword")[0].value;
          crypted = hex_sha1(pass);
          document.getElementsByName("password"+)[0].value=crypted;
          document.getElementsByName("prepassword")[0].value="";
     }
</script>
<form action='getpassword.php' method='POST' onSubmit="crypt()" >
     <input name='loginname' />
     <input type="hidden" name="password" />
     <input name='prepassword' type='password' />
     <input type='submit'>
</form>
plain code

<?php
     //getpassword.php
     $name = "root";
     $password = sha1("my_secret_password".$_SESSION[extra_key]);
     if($_POST[loginname]== $name && $_POST[password] == $password){
          do_something();
     }
     else{
          echo("Hey you gave me wrong password!!!!!");
     }
?>
plain code

แล้วทีนี้เวบของเราก็จะปลอดภัยจากการโจมตีขึ้นไปอีกระดับหนึ่ง แต่ปัญหาก็ยังไม่หมดเพียงเท่านั้นครับ ในกรณีที่ผู้ใช้งานใช้รหัสผ่านเป็นภาษาไทย ค่า Hash ที่ได้จาก JavaScript และ PHP จะต่างกันโดยสิ้นเชิง เพราะ PHP และ JavaScript ใช้ CharSet คนละตัวกัน ดังนั้นเราต้องปรับ CharSet ทั้งสองฝั่งให้ตรงกันก่อน ก่อนที่จะนำข้อมูลใส่ลงไปใน Hash Function ซึ่งวิธีดังกล่าวสามารถดูจากโค้ดข้างล่างนี้ได้เลยครับ

<?php
     //getpassword.php
     $name = "root";
     $password = "สุดยอดรหัสผ่าน my secret password";
     $th_charcode=Array(3653,43,47,3665,45,3666,3616,3667,3606,3668,3640,
     3641,3638,3647,3588,3669,3605,3670,3592,3671,
     3586,3672,3594,3673,3654,3664,3652,34,3635,3598,
     3614,3601,3632,3608,3633,3661,3637,3658,3619,3603,3609,3631,
     3618,3597,3610,3600,3621,3600,3587,3589,3615,3620,3627,3590,
     3585,3599,3604,3650,3648,3596,3657,3655,3656,
     3659,3634,3625,3626,3624,3623,3595,3591,46,3612,40,3611,41,
     3649,3593,3629,3630,3636,3642,3639,3660,3607,63,
     3617,3602,3651,3628,3613,3622);
     $th_charset=Array("ๅ","+","/","๑","-","๒","ภ","๓","ถ","๔",
     "ุ","ู","ึ","฿","ค","๕","ต","๖","จ","๗","ข","๘",
     "ช","๙","ๆ","๐","ไ",""","","","","","","","",
     "","","","","","","","","","","",
     "","","","","","","","","","","",
     "","","","","","","","","","","","","",
     "",".","","(","",")","","","","","","",
     "","","","?","","","","","","");
     $newpass="";
     for($i=0;$i
          if(in_array(substr($password,$i,1),$th_charset)){
               for($j=0;$j
                    if(substr($password,$i,1) == $th_charset[$j]){
                         $newpass.=chr($th_charcode[$j]);
                         break;
                    }
               }
          }
          else{
               $newpass.=substr($password,$i,1);
          }
     }
     $password = sha1($newpass.$_SESSION[extra_key]);
     if($_POST[loginname]== $name && $_POST[password] == $password){
          do_something();
     }
     else{
          echo("Hey you gave me wrong password!!!!!");
     }
?>
plain code

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

23 Dec 05 | by | tags เขียนโปรแกรม PHP JavaScript SHA1 MD5 Security

read 6502

<<ดูหนังดูละคร แล้วย้อนดูสังคม || โฮ่ ๆ ๆ ....Merry Cristmas !! นะครับชาวเว็บ..>>

ความคิดเห็น (click here to comment)

Search

Navigation

รวมลิงก์น่าสนใจ

ความเคลื่อนไหว

Login

name password

ลืมรหัสผ่าน