18 September 2015

PASSWORD HASHING & INPUT FILTERING

[PHP] 

Password hashing

จากข่าวการแฮ็กเว็บไซต์ต่างๆ ในช่วงที่ผ่านมา หลายคนคงได้ยินว่า บางเว็บไซต์เก็บข้อมูลรหัสผ่านไว้แบบ Plain text ก็คือไม่ได้เข้ารหัส ซึ่งทำให้ใครก็ตามที่เจาะเข้าระบบได้ก็สามารถเห็น Username, Password และข้อมูลสำคัญๆ ทุกอย่างได้หมดเลย ดังนั้นเพื่อเป็นการป้องกัน มาดูกันดีกว่าว่าเราจะเก็บข้อมูล Password ในฐานข้อมูลยังไงให้ปลอดภัย
ก่อนอื่นมาว่าด้วยเรื่องของการ Hash กันก่อน
การ Hash คือการแปลงแปลงชิ้นส่วนของข้อมูล (ไม่ว่าข้อมูลจะมีขนาดเล็กหรือขนาดใหญ่) ให้เป็นข้อมูลชิ้นเล็กๆ ที่มีความสัมพันธ์กับข้อมูลเดิม โดยผลที่ได้จะอยู่ในรูปของ String หรือ Integer
ซึ่งการ Hash จะเป็นการทำงานแบบ One-way คือ ไม่สามารถเอาผลลัพธ์ที่ได้ไปหาย้อนกลับว่าข้อมูลต้นฉบับก่อน Hash คืออะไร
ตัวอย่างฟังก์ชัน hash ที่นิยมใช้กัน คือฟังก์ชัน md5()
$data = “Hello World”;
$hash = md5($data);
echo $hash; // b10a8db164e0754105b7a99be72e3fe5
ผลลัพธ์ของ md5() จะได้ข้อมูล 128 bit หรือ 16 byte แต่เนื่องจากข้อมูลที่ได้เป็นเลขฐาน 16 (1 ตัวอักษรใช้ 4 bit) ดังนั้นค่าที่ได้จะเป็น string ความยาว 32 ตัวอักษร
ในระบบ Web Application เมื่อผู้ใช้ทำการลงทะเบียน ก็จะเอารหัสผ่านที่ผู้ใช้ตั้ง มาเข้าฟังก์ชัน hash แล้วค่อยเก็บลงฐานข้อมูล ดังนั้นรหัสผ่านที่อยู่ในฐานข้อมูลก็จะไม่ใช่รหัสผ่านจริง และเนื่องจากฟังก์ชัน hash เป็น one-way ดังนั้นจึงไม่มีทางรู้ได้เลยว่าผู้ใช้ตั้งรหัสผ่านว่ายังไง แม้แต่ admin ก็ไม่มีทางรู้ (ซึ่งจริงๆ แล้ว admin ก็ไม่มีสิทธิ์รู้รหัสผ่านของผู้ใช้) และเมื่อผู้ใช้ Login เข้าสู่ระบบ ก็จะเอารหัสผ่านที่ผู้ใช้ป้อน มาเข้าฟังก์ชัน hash เดียวกัน แล้วเอาค่าที่ได้มาตรวจดูว่าตรงกับค่าที่อยู่ในฐานข้อมูลมั้ย ถ้าตรงกันก็แปลว่าผู้ใช้ใส่รหัสผ่านถูกต้อง
ถ้าดูจากแนวคิดข้างบน ระบบนี้ก็น่าจะปลอดภัย แต่จริงๆ แล้ว มันก็มีปัญหาเหมือนกัน

ปัญหาที่ 1 : Hash Collision

เนื่องจากขนาดของ Output เป็นค่าคงที่ ดังนั้น จึงอาจเป็นไปได้ที่ Input ต่างกัน แต่ได้ Output มาเหมือนกัน ปัญหานี้จะเกิดขึ้นถ้าฟังก์ชัน hash ที่ใช้ ให้ output ออกมาเป็นค่าที่มีความยาวน้อยๆ เช่น ฟังก์ชัน crc32() จะให้ค่าออกมาเป็น integer 32 bit ซึ่งความยาวของ output จะจำกัดอยู่ที่ 9 ตัวอักษร ดังนั้น ถ้ามี hacker เจาะเข้าฐานข้อมูลได้ แล้วได้ hash ของ password ไป ก็สามารถเขียนโปรแกรมเพื่อสุ่มสร้าง password ที่ให้ output ออกมาตรงกับค่า hash ที่ได้ ซึ่ง password ที่สร้างขึ้นมา อาจไม่ใช่ password จริงที่ผู้ใช้ตั้งก็ได้

วิธีป้องกัน

ใช้ฟังก์ชัน hash ที่ให้ค่าความยาวของ output ไม่น้อยจนเกินไป เช่น ฟังก์ชัน sha1() จะให้ output ที่มีขนาด 160 bit (40 ตัวอักษร)

ปัญหาที่ 2 : Rainbow Tables

ตารางสีรุ้ง!!? … ไม่รู้จะแปลเป็นไทยว่าไงดี งั้นไม่แปลละกัน …
Rainbow Tables คือตารางขนาดใหญ่ที่สร้างขึ้นจากการ hash คำพื้นๆ ที่นิยมนำมาตั้งเป็นรหัสผ่าน ซึ่งตารางนี้อาจจะมีข้อมูลเป็นหลักล้านหรือหลักร้อยล้านแถวเลยก็ได้ สมมุติว่า hacker เจาะฐานข้อมูลได้ และได้ username กับ hash ของ password ไป ก็จะเอา hash ที่ได้มาเทียบกับค่า hash ใน rainbow table ถ้าเกิดในระบบมีผู้ใช้ที่ตั้งรหัสผ่านโดยใช้คำพื้นๆ hash นั้นก็จะไปตรงกับ hash ที่อยู่ใน rainbow table จากนั้นก็ … เสร็จโจร!

วิธีป้องกัน

… โรยเกลือ … แปลไม่เป็นอีกแล้วสิ … อธิบายง่ายๆ ก็คือ เราจะสร้าง salt ขึ้นมา ซึ่ง salt ที่ว่า ก็อาจจะเป็นตัวเลขหรือตัวอักษรอะไรก็ได้ใส่เข้าไปมั่วๆ เพื่อที่จะนำมา concatenate กับ password แล้วค่อยเอาไป hash ตัวอย่างโค้ด
$password = “easypassword”;
echo sha1($password); // 6c94d3b42518febd4ad747801d50a8972022f956
$salt = “f#@V)Hu^%Hgfds”;
echo sha1($salt . $password); // cd56a16759623378628c0d9336af69b74d9d71a5
เท่านี้ก็ป้องกันได้แล้ว … รึเปล่า?

ปัญหาที่ 3 : Rainbow Tables (again)

… อีกแล้ว!!?
เนื่องจากว่า Rainbow Tables เนี่ย มันสามารถสร้างขึ้นมาใหม่ได้ ซึ่งถ้า hacker สามารถเข้ามาในระบบได้ แล้วรู้ว่า salt ที่ใช้คืออะไร (เช่น อ่านดูจากไฟล์ php) ก็สามารถสร้าง Rainbow Table ที่เกิดจากการเอา salt มาใส่กับรหัสผ่าน แล้วก็แกะรหัสผ่านได้อยู่ดี

วิธีป้องกัน

ใช้ “Unique Salt” คือ salt ของใครของมัน … ง่ายสุดก็เอา user_id นี่แหละมาทำเป็น salt ซะเลย
$hash = sha1($user_id . $password);
การ hash แบบนี้ทำได้ในกรณีที่ว่า user_id ไม่สามารถเปลี่ยนได้ ซึ่งก็ทำให้ hash แต่ละตัว มีค่า salt ของใครของมัน

ปัญหาที่ 4 : Hash Speed

ปัจจุบันนี้คอมพิวเตอร์ทำงานเร็วมาก ฟังก์ชัน hash ถูกออกแบบมาเพื่อให้สามารถคำนวนได้อย่างรวดเร็ว ดังนั้นจึงเป็นไปได้ที่ใน 1 วินาทีสามารถคำนวณ hash ได้เป็นพันล้านตัว โดยทั่วไปเราอาจคิดว่าการกำหนดให้รหัสผ่านมีความยาวอย่างน้อย 8 ตัวอักษร ก็น่าจะเพียงพอสำหรับการป้องกันการโจมตีแบบ Brute Force ได้ แต่จริงๆ แล้วไม่ใช่ ยกตัวอย่างเช่น
  • ถ้ารหัสผ่านประกอบด้วยตัวอักษรตัวพิมพ์เล็ก, ตัวพิมพ์ใหญ่ และตัวเลข ก็จะมีจำนวนอักขระที่สามารถใช้งานได้คือ 62 ตัว (26+26+10)
  • String ที่มีความยาว 8 ตัวอักษร ก็มีความเป็นไปได้คือ 62^8 ก็ประมาณ 218 ล้านๆ
  • ถ้าสามารถคำนวณ hash ได้ 1 พันล้านตัวใน 1 วินาที (สมมุติว่าใช้คอมหลายๆ เครื่องช่วยกันคำนวณ) ก็จะใช้เวลาแค่ 60 ชั่วโมงในการแกะ
ไม่ต้องพูดถึงรหัสผ่านที่มีความยาวแค่ 6 ตัวอักษรที่นิยมใช้กัน ซึ่งในความยาวแค่นี้ สามารถแกะได้ด้วยเวลาแค่ 1 นาที ดังนั้น การกำหนดความยาวขั้นต่ำของรหัสผ่านไว้ที่ 9 ถึง 10 ตัวอักษร ก็เป็นเรื่องที่สมเหตุสมผล

วิธีป้องกัน

ใช้ฟังก์ชัน hash ที่คำนวณนานๆ เช่น สามารถคำนวณ hash ได้แค่ 1 ล้านตัวต่อวินาที แทนที่จะเป็น 100 ล้านตัว ก็จะเพิ่มเวลาที่ hacker ใช้ในการแกะรหัสผ่านเป็น 1000 เท่า จากเดิม 60 ชั่วโมง ก็จะกลายเป็น 7 ปี
ใน PHP จะมีฟังก์ชัน cryp() ซึ่งใช้อัลกอรึทึม BLOWFISH ในการเข้ารหัส สามารถศึกษาวิธีการใช้งานได้ที่http://www.w3schools.com/php/func_string_crypt.asp
จะเห็นได้ว่า ในเรื่องของการรักษาความปลอดภัยนั้น ความร่วมมือของผู้ใช้ก็มีส่วนด้วย ดังนั้น ถ้าเป็นไปได้ ก็ควรกำหนดให้ผู้ใช้ตั้งรหัสผ่านที่มีความยาว 8 ตัวอักษรขึ้นไป และในรหัสผ่านนั้นต้องประกอบด้วยตัวอักษรตัวพิมพ์เล็ก, ตัวพิมพ์ใหญ่, ตัวเลข หรือมีอักขระพิเศษเข้าไปด้วยก็จะยิ่งดี บางระบบสามารถตั้งรหัสผ่านเป็นภาษาไทยได้ด้วย ซึ่งก็ยิ่งเพิ่มความปลอดภัยมากขึ้นไปอีก
ในกรณีที่ผู้ใช้ลืมรหัสผ่าน มีกรณีเดียวเท่านั้นคือ ต้อง Reset password และกำหนดรหัสผ่านใหม่ ซึ่งการ Reset รหัสผ่าน ก็จะใช้วิธีสร้าง One-time password ขึ้นมา เป็นรหัสผ่านที่ใช้เข้าระบบได้แค่ครั้งเดียว คือเข้ามาเพื่อกำหนดรหัสผ่านใหม่เท่านั้น
… สุดท้าย อย่างที่บอก ว่ารหัสผ่านที่เก็บในฐานข้อมูลนั้นต้องเป็นความลับ และต้องไม่มีทางหาย้อนกลับได้ว่ารหัสผ่านจริงๆ คือคำว่าอะไร ดังนั้น ถ้าเข้าเว็บไซต์ไหน ที่เมื่อเวลากด “Forget Password” แล้วมันสามารถบอกรหัสผ่านเดิมของเราได้ ก็มั่นใจได้เลยว่าถ้าเว็บไซต์นี้โดนเจาะ … ซวยแน่

Input Filtering

จากบทความก่อน ผมก็ลืมเรื่องที่สำคัญอีกเรื่องนึง คือการตรวจสอบ Input ที่รับเข้ามาจากผู้ใช้ ซึ่งเรื่องนี้ก็เป็นเรื่องใหญ่อีกเช่นกัน เนื่องจาก Input ทุกอย่างที่รับเข้ามาจากผู้ใช้ สามารถถูกสร้างขึ้นได้เองหรือปลอมแปลงมาโดยไม่ได้ผ่าน Interface ของเว็บเราก็ได้ ซึ่งถ้าไม่มีการตรวจสอบข้อมูลที่รับเข้ามา แล้วเอามาประมวลผลเลย อย่างนี้ไม่ดีแน่
สิ่งที่ต้องจำ คือ “ห้ามเชื่อข้อมูลทุกอย่างที่มาจากแหล่งข้อมูลภายนอก” ไม่ว่าจะเป็น
  • ข้อมูลจาก form
  • ข้อมูลจาก $_GET, $_POST, $_REQUEST
  • คุกกี้ $_COOKIES
  • ข้อมูลจาก Web service
  • ไฟล์
  • ตัวแปรบางอย่างจาก Server (เช่น $_SERVER[‘SERVER_NAME’])
  • ตัวแปร Environment
  • ค่าที่ได้จากการ Query ฐานข้อมูล
  • ฯลฯ
ข้อมูลทุกอย่างที่รับเข้ามา ต้องผ่านการกรอง (Filter) ก่อนนำมาใช้
Filter มีอยู่ด้วยกัน 2 ลักษณะ

1. Sanitizing filters

  • อนุญาตหรือไม่อนุญาตให้มีตัวอักษรที่กำหนดอยู่ใน string
  • Return ค่าเป็น String

ตัวอย่าง

FILTER_SANITIZE_SPECIAL_CHARS ตัด HTML escape character (เช่น ‘ ” < > &) ออกจาก string
FILTER_SANITIZE_URL ตัดอักขระอื่นที่ไม่ใช่ตัวอักษร,ตัวเลข และไม่ใช่ $-_.+!*'(),{}|\\^~[]`<>#%”;/?:@&=

2. Logical filters

  • Return ค่าเป็น TRUE หรือ FALSE

ตัวอย่าง

FILTER_VALIDATE_EMAIL ตรวจสอบว่าค่าที่รับเข้ามาอยู่ในรูปแบบของ e-mail หรือเปล่า
FILTER_VALIDATE_INT ตรวจสอบค่าที่รับเข้ามาว่าเป็นชนิด Int หรือเปล่า
ตัวอย่างการใช้งาน filter เพื่อตรวจสอบค่าที่รับเข้ามาว่าอยู่ในรูปแบบของ email หรือเปล่า
if (isset($_REQUEST[’email’])) {
if (!is_string($_REQUEST[’email’])) {
break;
}
$email = filter_input(INPUT_POST, ’email’, FILTER_VALIDATE_EMAIL);
}
-------------------------------------------------------------------------------------------------------------------------
credit : https://bigta.wordpress.com/2011/06/12/php-password-hashing-input-filtering/
-------------------------------------------------------------------------------------------------------------------------

15 September 2015

22 เทคนิคการปรับ .htaccess

 .htaccess คือ วิธีการอีกหนึ่งวิธีที่ใช้สำหรับ config เปลี่ยนค่าต่างๆ ของแต่ละ directory หลักๆ ภายในไฟล์อาจจะประกอบไปด้วย 1 หรือหลายๆคำสั่ง โดยไฟล์ .htaccess จะถูกเจาะจงวางใว้แค่บาง directory และจะบังคับใช้คำสั่งภายใน directory และ sub directory นั้นๆ
ซึ่งผมได้รวบรวมเทคนิคที่เป็นประโยชน์และสำคัญๆใว้ดังนี้ครับ

1. Custom Directory Index Files

DirectoryIndex index.html index.php index.htm
คุณสามารถเปลี่ยนค่า default index file ได้โดยใช้คำสั่งข้างบน โดยระบุไฟล์ที่คุณต้องการ แทน index.html index.php index.htm ตามลำดับ

2. Custom Error Pages

ErrorDocument 404 errors/404.html
ใช้สำหรับ redirect user ไปหน้าที่คุณต้องการ ถ้าเกิดเหตุการที่ user เรียกหน้าที่ไม่มีในระบบ (เกิด error 404)

3. Control access at files & directory level

จำกัดหรือปฏิเสธการเข้าใช้ไฟล์หรือโฟลเดอร์ที่เป็นส่วนบุคคล เช่น โฟลเดอร์ includes ที่เก็บไฟล์สคริปต่างๆ
ในกรณีนี้ให้คุณสร้างไฟล์ .htaccess ในโฟลเดอร์ includes แล้วใส่คำสั่งดังนี้
# no one gets in here!
deny from all
จะปฏิเสธทุก direct access และทุกไฟล์ที่อยู่ในโฟลเดอร์นั้น
คุณสามารถระบุเงื่อนไขได้เช่นกัน โดยตัวอย่างนี้เป็นการจำกัดการเข้าถึงจากช่วงของ IP
# no nasty crackers in here!
order deny,allow
deny from all
allow from 192.168.0.0/24
# this would do the same thing..
#allow from 192.168.0
หรือบางครั้งคุณอาจจะแค่ต้องการ ban เพียงแค่ IP เดียว
# someone else giving the ruskies a bad name..
order allow,deny
deny from 83.222.23.219
allow from all

4. Modifying the Environment Variable

Set / Unset environment variables โดยใช้ SetEnv and UnSetEnv.
SetEnv SITE_WEBMASTER_URI mailto:Jack.Sprat@characterology.com
UnSetEnv REMOTE_ADDR

5. 301 Redirect using htaccess

ถ้าคุณต้องการที่จะ redirect จากไฟล์เก่าไปไฟล์ใหม่
Redirect 301 /old/file.html http://yourdomain.com/new/file.html
ถ้าเป็นไดเรคทอรี่
RedirectMatch 301 /blog(.*) http://yourdomain.com/$1

6. Implementing a Caching Scheme with .htaccess

Cache ข้อมูลที่มีการเปลี่ยนแปลงไม่บ่อย (static) เพื่อเพื่ม performance ระบบ
# year
Header set Cache-Control “public”
Header set Expires “Thu, 15 Apr 2010 20:00:00 GMT”
Header unset Last-Modified
#2 hours
Header set Cache-Control “max-age=7200, must-revalidate”
SetOutputFilter DEFLATE
Header set Expires “Thu, 15 Apr 2010 20:00:00 GMT”

7. Compress output using GZIP

บีบอัดไฟล์ css, js, html, ด้วย Gzip
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
โดยโค้ดข้างบนจะทำงานถ้าเว็บเซอร์เวอร์ของคุณเปิด mod_gzip คุณอาจจะต้องเพิ่มโค้ดข้างล่างนี้
ถ้าเว็บเซอร์เวอร์ของคุณสนับสนุน mod_deflate
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|gz2|sit|rar)$ no-gzip dont-vary
ถ้าเว็บเซอร์เวอร์ของคุณไม่สนันสนุน mod_deflate คุณอาจต้องการเพิ่มโค้ดนี้
php_value output_handler ob_gzhandler

8. Redirect browser to https (ssl)

redirect เว็บไซด์ไปใช้ https
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

9. Rewrite URLs using htacccess

เปลี่ยน URL จาก product.php?id=12 เป็น product-12.html
RewriteEngine on
RewriteRule ^product-([0-9]+)\.html$ product.php?id=$1
เปลี่ยน URL จาก product.php?id=12 เป็น product/ipod-nano/12.html
RewriteEngine on
RewriteRule ^product/([a-zA-Z0-9_-]+)/([0-9]+)\.html$ product.php?id=$2
เปลี่ยน URL ที่ไม่มี www ให้มี www (ป้องกัน Duplicate Content)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^viralpatel\.net$
RewriteRule (.*) http://www.viralpatel.net/$1 [R=301,L]
เปลี่ยน URL จาก yoursite.com/user.php?username=xyz เป็น yoursite.com/xyz
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)$ user.php?username=$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ user.php?username=$1
Redirect domain ไปหา subfolder ภายใน public_html
RewriteEngine On
RewriteCond %{HTTP_HOST} ^test\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.test\.com$
RewriteCond %{REQUEST_URI} !^/new/
RewriteRule (.*) /new/$1

10. Prevent Directory Listing

หลีกเลี่ยง directory listing
Options -Indexes
หรือ
IndexIgnore *

11. Adding new MIME types

ประเภทขึ้นอยู่กับนามสกุลไฟล์ นามสกุลที่ไม่รู้จักจะถูกเปลี่ยนเป็นข้อความ และจะเกิดความเสียหาย
AddType application/x-endnote-connection enz
AddType application/x-endnote-filter enf
AddType application/x-spss-savefile sav

12. Deny access to static file data

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]
RewriteCond %{HTTP_REFERER} !^http://www.askapache.com.*$ [NC]
RewriteRule \.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$ – [F,NS,L]

13. Specify Upload file limit for PHP in htaccess

php_value upload_max_filesize 20M
php_value post_max_size 20M
php_value max_execution_time 200
php_value max_input_time 200
บรรทัดแรกคือการจำจัดค่าสูงสุดของไฟล์ที่สามารถอัพโหลดได้
บรรทัดสองคือการจำกัดค่าสูงสุดของข้อมูลการโพส
บรรทัดสามคือค่าเวลาในการ execution
บรรทัดสุดท้ายคือค่าเวลาสูงสุดที่อนุญาติในการ input ข้อมูลอัพโหลดเช่น POST and GET

14. Disallow Script Execution

Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi

15. Change Charset and Language headers

AddDefaultCharset UTF-8
DefaultLanguage en-US

16. Set Timezone of the Server (GMT)

SetEnv TZ America/Indianapolis
รายชื่อของเขตเวลาที่สนับสนุน
http://www.php.net/manual/en/timezones.php

17. Force “File Save As” Prompt

AddType application/octet-stream .avi .mpg .mov .pdf .xls .mp4

18. Protecting a single file

โดยปกติ .htaccess จะมีผลกับข้อมูลทั้งไดเรคทอรี่ แต่คุณสามารถที่จะแก้ไขคำสั่งแบบเจาะจงกับบางไฟล์
order deny,allow
deny from all
AuthType Basic
AuthName “Characterology Student Authcate”
AuthLDAP on
AuthLDAPServer ldap://directory.characterology.com/
AuthLDAPBase “ou=Student, o=Characterology University, c=au”
require valid-user
satisfy any

19. Set Cookie using htaccess

environment variable
Header set Set-Cookie “language=%{lang}e; path=/;” env=lang
สร้าง cookie ในเครื่อง client กับข้อมูลที่ matching กัน
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)(de|es|fr|it|ja|ru|en)/$ – [co=lang:$2:.yourserver.com:7200:/]

20. Send Custom Headers

Header set P3P “policyref=\”http://www.askapache.com/w3c/p3p.xml\””
Header set X-Pingback “http://www.askapache.com/xmlrpc.php”
Header set Content-Language “en-US”
Header set Vary “Accept-Encoding”

21. Blocking request based on User-Agent Header

SetEnvIfNoCase ^User-Agent$ .*(craftbot|download|extract|stripper|sucker|ninja|clshttp|webspider|leacher|collector|grabber|webpictures) HTTP_SAFE_BADBOT
SetEnvIfNoCase ^User-Agent$ .*(libwww-perl|aesop_com_spiderman) HTTP_SAFE_BADBOT
Deny from env=HTTP_SAFE_BADBOT

22.Prevent hacks

ถ้าคุณต้องการที่จะเพิ่มระดับความปลอดภัยให้กับระบบคุณ คุณสามารถเพิ่มโค้ดเพียงไม่กี่บรรทัดนี้ เพื่อตรวจสอบ url ที่แปลกๆที่มีพิรุทเสี่ยงจะเป็นอัตราย
RewriteEngine On
# proc/self/environ? noway!
RewriteCond %{QUERY_STRING} proc/self/environ [OR]
# Block out any script trying to set a mosConfig value through the URL
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*(.*) [OR]
# Block out any script that includes a
---------------------------------------------------------------
credit : http://www.piranon.com/22
---------------------------------------------------------------