本文僅介紹PHP中的一些轉義函式的使用,
互聯網中一切的輸入都不可信,有用戶可以自由輸入的地方就可能存在著安全漏洞,轉義函式的使用就是為了提高系統的安全性,防止潛在的攻擊,如SQL注入,XSS攻擊等,本文介紹六個函式,分別是:
addcslashes();
addslashes();
mysql_real_escape_string();(mysqli_real_escape_string();)
htmlspecialchars();
htmlentities();
strip_tags();
1.addcslashes()函式及addslashes()函式
addcslashes() 函式回傳在指定字符前添加反斜杠的字串,且addcslashes() 函式對大小寫敏感,
需要注意:對以下字符應用 addcslashes() 時請小心:0(NULL), r(回車), n(換行), f 換頁)、t(制表符)以及 v(垂直制表符),在 PHP 中,\0, \r, \n, \t, \f 以及 \v 是預定義的轉義序列, (實驗說明,PHP7.4不再處理這些內容)
addslashes() 函式回傳在預定義字符之前添加反斜杠的字串,預定義字符是:
單引號(’)雙引號(")反斜杠(\)NULL
默認地,PHP 對所有的 GET、POST 和 COOKIE 資料自動運行 addslashes(),所以您不應對已轉義過的字串使用 addslashes(),因為這樣會導致雙層轉義(就目前實驗來看,本人PHP版本為7.4,PHP5.4版本以上已經不會默認對特殊字符轉義,特殊字符的處理已經完全交給用戶自己處理了)
可實驗如下,創建index.php檔案:
<?php
$str = "He's a young student, and has many interests.";
echo "<h3>".$str."</h3><br>";
echo "<h3>".addcslashes($str,'a')."</h3><br>";
echo "<h3>".addcslashes($str,'H')."</h3><br>";
echo "<h3>".addcslashes($str,' ')."</h3><br>";
echo "<h3>".addcslashes($str,'\'')."</h3><br>";
echo "<h3>".addcslashes($str,'a..z')."</h3><br>";
$s = '"There Are Heroisms All Round Us "\n.
Mr. Hungerton, her father, really was the most tactless person upon earth,—a fluffy, feathery, untidy cockatoo of a man, perfectly good-natured, but absolutely centered upon his own silly self. If anything could have driven me from Gladys, it would have been the thought of such a father-in-law. \t
---Doyle,Arthur Conan. (The Lost World) \r';
echo "<h3>".$s."</h3><br>";
echo "<h3>".addcslashes($s,'\n')."</h3><br>";
echo "<h3>".addcslashes($s,'\\n')."</h3><br>";
echo "<h3>".addcslashes($s,'n')."</h3><br>";
echo "<h3>".addslashes($s)."</h3><br>";
?>
開啟apache后,瀏覽器中輸入地址:https://127.0.0.1/index.php,首先對$str= "He’s a young student, and has many interests."分析,可獲得下列結果:

(1)為原輸入輸出,單引號并沒有被轉義,經實驗,通過GET獲得的資料也不會被轉義;
(2)對所有a進行轉義,變為“\a”;
(3)對H進行轉義,區分大小寫;
(4)對空格進行轉義;
(5)對單引號進行轉義,當然該陳述句也可以寫作:
echo "<h3>".addcslashes($str,"'")."</h3><br>";
(6)對范圍內的每個字符均進行轉義,a…z表示從a到z的所有字母;
以上的陳述句均是對一般字符的使用,下面考慮一些特殊字符:

按順序分析:
(1)僅列印出原輸入,作為對比;
(2)對字串“\n”進行轉義,這里千萬不要將其看做c語言中的換行符,它就是單斜杠“\”和字符n,就是對字串中的單斜杠“\”和字符n分別進行轉義;
(3)這里對字符“\n”進行轉義,結果和(2)一樣,這里重復了一個單斜杠,并不影響結果,仍舊對單斜杠和字母n進行轉義;
(4)正常轉義,僅對字母n進行轉義;
(5)所使用的是addslashes()函式,對預定義符號進行轉義;
總的來說,由于SQL注入中一般需要閉合單引號(除了數字型的注入,極少使用),使用addslashes()即可對單引號轉義,只能說從一定程度上減小注入的風險,并不能真正避免,對于addcslashes()函式,可以自定義轉義哪些字符,使用不當容易出錯,對于XSS攻擊,可以對"<",">"
進行轉義,但基本沒用,可以通過編碼的方式繞過,
2.mysql_real_escape_string()函式(PHP7中已移除,不推薦)
該函式于PHP 4.3.0,引入,在PHP 5.5.0開始廢棄,PHP 7.0.0 開始被移除,可以使用MYSQLi函式mysqli_real_escape_string()替換,二者功能上沒有區別,但是在引數位置順序上有所不同,關于mysql與mysqli的區別見參考資料3:mysql與mysqli的區別,請不要使用此函式,PHP7已經不支持此庫,
該部分由于已舍棄,這里僅作記錄,實際中請使用 mysqli_real_escape_string(),mysqli_real_escape_string()函式引數順序與此相反!
mysql_real_escape_string () 轉義 SQL 陳述句中使用的字串中的特殊字符,并考慮到連接的當前字符集,它會呼叫mysql庫的函式 mysql_real_escape_string, 在以下字符前添加反斜杠: \x00, \n, \r, , ', " 和 \x1a,為了安全起見,在向MySQL傳送查詢前,必須呼叫這個函式(除了少數例外情況),
格式:
mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier = NULL ] ) : string
引數說明:
| $unescaped_string | 必須存在的引數,規定要轉義的字串, |
|---|---|
| $link_identifier | 可選的引數,MySQL 連接,如不指定連接標識,則使用由 mysql_connect() 最近打開的連接,如果沒有找到該連接,會嘗試不帶引數呼叫 mysql_connect() 來創建,如沒有找到連接或無法建立連接,則會生成 E_WARNING 級別的錯誤, |
| 回傳值 | 轉義后的字串,或者錯誤資訊, |
由于此函式已舍棄,這里給出一個不使用轉義函式可能導致注入風險的例子:
在檔案夾/var/www/html/下建立檔案 SQLIjection.php,內容如下:
<?php
$serve = 'localhost:3306';
$user = 'lee';
$psd = '123';
$dbname = 'kali';
$link = mysqli_connect($serve,$user,$psd,$dbname);
// 檢測連接
if (!$link) {
die("Connection failed: " . mysqli_connect_error());
}
$query = 'select * from users where id = '.$_GET['id'].' and password = '.$_GET['password'];
//$query = 'select * from users where id = 1';
echo 'THE query is :'. $query;
echo "<br>";
mysqli_set_charset($link,'UTF-8'); // 設定資料庫字符集
$result = mysqli_query($link,$query);
$data = mysqli_fetch_all($result); // 從結果集中獲取所有資料
print_r($data);
?>
關于建立PHP與mysql互動程序的具體細節,見另一篇文章:PHP 7.4 與mysql(mariaDB)連接,資料庫內容相應的有所變化:

瀏覽器中輸入:http://localhost/SQLInjection.php?id=1&password=1234,有如下結果:

對于數字型的輸入,加不加引號都行,http://localhost/SQLInjection.php?id=‘1’&password=‘1234’,也是對的,但是含有字母則必須帶引號,由于沒有任何的過濾措施,存在注入風險,再次強調,一定要遵循 資料與代碼分離原則!,瀏覽器輸入:http://localhost/SQLInjection.phpid=1&password=’ 'or 1

可以發現,資料庫所有內容都被顯示出來,
3.mysqli_real_escape_string()函式
mysqli庫提供了面向物件和面向程序兩種書寫方式,根據個人習慣自由選擇,所以該函式也可以寫作:mysqli::real_escape_string;這里本人采用面向程序的方式,
| 程序化風格 | mysqli_real_escape_string ( mysqli $link , string $escapestr ) : string |
|---|---|
| 用來對字串中的特殊字符進行轉義, 以使得這個字串是一個合法的 SQL 陳述句, 傳入的字串會根據當前連接的字符集進行轉義,得到一個編碼后的合法的 SQL 陳述句, | |
| $link | 僅以程序化樣式:由mysqli_connect() 或 mysqli_init() 回傳的鏈接標識, |
| $escapestr | 需要進行轉義的字串,會被進行轉義的字符包括: NUL (ASCII 0),\n,\r,\,’," 和 Control-Z. |
該函式用來轉義輸入的字符,可以簡單驗證如下:檔案夾下創建mres.php檔案,
<?php
$serve = 'localhost:3306';
$user = 'lee';
$psd = '123';
$dbname = 'kali';
$link = mysqli_connect($serve,$user,$psd,$dbname);
// 檢測連接
if (!$link) {
die("Connection failed: " . mysqli_connect_error());
}
mysqli_query($link, "CREATE TABLE Users LIKE users");
$username = "'lee's";
// 由于未對 $username 進行轉義,此次查詢會失敗
if (!mysqli_query($link, "INSERT into Users (username) VALUES ('$username')")) {
printf("Error: %s\n", mysqli_sqlstate($link));
}
/*
$username = mysqli_real_escape_string($link, $username);
// 對 $username 進行轉義之后,查詢可以正常執行
if (mysqli_query($link, "INSERT into Users (username) VALUES ('$username')")) {
printf("%d Row inserted.\n", mysqli_affected_rows($link));
}
*/
mysqli_close($link);
?>
由于$username = “'lee’s”;輸入為 'lee’s ,單引號的存在會產生語法錯誤:

使用函式轉義可以解決這一問題:

查詢資料庫可以看到資料已經插入:

4.html string函式
除了Mysqli庫函式之外,PHP也自帶了一些字串處理函式:htmlspecialchars(); htmlentities(); strip_tags();這些函式主要針對XSS攻擊,
htmlspecialchars()函式
htmlspecialchars() 函式把預定義的字符轉換為 HTML 物體,
預定義的字符是:
& (和號)成為 &
" (雙引號)成為 "
’ (單引號)成為 '
< (小于)成為 <
> (大于)成為 >
| 語法 | htmlspecialchars(string,flags,character-set,double_encode) |
|---|---|
| string | 必需,規定要轉換的字串, |
| flags | 可選,規定如何處理引號、無效的編碼以及使用哪種檔案型別,可用的引號型別:ENT_COMPAT - 默認,僅編碼雙引號,ENT_QUOTES - 編碼雙引號和單引號,ENT_NOQUOTES - 不編碼任何引號, |
| character-set | 可選,一個規定了要使用的字符集的字串, |
| double_encode | 可選,布林值,規定了是否編碼已存在的 HTML 物體,TRUE - 默認,將對每個物體進行轉換,FALSE - 不會對已存在的 HTML 物體進行編碼, |
htmlentities()函式
htmlentities轉換所有的html標記,htmlspecialchars只格式化& 、’、"、 <、> 這幾個特殊符號,
使用htmlentities不指定編碼的話遇到中文會亂碼(指定htmlentities為UTF-8編碼,可以正常轉義),
其引數格式與htmlspecialchars()函式一樣,
<?php
$str="<script>alert('123')</script>";
echo htmlentities($str, ENT_QUOTES);
//ENT_COMPAT - 默認,僅編碼雙引號,
//ENT_QUOTES - 編碼雙引號和單引號,
//ENT_NOQUOTES - 不編碼任何引號,
//輸出結果為<script>alert('123')</script>gt;
//頁面展示: <script>alert('123')</script>
strip_tags()函式
strip_tags() 函式剝去字串中的 HTML、XML 以及 PHP 的標簽,該函式始侄訓剝離 HTML 注釋,這點無法通過 allow 引數改變,該函式是二進制安全的,
| 語法 | strip_tags(string,allow) |
|---|---|
| string | 必需,規定要檢查的字串, |
| allow | 可選,規定允許的標簽,這些標簽不會被洗掉, |
<?php
echo strip_tags("Hello <b><i>world!</i></b>","<b>");
?>

參考資料:
- mysql_real_escape_string()函式官方檔案
- mysqli_real_escape_string()函式官方檔案
- mysql與mysqli的區別
- PHP 7.4 與mysql(mariaDB)連接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/168471.html
標籤:AI
上一篇:學生,打算購買服務器,做一個小型站,服務器需要什么配置
下一篇:MySQL 關閉安全更新模式
