Web安全防護(二)

女友在高考發表於2022-01-25

點選劫持

點選劫持,也稱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跳轉漏洞校驗繞過

  1. 域名字串校驗
//獲取引數
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. 程式碼固定跳轉地址,不讓使用者隨意輸
  2. 跳轉目標地址採用對映機制,如 1代表aaa.com,2代表bbb.com這樣,使用者只能輸1和2才能過校驗
  3. 合理充分的校驗機制,校驗跳轉的目標地址,非己方的地址跳轉時可以提示使用者,類似知乎做的那種。

Session攻擊

通過竊取使用者SessionId,使用SessionId登入進目標賬戶的攻擊方法。如果SessionId是儲存在Cookie中的,則這種攻擊可以稱為Cookie劫持。

3.1 Session劫持

攻擊原理:

  1. 目標使用者登入網站
  2. 登入成功後,使用者的SessionId伺服器會認為是已登入的,可以做一些他許可權內的操作
  3. 攻擊者通過某種攻擊手段捕獲Session ID
  4. 攻擊者通過捕獲到的Session ID訪問站點即可獲得目標使用者合法會話。

獲取SessionId的方式有多種:

  1. 暴力破解:不斷嘗試各種Session ID
  2. 預測:如果Session ID使用非隨機的方式產生,那麼就有可能計算出來
  3. 竊取:使用網路嗅探、本地木馬竊取、XSS攻擊等方法

防禦方法:

  1. Cookie HttpOnly
  2. Cookie Secure,是設定Cookie時,可以設定的一個屬性,設定了之後只有https訪問時,瀏覽器才會傳送該cookie。這樣攻擊者從網路上竊聽到,也是拿到一個加密的cookie
response.setHeader("SET-
HEADER","user="+request.getParameter("cookie")+";HttpOnly;Sec
ure");

3.2 會話固定

會話固定是讓使用者使用黑客預先設定的sessionID進行登入,這樣同樣黑客能拿到使用者SessionId。

攻擊步驟:

  1. 攻擊者通過某種手段重置使用者的SessinoID,然後監聽使用者會話狀態
  2. 目標使用者攜帶攻擊者設定的Session ID登入站點
  3. 攻擊者通過Session ID獲得合法會話

攻擊者如果讓目標使用黑客的Session ID呢?如果是儲存在Cookie中是比較難做的,但如果是SessionID儲存在URL中,則攻擊者只要誘導使用者開啟這個URL即可。

防禦方法:

  1. 使用者登入的時候就進行重置SessionID
// 會話失效
session.invalidate();
// 會話重建
session=request.getSession(true);
  1. SessionID閒置過久時,進行重置
  2. 設定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持久化地儲存在本地。

防護方案:

  1. 可以設定一個固定的時間,如3天后就強制過期,但是也影響了正常使用者
  2. 比如使用者的IP、UserAgent資訊發生編號,就可以強制銷燬當前的Session,並要求使用者重新登入

注入攻擊

注入攻擊是Web安全領域中一種最常見的攻擊方式。XSS本質上也是一種針對HTML的注入攻擊。注入攻擊的本質,是把使用者輸入的資料當做了程式碼執行。這裡有兩個關鍵條件,第一個是使用者能控制輸入,第二個是原本程式要執行的程式碼拼接了使用者輸入的資料。解決注入攻擊的核心思想:資料與程式碼分離原則

4.1 SQL隱碼攻擊

本應該輸入正常的資料,而黑客卻輸入一些sql語句。如果應用程式比較脆弱的話,則可能應用程式會被攻擊。

最簡單的示例就是一個:查詢某個使用者

String query = "select * from accounts where name ='"+request.getParameter("name")+"';

使用者如果輸張三李四是沒問題的,如果輸入 李四 or 1=1 那麼它會查到所有使用者資料。

容易導致SQL隱碼攻擊的弱點:

  1. 應用程式中使用字串連線方式或聯合查詢方式組合SQL語句
  2. 應用程式連線資料庫時使用許可權過大的賬戶(很多開發人員喜歡直接用管理員賬戶)
  3. 未校驗使用者輸入的字串

攻擊步驟:

  1. SQL盲注

所謂盲注,就是在伺服器沒有返回錯誤資訊的情況下完成的注入攻擊。最常見的盲注驗證方法是構造簡單的條件語句,根據返回的頁面是否變化來判斷是否存在漏洞。

示例:下面是一個根據userId查詢使用者的功能:

1) 我先輸入

1 ' and 1=1 #


發現能查詢到資料

2)再輸入

1 ' and 1=2 # 發現查不出資料,證明注入成功。

  1. 猜解資料庫

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#

成功爆出了某網站的使用者名稱和密碼

  1. 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容器解釋並執行了使用者上傳的指令碼
  • 上傳檔案是病毒、木馬檔案,然後誘使使用者或管理員下載執行
  • 上傳檔案是釣魚圖片或為包含了指令碼的圖片,在某些版本的瀏覽器中會被作為指令碼執行,被用於釣魚和欺詐。

防護方案:

  1. 檢查上傳副檔名
  2. 上傳檔案的目錄必須是http請求無法直接訪問到的。如果需要訪問,需要上傳到其他(和web伺服器不同的)域名下,並設定該目錄為不可執行目錄
  3. 上傳檔案要儲存的檔名和目錄名由系統根據時間生成,不允許使用者自定義
  4. 圖片上傳,要通過處理(縮圖、水印等),無異常才能儲存到伺服器
  5. 上傳檔案需要做日誌記錄

5.2 檔案下載和目錄瀏覽漏洞

檔案下載和目錄瀏覽漏洞是屬於程式設計和編碼上的不嚴謹導致的。處理使用者請求下載檔案時,使用者提交檔案路徑,就把伺服器上對應的檔案傳送給使用者,這就造成了任意檔案下載危險。如果使用者提交目錄,就把目錄下的檔案列表發給使用者,會造成目錄遍歷安全威脅。良好的設計應該是:不允許使用者提交任意檔案路徑進行下載,而是使用者單機下載按鈕預設傳遞ID到後臺程式。

防護方案:

  1. 要下載的檔案地址儲存在資料庫中
  2. 檔案路徑儲存至資料庫,讓使用者提交檔案對應ID下載檔案
  3. 下載檔案之前做許可權判斷
  4. 檔案放在web無法直接訪問的目錄下
  5. 記錄檔案下載日誌
  6. 不允許提供目錄遍歷服務

訪問控制

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攻擊。攻擊原理是:針對一些耗費資源較大的應用頁面不斷髮起請求,以達到消耗伺服器資源的目的。

防護方案:

  1. 程式碼要做好效能優化,合理的使用快取,減輕資料庫負擔
  2. 網路架構優化,善用負債均衡,避免使用者流量集中在單臺伺服器,同時可以充分利用CDN和映象站點的分流作用,緩解主站的壓力。
  3. 使用頁面靜態化技術,利用客戶端瀏覽器的快取功能或伺服器的快取功能,CDN節點的緩衝服務,均可以降低伺服器的檢索壓力和計算壓力。
  4. 也可以使用一些對抗手段。如限制每個ip的請求頻率,超出頻率的ip加入黑名單

IP黑白名單的開發

可以使用OpenResty+Lua指令碼實現。也可以使用KONG

相關文章