Web安全概覽

前言

介紹一下 Web 端相關的攻擊手法及原理,包括但不限於 前端 後端 運維javascript

本文後端語言將使用PHP,由於通過對比,PHP做爲後端代碼演示,是最顯而易見的。php

以及本文介紹的全部攻擊手法都將提供Docker 靶場,方便後續你們自行研究、測試。html

此篇文章是由我以前寫的安全文章進行了部分彙總、優化及添加。若是你們比較感興趣,能夠去Freebuf Black-Hole看我以前寫的文章。前端

前端

XSS

XSS本質就是在別人的瀏覽器裏執行你的JavaScript代碼,其餘都是一種輔助手段。java

DOM XSS

利用JavaScript操做DOM的特性,來作到攻擊git

常常出現的狀況:先後端分離架構github

不少開發者,都知道不到萬不得已不要使用eval函數,不使用的緣由其中一點就是不安全,可是難道不使用eval就不會有安全問題麼?答案是否認的。web

見下面的代碼:sql

<script>
  window.open(new URL(location.hash.slice(1)).href)
</script>複製代碼

爲了更好的說明,我這裏簡單的把做用說明一下:docker

假設當前url爲 http://baidu.com/#http://360.cn,那麼location.hash.slice(1)的結果就是http://360.cn

new URL(url).href則是會對url進行解析,並取出解析後的url。若是你的url不知足它內部的判斷,則會報錯。

是否是以爲這段代碼沒什麼問題。畢竟有new URL()這種瀏覽器內置函數幫咱們作了過濾。

OK,那咱們就要去攻破這個函數的判斷。下圖爲URL接口規範中的列表:

咱們能夠看到hello:world是符合規範的。並且hello:正好又是JavaScript裏的標記,相似於C語言中的goto。那咱們更改url爲: http://baidu.com/#javascript:alert(1)。則會成功觸發漏洞。

Docker 靶場

後端

反射XSS

DOM XSS也屬於反射型 XSS,通常而言統稱都叫反射 XSS,只有當須要劃分比較細時,纔會分開來。

由於前/後端沒有作好相對應的過濾,致使的問題

常常出現的狀況:MVC架構

由於像MVC這種架構,實際上是在後端語言中編寫前端代碼,在訪問url的時候,會先由後端根據請求去構造前端頁面,再返回前端源碼到瀏覽器端,而這個過程當中,若是出現了XSS漏洞,又由於後端參與其中,因此咱們通常認爲這是反射型XSS

見下面的 PHP 代碼:

<?php
  // 關閉瀏覽器的XSS檢測機制
  header("X-XSS-Protection: 0;");

  $bg = $_GET['bg'];
  if (empty($bg)) {
    $bg = '999';
  }
  echo "<div style='width: 120px; height: 120px; background-color:#$bg'>我是一隻小方塊</div>";
?>複製代碼

能夠看到,這段代碼將會獲取url參數中的bg來獲取背景顏色。乍一看,好像沒什麼問題。可是要知道其中$bg是可控的。那咱們只須要把裏面的標籤閉合掉就行。見下面:

http://127.0.0.1:8082/?bg=123' onclick='alert(1)

上面的代碼放在bg參數裏,那代碼就變成了

<div style='width: 120px; height: 120px; background-color:#123' onclick='alert(1)'>我是一隻小方塊</div>

Docker 靶場

存儲型XSS

在反射XSS的基礎上,作了一步 入庫的操做

見下面的代碼:

// 獲取客戶端的IP地址
// 此段代碼來之:https://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php
$ipaddress = 'UNKNOWN';
$keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR');
foreach($keys as $k) {
  if (isset($_SERVER[$k]) && !empty($_SERVER[$k])) {
    $ipaddress = $_SERVER[$k];
    break;
  }
}

// 獲取內容,並對內容作編碼過濾
$content = htmlspecialchars($_POST['content'], ENT_QUOTES);

$sql = "INSERT INTO xss.message (content, ip) VALUES ('$content', '$ipaddress')";
$conn->query($sql);複製代碼

這段代碼看起來是沒有任何問題的,由於咱們已經對content參數作了進一步的編碼過濾。

htmlspecialchars(string,ENT_QUOTES) 此方法的編碼規則爲:

& 編碼爲 &amp;

" 編碼爲 &quot;

' 編碼爲 &#039;

< 編碼爲 &lt;

> 編碼爲 &gt;

那即便咱們寫入了HTML標籤等代碼,也會被轉碼,假如咱們提交的內容爲<script>alert(1)</script>那在數據庫的裏表現就會變成: &lt;script&gt;alert(1)&lt;/script&gt;

那難道沒有辦法繞過去麼?答案固然是能夠。

能夠看到,這段代碼不止把內容入庫了,還把用戶的IP也入庫了。那問題就出現了,CLIENT-IPX_FORWARDED_FOR是用戶可控的。只須要安裝 ModHeader 這個瀏覽器插件便可如圖:

Imgur

修改後,再去從新提交一次,就會發現已經成功入庫了,如圖:

Imgur

Docker 靶場

CSRF

CSRF能夠理解爲是一種借刀殺人的手法,通常出如今表單提交裏。最多見的是出現的開源項目裏,好比各種CMS。

<form method="post" action="addAdminUser.php">
  <div class="input-group">
    <label for="username">要添加的管理員帳號: </label>
    <input type="input" name="username">
  </div>
  <div class="input-group">
    <label for="password">要添加的管理員密碼: </label>
    <input type="password" name="password">
  </div>
  <div class="input-group">
    <button type="submit">添加</button>
  </div>
</form>複製代碼

見上面代碼,此代碼存在於管理員後臺裏。用於添加管理員帳號。而且 addAdminUser.php 裏是有對當前用戶的 Cookies 作了校驗,非管理員帳戶不能添加。

可是這個表單裏沒有 驗證碼Token ,以及 addAdminUser.php 裏沒有作 referer 來源校驗。

就會出現 CSRF 漏洞。

由於瀏覽器發現你請求了某個資源後,會自動把你未過時的 Cookies 加入到請求頭裏。也就是說,即便是在其餘網站裏,發送了添加管理員的請求,會自動把你登錄後的 Cookies 加入到請求裏,服務端會認爲是你本人觸發的(由於 Cookies 校驗成功)

至於爲何這裏 Cors 沒有起到做用,是由於這種方式,請求後是拿不到任何返回信息的,因此 Cors 並不會攔截。若是你使用 Ajax來請求,是確定會被攔截掉,由於 Ajax 請求是能夠拿到返回信息,全部會被 Cors 攔截掉。

那除了 form 標籤,還有什麼方法能夠進行攻擊呢?在 w3c cors 規範中,有這麼一句話:

A simple cross-origin request has been defined as congruent with those which may be generated by currently deployed user agents that do not conform to this specification. Simple cross-origin requests generated outside this specification (such as cross-origin form submissions using GET or POST or cross-origin GET requests resulting from script elements) typically include user credentials, so resources conforming to this specification must always be prepared to expect simple cross-origin requests with credentials.

----詳情可見 w3c cors

這裏沒有說的特別細,我補充了一下,大體意思是說,使用 GETPOST 進行表單提交時,亦或者使用一些 HTML 標籤引發的 GET 請求,如:aimg 等,基本上都會攜帶用戶憑據(Cookies)

Docker 靶場

SSRF

SSRF 本質其實和 CSRF 相差不大。只是 CSRF 面向的是客戶端的用戶,而 SSRF面向的是服務端自己。

這種漏洞通常出現於:會訪問並返回用戶可控的資源的功能上。

例如:在線查看網站源碼獲取用戶發連接的title在線翻譯網頁

<script>
  // 根據url動態拼接url
  function seeCode() {
    const url = document.getElementsByTagName('input')[0].value;
    location.href = location.origin + location.pathname + '?url=' + url
  }
</script>

<input type="text" placeholder="請輸入要查看源代碼的網站 URL"/>
<button onclick="seeCode()">查看</button>
<?php
  $url = $_GET['url'];
  if ("" == trim($url)) {
    return;
  }

  // 獲取內容
  $websiteCode = file_get_contents($url);

  // 轉碼後存入 textarea 標籤裏
  echo "<textarea>".htmlspecialchars($websiteCode, ENT_QUOTES)."</textarea>";
?>複製代碼

能夠看到,這裏沒有對用戶的輸入作任何的過濾,致使用戶能夠直接輸入http://192.168.1.2等url,來訪問內網資源,由於訪問資源的是服務端自己,而服務端自己也是能夠訪問同局域網的資源的。

Docker 靶場

JSON Hijacking

JSON Hijacking 其實本質和 CSRF 原理同樣

這裏的原理指的是,漏洞產生的原理同樣,仍是由於標籤產生的請求,會攜帶用戶憑證

這個攻擊手法和 CSRF 最大的不一樣,就是 JSON HijackingCSRF 的基礎上,又利用了 JSONP 的特性

<?php
  require 'utils.php';

  // 用戶認證、並獲取用戶信息
  $result = getUserInfo();
  if (count($result) != 3) {
    echo "";
    exit();
  }

  $fnName = $_GET['callback'];
  if ("" == trim($fnName)) {
    echo "";
    exit();
  }

	// 輸出爲: getInfo({"name": name, "balance": balance });
  echo "$fnName({name: '$result[0]', balance: '$result[2]'})";
?>複製代碼
<script>
  function getInfo(data) {
    console.log(data); // {"name": name, "balance": balance}
  }
</script>
<script src="./json.php?callback=getInfo"></script>複製代碼

若是有惡意攻擊者,寫了一個頁面,而且也在網頁里加入了<script src="http://xxx/json.php?callback=getInfo"></script>

根據上文提到的 w3c cors 規範中,若是用戶事先已經登錄過了,再打開惡意攻擊者發的連接,那麼攻擊者就能夠獲取一些本不該該獲取的敏感信息。

Docker 靶場

相關文章
相關標籤/搜索