Twitter Delicious Facebook Digg Stumbleupon Favorites More

Thứ Tư

Anti PHP & SQL Injection

I - Anti PHP & SQL Injection

1.SQL Injection

- Hầu hết các lỗi SQL Injection đều là do câu lệnh SQL sai hoặc do User làm cho câu lệnh SQL sai , không thực hiện đúng chức năng của nó . Ví dụ như chúng ta có một Script kiểm tra đăng nhập như sau :

Mã lệnh (php)
<?
//Các lệnh Connect vào SQL Database .v.v.
$username = $_POST['username']; //Lấy User và Pass từ Form
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM users WHERE user = \"$username\" AND password = \"$password\"");
if (mysql_num_rows($result) > 0) {
//Đăng nhập thành công
}
else {
//Đăng nhập không đúng Username hay Password
}
//.......
?>

- Đoạn Script trên là một đoạn Script rất đơn giản thực hiện Login thông qua câu SQL kiểm tra username và password . Câu lệnh SQL nguyên thủy là :

SELECT * FROM users WHERE user = "$username" AND password = "$password"

- Tuy nhiên, đây lại là một SQL Injection vô cùng lớn, nếu như User nhập biến User là " OR 1 OR user="

- Khi đó lệnh SQL sẽ trở thành :

SELECT * FROM users WHERE user = "" OR 1 OR user="" AND password = "$password"

- Kết quả trả về sẽ là toàn bộ user trong Database và dĩ nhiên đây là một trường hợp Login không hợp lệ (biến password cũng có thể sữ dụng để tạo SQL Injection) . Thực ra, lỗi trên là do biến $username, có thể fix bằng cách kiểm tra biến user, rồi sau đó mới kiểm tra biến pass, hoặc một cách nhanh hơn, fix được hầu hết tất cả các lỗi SQL Injection mà chỉ cần sữ dụng một hàm có sẵn của PHP, đó là hàm addslashes .

- Xin nói một chút về hàm addslashes: hàm này sẽ trả về một chuỗi với dấu \ trước các ký tự cần trích dẫn trong Database, các ký tự đó là " \ và NUL (\0) .

- Cấu trúc hàm addslashes : string addslashes ( string str)

- Nhờ có hàm addslashes mà câu lệnh SQL của ta sẽ trở thành :

SELECT * FROM users WHERE user = "\" OR 1 OR user=\"" AND password = "$password"

- Như vậy thì câu lệnh SQL sẽ hoạt động đúng như chức năng của nó . Một số lỗi SQL Injection khác cũng có thể khắc phục bằng phương pháp này. Tôi cũng xin nhắc lại là phương pháp này chỉ fix được hầu hết tất cả các lỗi SQL Injection, tức là các lỗi do biến PHP gây ra, còn các lỗi do bản thân câu lệnh SQL thì cách này không có hiệu quả gì. Tuy nhiên nếu dùng phương pháp này và câu lệnh SQL chắc chắn thì tôi tin rằng bạn sẽ không còn lo lắng về SQL Injection.

2.PHP Injection

- Lỗi PHP Injection thường xảy ra với các script đọc File, tương tác hệ thống v.v. . Đây là một điển hình của PHP Injection:

Mã lệnh (php)
<?
//...
readfile($file);
//...
?>

- Thoạt nhìn thì không có lỗi gì, nhưng nếu như vì một lý do gì đó mà biến $file không được khai báo thì đây là một lỗi PHP Injection rất nặng. Nếu như Link đưa đến trang có lỗi như thế này : http://somehost.com/somescript.php?file=somescript.php

- Lúc này thì biến $file lại được khai báo bởi chính PHP, chức năng Regiser-Global và kết quả là sẽ đưa ra nội dung của file somescript.php hay bất cứ File nào trên hệ thống (kể cả File chức Password nếu hacker chịu khó mò và xem như host của chúng ta tiêu luôn).

- Nếu phân tích thì ta sẽ thấy rằng biến $file đã được khai báo do chức năng Register-Global (chức năng tự động đăng ký các biến trong GET, POST , COOKIE v.v...), và được fix một cách đơn giản là tắt chức năng này đi. Việc tắt chức năng này đi cũng không ảnh hưởng gì nhiều đến PHP.

II.Using Header

- Header là một hàm khác hay của PHP, hàm này sẽ send raw HTTP Header. Bạn có thể tìm tài liệu về HTTP Header trên rất nhiều diễn đàn lập trình khác. Trong bài viết này tôi sẽ đề cập đến một số header thông dụng.

1.Location Header

- Location Header có tác dụng chuyển trang yêu cầu đền một trang khác.

Mã lệnh (php)
header("location : http://php.net");
//Chuyển đến trang php.net

2.HTTP Command

- Lệnh Header cũng có thể sử dụng để gửi các lệnh của HTTP như 404 , 500 .v.v.

Mã lệnh (php)
header("HTTP/1.0 404 Not Found"); //Thông báo không tìm thấy của HTTP.

3.Attachment Header

- Header này có tác dụng thay tạo bảng Download, tải File do PHP tạo ra về máy ( UDU - Unlimited Database Upload , một script giúp ghi dữ liệu binary trong Database là một ví dụ về header này)

Mã lệnh (php)
<?
//Dạng File
header("Content-type: application/pdf");
//Tên File
header("Content-Disposition: attachment; filename=downloaded.pdf");
//Kích thước của File
header("Content-Length: " . filesize("original.pdf") );
//Nội dung cuả File
readfile('original.pdf');
?>

4.Authentication Header

- Đây là một header rất hay của PHP, nó sẽ tạo ra một bảng Login và yêu cầu nhập Username và Password, rất thích hợp cho trang dành cho các vùng hạng chế.

Mã lệnh (php)
<?
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
}
else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>

- Chú ý khi sữ dụng Header : header phải được gọi trước khi đưa nội dung vào trang, vì header phải được gửi trước khi gửi nội dung của trang hoặc bạn sẽ nhận được lỗi thông báo về Header, tuy nhiên bạn có thể tranh lỗi này bằng sữ dụng Output buffering mà tôi sẽ đề cập sau đây. Đây là một vd về sử dụng header sai:

Mã lệnh (html)
<html>
<?php
//Lỗi vì <html> đã được gửi rồi
header('Location: http://www.example.com/');
?>

III.Output Buffering

- Cũng như ASP, PHP cũng có chức năng tạo bộ đệm trang và chức năng này mạnh hơn rất nhiều so với ASP nhưng lại đòi hỏi cấu hình PHP. Tuy nhiên chức năng này hoạt động hầu hết trên Server mà không cần phải cấu hình lại PHP. Bạn có thể sử dụng các hàm Buffer của PHP hoặc tự tạo bộ đệm cho mình. Sử dụng Buffer sẽ giúp cho bạn tránh được lỗi header và có thể thay đổi nội dung của trang nhưng nó cũng yêu cầu một Server tốt, vì mỗi lần Buffer thì nó sẽ ghi vào bộ nhớ hay File.

1.Output Buffering Function

- Sau đây là một số hàm sử dụng Output Buffer:

- bool ob_start: bắt đầu sử dụng Buffer

- bool ob_end_flush: kết thúc sử dụng Buffer và gửi bộ đệm đến Client, chú ý là bộ đệm sẽ không thay đổi được nữa.

- bool ob_end_clean: kết thúc sử dụng Buffer và xóa toàn bộ bộ đệm .

- void ob_flush: gửi bộ đệm đến Client, bộ đệm không thay đổi được nữa.

- void ob_clean: xóa bộ đệm .

- string ob_get_contents: trả về nội dung bộ đệm .

- int ob_get_length: trả về kích thước bộ đệm .

- string ob_get_clean: trả về nội dung bộ đệm và xóa bộ đệm.

2.User Output Function

- Một cách khác để sử dụng Buffer là tạo một biến để chứa nội dung của trang trước khi đưa nội dung của trang ra. Cách này hơi tốn công so với sử dụng hàm của PHP nhưng nó đơn giản và không bị hạn chế.

IV.Search Array

- PHP là một ngôn ngữ Web mạnh, nhưng nó lại có một thiếu sót rất lớn là tìm kiếm trong Array, hầu hết các hàm của PHP chỉ sử dụng khi ta biết rỏ là key hay value đó hoặc có hoặc không trong Array đó, không thể nào tìm kiếm các key hay value liên quan hay hơi giống hay không phân biệt chữ hoa và chữ thường (sensitive) so với chuổi cần tìm .

1.PHP Array Function

- Sau đây là một số hàm tìm kiếm trong array của PHP:

mixed array_search ( mixed needle, array haystack [, bool strict])

- Hàm array_search tìm kiếm một giá trị trong array và trả về key của Value đó. Hàm này xem ra lại rất kém hiệu quả.

bool in_array ( mixed needle, array haystack [, bool strict])Hàm này cũng tương tự như array_search nhưng nó trả về giá trị TRUE nếu tìm thấy và FALSE nếu không tìm thấy trong Array.

- bool array_key_exists ( mixed key, array search) Hàm này là mô phỏng của in_array, điểm khác là nó kiểm tra key chứ không phải value.

- array array_keys ( array input [, mixed search_value])Cuối cùng là hàm array_key, hàm này sẽ trả về một array chứa Key của array cần tìm hay của một giá trị Array cần tìm. Hàm này không thể sử dụng để tìm kiếm nhưng có thể sử dụng trong việc tìm kiếm.

- Hầu hết các hàm liệt kê trên đều không hiệu quả, không thích hợp cho việc tìm kiếm Array, vì vậy mà tôi đã phải viết lại hàm SearchArray

2.SearchArray Function

- Hàm này do tôi viết lại để tìm kiếm trong Array

Mã lệnh (php)
function searcharray($search , $ARRAY , $checkkey = "" , $cmpflag = 0 , $breakonfind = "") {
$ret = array();$add = true;
foreach ($ARRAY as $key => $val) {
$add = false;
if ($checkkey != "") $cmp = $key;
else $cmp = $val;
if ($cmp <> "") {
switch ($cmpflag) {
case 1: //Compare From Left
if (strcasecmp(substr($cmp , 0 , strlen($search)) , $search) == 0) $add = true;
break;
case 2: //Compare From Right
if (strcasecmp(substr($cmp , strlen($cmp) - strlen($search)) , $search) == 0) $add = true;
break;
case 3: //Normal String Compare
if (strcasecmp($cmp , $search) == 0) $add = true;
break;
default: //In String Compare
if (stristr($cmp , $search)) $add = true;
break;
}
if ($add) {
if ($breakonfind != "") return $key;
$ret[] = $key;
}
}
}
return ($breakonfind != "") ? "" : $ret;
}

- Hàm này tìm kiếm rất hiệu quả, nó so sánh từng giá trị hay khóa trong Array và đưa ra kết quả tìm kiếm. Cách so sánh cũng tùy vào Flag mà ta đưa vào, và có thể chỉ tìm giá trị đầu tiên.

- Cách sữ dụng: hàm này có 5 tham số, trong đó có 2 tham số là bắt buộc.

- search: giá trị cần tìm .

- ARRAY: array cần kiểm tra .

- checkkey: nếu checkkey khác rỗng ("") , hàm sẽ kiểm tra khóa thay vì Value.

- cmpflag: cách kiểm tra: 1: so sánh chuổi từ bên trái, 2: so sánh chuổi từ bên phải, còn lại: hàm sẽ kiểm tra xem chuổi cần tìm có trong chuổi kiểm tra không. Tất cả các kiểu so sánh đều không phân biệt chữ hoa chữ thường.

- breakonfind: nếu khác rỗng ("") hàm sẽ trả về key của giá trị tìm thấy đầu tiên hay môt giá trị rỗng ("") nếu không tìm ra.

Hàm sẽ trả về một array chứa các giá trị tìm thấy nếu flag breakonfind không được set.

V.Make Configuration File

- Khi bạn tạo code một PHP script lớn như Forum hay Mysql Manager hay File Manager .v.v... hẳn các bạn sẽ dùng một File Config.php để lưu lại cấu hình PHP. Hàm savefile cũng do tôi viết có thể tạo một file config nhanh và rất hiệu quả.

Mã lệnh (php)
function savefile($F , $V) {
$result = "<?\n\n";
$f = fopen($F , "wb");
foreach($V as $key => $val) {
$result .= "\$" . addslashes($key) . " = " . parseval($val) . ";\n";
}
$result .= "\n?>";
fwrite($f , $result);
fclose($f);
}
function parseval($v) {
if (!is_array($v)) {
return "\"" . addslashes($v) . "\"";
}
else {
$result = "array(";
foreach ($v as $key => $value) {
$result .= '"' . addslashes($key) . '" => ' . parseval($value) . ",";
}
if (substr($result , strlen($result) - 1 , 1) == ",") $result = substr($result , 0 , strlen($result) - 1);
$result .= ")";
return $result;
}
}

- Hàm savefile sẽ mở File và sau đó sẽ chạy đệ quy parseval để tạo chuổi PHP về file Config.

- Ví dụ về sử dụng:

savefile("config.php" , array("MAINCONFIG" => $MAINCONFIG , "OTHERCONFIG" => $OTHERCONFIG);

- Hàm sẽ lưu vào file config.php 2 giá trị là MAINCONFIG theo biến $MAINCONFIG và OTHERCONFIG theo biến $OTHERCONFIG. File Config.php sẽ có nội dung như sau:

Mã lệnh (php)
<?
$MAINCONFIG = //Giá trị biến MAINCONFIG, tùy theo MAINCONFIG có dạng nào mà config được save theo dạng đó
$OTHERCONFIG = //Giá trị biến OTHERCONFIG, như trên
?>

VI.Use Pre-Made Script

- Xin kết thúc bài viết lập trình PHP nâng cao bằng một số Script thông dụng hiện nay.

1.Mysql Class

- Bạn có thể tìm thấy Mysql Class trong bộ Forum Invision Power Board, nó nằm ở thư mục IPB PATH\sources\Drivers/mySQL.php . Đây là một Class tương tác với mysql theo kiểu Object rất hay, nhưng điểm hay của nó là có thể tạo được câu lệnh SQL như INSERT, UPDATE từ các biến array rất chính xác (multi query). Tuy nhiên bạn cũng không nên sử dụng hoàn toàn class này mà nên dùng để tham khảo vì IPB không cho edit source.

2.phpMyAdmin

- Cái này thì chắc ai cũng biết , phpMyAdmin quản lý mySQL rất tuyệt vời, có thể download tại http://mysql.org

3.phpRemoteView

- Đây là một Script khá hay giúp bạn tương tác với hệ thống sử dụng PHP (cái này được xem là một công cụ hack thì đúng hơn , nhưng source của nó thì rất tuyệt). Script có thể download tại http://php.spb.ru/remview/

4.Net2ftp

- Một công cụ rất hay giúp bạn Connect tới các FTP Server sữ dụng PHP, có thể download tại http://www.net2ftp.com

5.pclTar , pclZip

- Hai công cụ tuyệt vời trong việc tạo các File Zip, Tar sử dụng PHP. Điểm đặc biệt là 2 script này không yêu cầu bất cứ gì từ PHP, bạn chỉ cần include vào và sử dụng. Có thể Download tại: http://www.phpconcept.net

6.Eskuel

- Một công cụ quản lý MySQL khác, công cụ này không bằng phpMyAdmin nhưng lại có một size rất khiêm tốn. Download tại: http://eskuel.sourceforge.net/site/upgrade...〈=english

7.Invision File Manager

- Ngoài Invision Power Board, hảng Invision còn viết một chương trình Manager rất hay, hổ trợ nhiều User và chức năng Zip File. Download tại trang web http://invisionpower.com

0 nhận xét:

Đăng nhận xét

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Blogger Templates