點選劫持
點選劫持,也稱UI覆蓋攻擊
1.1 iframe覆蓋攻擊
黑客建立一個網頁,用iframe包含了目標網站,並且把它隱藏起來。做一個偽裝的頁面或圖片蓋上去,且按鈕與目標網站一致,誘導使用者去點選。偽裝的按鈕背後可能就會執行了危險操作。
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<head>
<title>點選劫持 POC</title>
<style>
iframe {
width: 1440px;
height: 900px;
position: absolute;
top: -0px;
left: -0px;
z-index: 2;
-moz-opacity: 0;
opacity: 0;
filter: alpha(opacity=0);
}
button {
position: absolute;
top: 270px;
left: 1150px;
z-index: 1;
width: 90px;
height:40px;
}
</style>
</head>
<body>
<button>美女圖片</button>
<img src="http://pic1.win4000.com/wallpaper/2018-03-
19/5aaf2bf0122d2.jpg">
<iframe src="http://i.youku.com/u/UMjA0NTg4Njcy"
scrolling="no"></iframe>
</body>
</html>
防護方案:
使用一個HTTP頭-X-Frame-Options。它可以設定frame的載入許可權。它有三個可選的值:
- DENY:瀏覽器會拒絕當前頁面載入任何frame頁面
- SAMEORIGIN:frame頁面的地址只能為同源域名下的頁面
- ALLOW-FROM uri:允許frame載入的頁面地址
nginx配置:
add_header X-Frame-Options SAMEORIGIN;
1.2 圖片覆蓋攻擊
圖片覆蓋攻擊,攻擊者使用一張或多張圖片,利用圖片的style或者能夠控制的CSS,將圖片覆蓋在網頁上,形成點選劫持。
<a href="http://tieba.baidu.com/f?kw=%C3%C0%C5%AE">
<img src="XXXXXX"
style="position:absolute;top:90px;left:320px;" />
</a>
你以為你點了圖片,其實你點了其他的連結。
防護方案:
在防禦圖片覆蓋攻擊時,需要檢查使用者提交的HTML程式碼中,img標籤的style屬性是否可能導致浮出。
URL跳轉漏洞
URL跳轉漏洞(URL重定向漏洞),跳轉漏洞一般用於釣魚攻擊
攻擊原理:
URL跳轉漏洞本質上是利用Web應用中帶有重定向功能的業務,將使用者從一個網站重定向到另一個網站。
示例:http://www.
aaa.com?returnUrl=http://www.evil.com,www.aaa.com 有一個功能會取到returnUrl後的路徑,然後跳轉。這種功能就會被黑客利用,跳轉到他想跳轉的其他頁面上去。
一般容易出現的漏洞的點:
- 登入跳轉、第三方授權
- 分享
- 收藏
URL跳轉漏洞校驗繞過
- 域名字串校驗
//獲取引數
String url = request.getParameter("returnUrl");
//判斷是否包含域名
if (url.indexOf("www.abc.com ") !=-1){
response.sendRedirect(url);
}
黑客可以註冊一個包含abc.com的域名來繞過,如:
http://www.abc.com?returnUrl=http://www.abc.com.evil.com
2. 利用URL的各種特性符號
http://www.aaa.com?returnUrl=http://www.evil.com?www.aaa.com
http://www.aaa.com?returnUrl=http://www.evil.comwww.aaa.com
http://www.aaa.com?returnUrl=http://www.aaa.com@www.evil.com
http://www.aaa.com?returnUrl=http://www.evil.com#www.aaa.com
防護方案
- 程式碼固定跳轉地址,不讓使用者隨意輸
- 跳轉目標地址採用對映機制,如 1代表aaa.com,2代表bbb.com這樣,使用者只能輸1和2才能過校驗
- 合理充分的校驗機制,校驗跳轉的目標地址,非己方的地址跳轉時可以提示使用者,類似知乎做的那種。
Session攻擊
通過竊取使用者SessionId,使用SessionId登入進目標賬戶的攻擊方法。如果SessionId是儲存在Cookie中的,則這種攻擊可以稱為Cookie劫持。
3.1 Session劫持
攻擊原理:
- 目標使用者登入網站
- 登入成功後,使用者的SessionId伺服器會認為是已登入的,可以做一些他許可權內的操作
- 攻擊者通過某種攻擊手段捕獲Session ID
- 攻擊者通過捕獲到的Session ID訪問站點即可獲得目標使用者合法會話。
獲取SessionId的方式有多種:
- 暴力破解:不斷嘗試各種Session ID
- 預測:如果Session ID使用非隨機的方式產生,那麼就有可能計算出來
- 竊取:使用網路嗅探、本地木馬竊取、XSS攻擊等方法
防禦方法:
- Cookie HttpOnly
- Cookie Secure,是設定Cookie時,可以設定的一個屬性,設定了之後只有https訪問時,瀏覽器才會傳送該cookie。這樣攻擊者從網路上竊聽到,也是拿到一個加密的cookie
response.setHeader("SET-
HEADER","user="+request.getParameter("cookie")+";HttpOnly;Sec
ure");
3.2 會話固定
會話固定是讓使用者使用黑客預先設定的sessionID進行登入,這樣同樣黑客能拿到使用者SessionId。
攻擊步驟:
- 攻擊者通過某種手段重置使用者的SessinoID,然後監聽使用者會話狀態
- 目標使用者攜帶攻擊者設定的Session ID登入站點
- 攻擊者通過Session ID獲得合法會話
攻擊者如果讓目標使用黑客的Session ID呢?如果是儲存在Cookie中是比較難做的,但如果是SessionID儲存在URL中,則攻擊者只要誘導使用者開啟這個URL即可。
防禦方法:
- 使用者登入的時候就進行重置SessionID
// 會話失效
session.invalidate();
// 會話重建
session=request.getSession(true);
- SessionID閒置過久時,進行重置
- 設定HttpOnly
3.3 Session保持攻擊
一般情況下,Session是有生命週期的,當使用者長時間未活動,或者使用者點選退出後,伺服器將銷燬Session。但如果攻擊者拿到了一個使用者的Session,它可以通過不停的發起訪問請求,讓Session一直存活。
<script>
//要保持session的url
var url =
"http://bbs.yuanjing.com/wap/index.php?/sid=LOXSAJH4M";
//定時任務
window.setInterval("keeyId()",6000);
function keepsid(){
document.getElementById("iframe1").src=url+"&time"+Math.rand
om();
}
</script>
<iframe id="iframe1" src=""/></iframe>
攻擊者設定可以為Session Cookie增加一個Expire事件,使得原本瀏覽器關閉就會失效的Cookie持久化地儲存在本地。
防護方案:
- 可以設定一個固定的時間,如3天后就強制過期,但是也影響了正常使用者
- 比如使用者的IP、UserAgent資訊發生編號,就可以強制銷燬當前的Session,並要求使用者重新登入
注入攻擊
注入攻擊是Web安全領域中一種最常見的攻擊方式。XSS本質上也是一種針對HTML的注入攻擊。注入攻擊的本質,是把使用者輸入的資料當做了程式碼執行。這裡有兩個關鍵條件,第一個是使用者能控制輸入,第二個是原本程式要執行的程式碼拼接了使用者輸入的資料。解決注入攻擊的核心思想:資料與程式碼分離原則
4.1 SQL隱碼攻擊
本應該輸入正常的資料,而黑客卻輸入一些sql語句。如果應用程式比較脆弱的話,則可能應用程式會被攻擊。
最簡單的示例就是一個:查詢某個使用者
String query = "select * from accounts where name ='"+request.getParameter("name")+"';
使用者如果輸張三李四是沒問題的,如果輸入 李四 or 1=1 那麼它會查到所有使用者資料。
容易導致SQL隱碼攻擊的弱點:
- 應用程式中使用字串連線方式或聯合查詢方式組合SQL語句
- 應用程式連線資料庫時使用許可權過大的賬戶(很多開發人員喜歡直接用管理員賬戶)
- 未校驗使用者輸入的字串
攻擊步驟:
- SQL盲注
所謂盲注,就是在伺服器沒有返回錯誤資訊的情況下完成的注入攻擊。最常見的盲注驗證方法是構造簡單的條件語句,根據返回的頁面是否變化來判斷是否存在漏洞。
示例:下面是一個根據userId查詢使用者的功能:
1) 我先輸入
1 ' and 1=1 #
發現能查詢到資料
2)再輸入
1 ' and 1=2 # 發現查不出資料,證明注入成功。
- 猜解資料庫
3)繼續輸入利用order by猜列數
1' order by 1 #
成功,然後輸入 1' order by 2 # ,依次遞增,直到提示
Unknown column '3' in 'order clause'
成功得到該表的列數。
4)知道列數之後,使用union select 聯合查詢獲取更多的資訊,union 查詢的使用前提是關聯查詢的兩個查詢列數要一致
1 ' union select database(),user() #
查詢到資料庫名和當前查詢的使用者名稱
5)繼續查詢當前資料庫版本、作業系統
1 ' union select version(),@@version_compile_os#
6)根據資料庫名,查詢裡面的表
1 ' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa' #
7)猜users表的欄位,根據經驗試試是不是user和password
1' union select user,password from users#
成功爆出了某網站的使用者名稱和密碼
- ORM注入
1) Mybatis:
${}:單純替代,純粹的將引數傳進去,沒有做任何的轉義操作和預編譯。
#{}: Mybatis會通過預編譯機制生成PreparedStatement引數,然後再安全的給引數賦值
${}是存在注入風險的。
2) Hibernate
usernameString//前臺輸入的使用者名稱
passwordString//前臺輸入的密碼
//hql語句
String queryString = "from User t where t.username= " +
usernameString + " and t.password="+ passwordString;
//執行查詢
List result = session.createQuery(queryString).list();
通過hql拼接的方式不安全。建議用引數繫結:
usernameString//前臺輸入的使用者名稱
passwordString//前臺輸入的密碼
//hql語句
String queryString = "from User t where t.username:
usernameString and t.password: passwordString";
//執行查詢
List result = session.createQuery(queryString)
.setString("usernameString ",
usernameString )
.setString("passwordString",
passwordString)
.list();
3)JDBC:使用預處理執行SQL語句,對所有傳入SQL語句中的變數做繫結,這樣使用者拼接進來的變數無論內容是什麼,都會被當做替代符號"?"所替代的值。
示例:
String sql = "select * from users where userid = " + userid;
如果使用者輸入userid是"1;delete users;"會被編譯成2條sql,那麼users表會被非法刪除。
但是如果是預編譯的方式,那麼會編譯成一條sql,查詢userid為'"1;delete users;"的使用者,查詢結果會是不存在,不會存在危險。
4.2 XML注入
XML注入是將使用者錄入的資訊作為XML節點。
示例:
//userData是準備儲存的XML資料,接受了name和email兩個使用者提交的資料
String userData = "<USER >"+
"<name>"+
request.getParameter("name")+
"</name>"+
"<email>"+
request.getParameter("email")+
"</email>"
"</USER>"
//儲存XML資料
userDao.save(userData);
如果使用者輸入的時候name輸入張三,email輸入:
user1@lagou.com</email></USER><USER><name>user2</name>
<email>user2@lagou.com
這樣就惡意構造了一個xml,拼接起來一次儲存了兩條資料。
防護方案:
對xml資料進行轉義:
String userData = "<USER>"+
"
<name>"+StringUtil.xmlEncode(request.getParameter("name"))+"
</name>"+
"
<email>"+StringUtil.xmlEncode(request.getParameter("email"))+
"</email>"+
"</USER>";
4.3 程式碼注入
web應用程式中如果有允許接收使用者輸入一段程式碼並執行。那麼使用者可以根據這個功能寫一個遠端控制木馬,進行惡意攻擊。程式碼注入往往是由一些不安全的函式或者方法引起的,其中的典型代表就是eval()
public static void main(String[] args) {
//在Java中也可以實施程式碼注入,比如利用Java的指令碼引擎。
ScriptEngineManager manager = new
ScriptEngineManager();
//獲得JS引擎物件
ScriptEngine engine =
manager.getEngineByName("JavaScript");
try {
//使用者錄入
String param = "hello";
String command = "print('"+param+"')";
//呼叫JS中的eval方法
engine.eval(command);
} catch (ScriptException e) {
e.printStackTrace();
}
}
攻擊示例:
hello'); var fImport = new JavaImporter(java.io.File);
with(fImport) { var f = new File('new'); f.createNewFile(); }
防護方案:
對抗程式碼注入,需要禁止eval()等可以執行命令的函式,如果一定要用,則需要對使用者輸入的資料進行處理。如只能由開發人員定義程式碼內容,使用者只能提交對應的id”1、2、3“等引數。
4.4 OS命令注入
OS命令注入(作業系統命令注入),僅當Web應用程式程式碼包括作業系統呼叫,並且使用了使用者的輸入內容。
示例:
應用程式開發人員希望使用者能夠在Web應用程式中檢視Ping命令的輸出。使用者正常輸入ip,那還好。
如果輸入:
127.0.0.1 && whoami
或者
127.0.0.1 && ps -ef
就能夠執行一些危險的操作。
防護方案:
最有效的方法就是不要再應用程式程式碼中呼叫OS命令。如果非要這麼搞,那麼還是一樣需要對使用者輸入進行嚴格的驗證。
檔案操作防護
5.1 檔案上傳漏洞
網際網路當中,我們經常用到檔案上傳功能,傳excel、傳圖片、傳視訊等等。檔案上傳後,伺服器的處理邏輯如果做的不夠安全,就會導致漏洞的產生。
檔案上傳後導致的常見安全問題一般有:
- 上傳檔案是Web指令碼語言,伺服器的Web容器解釋並執行了使用者上傳的指令碼
- 上傳檔案是病毒、木馬檔案,然後誘使使用者或管理員下載執行
- 上傳檔案是釣魚圖片或為包含了指令碼的圖片,在某些版本的瀏覽器中會被作為指令碼執行,被用於釣魚和欺詐。
防護方案:
- 檢查上傳副檔名
- 上傳檔案的目錄必須是http請求無法直接訪問到的。如果需要訪問,需要上傳到其他(和web伺服器不同的)域名下,並設定該目錄為不可執行目錄
- 上傳檔案要儲存的檔名和目錄名由系統根據時間生成,不允許使用者自定義
- 圖片上傳,要通過處理(縮圖、水印等),無異常才能儲存到伺服器
- 上傳檔案需要做日誌記錄
5.2 檔案下載和目錄瀏覽漏洞
檔案下載和目錄瀏覽漏洞是屬於程式設計和編碼上的不嚴謹導致的。處理使用者請求下載檔案時,使用者提交檔案路徑,就把伺服器上對應的檔案傳送給使用者,這就造成了任意檔案下載危險。如果使用者提交目錄,就把目錄下的檔案列表發給使用者,會造成目錄遍歷安全威脅。良好的設計應該是:不允許使用者提交任意檔案路徑進行下載,而是使用者單機下載按鈕預設傳遞ID到後臺程式。
防護方案:
- 要下載的檔案地址儲存在資料庫中
- 檔案路徑儲存至資料庫,讓使用者提交檔案對應ID下載檔案
- 下載檔案之前做許可權判斷
- 檔案放在web無法直接訪問的目錄下
- 記錄檔案下載日誌
- 不允許提供目錄遍歷服務
訪問控制
6.1 功能許可權漏洞
功能許可權漏洞是指Web應用沒有做許可權控制,或僅僅在選單上做了許可權控制,導致惡意使用者只要猜到了其他頁面的URL地址,就可以訪問到他許可權外的頁面和資料。
防護方案:
針對任何URL,每次使用者訪問,都要判斷使用者是否有訪問此URL的許可權。
6.2 資料許可權漏洞
這種問題出現在未對使用者與資料級別之間建立關係,如使用者A和使用者B都有查詢訂單的許可權,但是A只能查詢A的訂單,B只能查B的訂單。如果只校驗使用者是否有某個功能的許可權,不校驗時候有這個資料的許可權,就會出現越權問題。
防護方案:
根據使用者的ID做好資料級許可權控制,比如針對CRUD操作進行身份驗證,且對使用者訪問的資料進行資料許可權校驗,防止通過修改ID的方式檢視別人的資料。
DDOS攻擊
7.1 DDOS攻擊
DDOS(Distributed Denial of Service)又稱為分散式拒絕服務,DDOS是利用合理的請求造成資源過載,導致服務不可用。常見的DDOS攻擊有SYN flood、UDP flood、ICMP flood等。其中SYN flood是一種最為經典的DDOS攻擊,其發現於1996年,至今仍然保持著非常強大的生命力。SYN flood如此猖獗是因為它利用了TCP協議設計中的缺陷,而TCP/IP是整個網際網路的基礎,想要修復這樣的缺陷機不是不可能的事情。
SYN flood攻擊原理:
SYN flood攻擊是根據TCP協議的三次握手過程進行的攻擊。在TCP伺服器收到SYN請求包時,在傳送ACK包回去之前,TCP伺服器需要先分配一個資料區專門服務於這個快形成的TCP連線。
在常見的SYN flood攻擊中,攻擊者短時間內傳送大量的SYN包給受害者伺服器,伺服器需要為每個TCP SYN包分配一個資料區,只要這些SYN包具有不同的源地址。這將給受害者伺服器造成很大的系統負擔,最終導致系統不能正常工作。
SYN flood防護方案:
syn cookie:
syn cookie是通過修改TCP三次握手協議,來專門防禦DDOS的一種手段。伺服器收到客戶端的SYN包,並且返回一個ACK+SYN包時,不專門分配一個資料區,而是根據這個包計算出一個cookie值。然後再收到ACK包時,伺服器根據這個cookie值檢查這個ACK包是否合法。如果合法,再分配專門的資料區進行處理未來的TCP連線。
7.2 CC攻擊
CC攻擊是DDOS攻擊的一種,可以看作是應用層面的DDOS攻擊。攻擊原理是:針對一些耗費資源較大的應用頁面不斷髮起請求,以達到消耗伺服器資源的目的。
防護方案:
- 程式碼要做好效能優化,合理的使用快取,減輕資料庫負擔
- 網路架構優化,善用負債均衡,避免使用者流量集中在單臺伺服器,同時可以充分利用CDN和映象站點的分流作用,緩解主站的壓力。
- 使用頁面靜態化技術,利用客戶端瀏覽器的快取功能或伺服器的快取功能,CDN節點的緩衝服務,均可以降低伺服器的檢索壓力和計算壓力。
- 也可以使用一些對抗手段。如限制每個ip的請求頻率,超出頻率的ip加入黑名單
IP黑白名單的開發
可以使用OpenResty+Lua指令碼實現。也可以使用KONG