# 采用大數據和機器學習來保護您的在線服務
**[艾莉森溶膠](https://msdn.microsoft.com/zh-cn/magazine/ee532098.aspx?sdmr=AlissonSol&sdmi=authors)?
[唐 Ankney](https://msdn.microsoft.com/zh-cn/magazine/ee532098.aspx?sdmr=DonAnkney&sdmi=authors)?
[Eugene Bobukh](https://msdn.microsoft.com/zh-cn/magazine/ee532098.aspx?sdmr=EugeneBobukh&sdmi=authors)**
**[下載代碼示例](https://msdn.microsoft.com/zh-cn/magazine/msdnmag0115)**
目前有幾種方法保護在線服務,從安全開發生命周期的操作流程對事件作出迅速反應。在線服務的主要資產之一,經常被忽視 — — 大數據創建的請求日志和業務事件監視。這篇文章將探討使用率數據處理和機器學習 (ML) 技術來提高安全性,基于保護 Microsoft 應用程序中的在線資產的經驗 & 服務組 (ASG),包括 Bing,Bing 的廣告和 MSN 等服務。
大多數在線服務創建幾個流的記錄的數據。固然沒有標準分類的各種測量您可以存儲有關的服務,當你正在尋求安全問題的數據,可以大致歸類為使用率數據或操作數據。使用率數據包括關于由其目標受眾服務使用的任何記錄的值。一個常見的例子是對 Web 站點的請求的日志項:
~~~
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2014-10-27 20:46:57 127.0.0.1 GET /search q=election+results&form=PRUSEN&mkt=en-us 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.4;+WOW64;+Trident/7.0;+Touch;+rv:11.0)+like+Gecko - 200 0 0 5265
~~~
這種類型的日志條目包含數據只是關于所請求的資源,客戶端瀏覽器、 返回代碼和完成請求所需的時間。更復雜的服務可以豐富與派生的信息,比如地理位置或特定于應用程序的信息,如用戶標識 (對于已登錄的用戶) 的使用率數據。會沒有使用率數據沒有實際的用戶,除了或許用于測試和監控代理。
業務數據是指服務器和服務操作的測量。這包括 CPU 利用率或溫度、 磁盤空間、 網絡傳輸速率,應用程序異常、 內存故障和登錄,只要打開服務器,啟動服務的類似因素。在現代數據中心,日志信息通常包括不僅計算設備,如空調的測量、 派駐人員和游客在區內包含敏感數據,門被打開和關閉和類似的業務安全標準所需的信息方面。
這篇文章中的代碼示例將集中處理使用率數據。不過,您可以應用的大多數原則概述,并證明在這里識別漏洞利用業務數據。你也可以提高你的識別安全事件關聯使用數據和業務數據的機會。
## 進攻的終結點
改變為一個大型的在線服務的速度很難來保護使用只有典型的安全開發生命周期做法,例如代碼審查和靜態分析工具。數以千計的變化都承諾每個月。經常有至少幾個幾百個實驗"飛行"在任何給定的點。這些實驗呈現新的特點,來選擇要收集反饋信息廣泛發布之前的用戶。除了以下良好發展做法和有滲透測試團隊不斷設法找出漏洞,至關重要的是要盡可能多的漏洞發現盡可能自動化。
在 2014 年年底,附近微軟 Bing 服務生成數百兆兆字節的使用率數據每天,測井達數千億美元的請求。它是安全承擔一些這些請求是實際攻擊,試圖找出或漏洞。一個典型的查詢到 Bing 是向服務發送一個 URL 請求:
~~~
http://www.bing.com/search?q=election+results&form=PRUSEN&mkt=en-us
~~~
在此示例中,用戶搜索"選舉結果"。有兩個其他 URL 中的參數識別起源的要求和市場設置 (在本例中,該值指示用戶語言英語和美國) 的 Web 窗體。你可能會理解這一點作為"搜索"應用程序在 Bing 的域中,參數 q,形式與市場的呼喚所有此類要求表示在一個規范的格式,如下所示:
~~~
http://www.bing.com/search?q=[]&form=[]&mkt=[]
~~~
有內冰域回答類似請求的其他應用程序。一個請求要求的視頻格式的"選舉結果"將是:
~~~
http://www.bing.com/videos?q=election+results&form=PRUSEN&mkt=en-us
~~~
隨著在線服務的增長,新的應用程序和功能添加動態 — — 一些方便和其他的兼容性。不同的格式通常允許相同的請求。Bing 視頻也會接受這項要求:
~~~
http://videos.bing.com/?q=election+results&form=PRUSEN&mkt=en-us
~~~
假設你可以從使用率日志列表與規范的所有請求到服務,你可以然后探測器試圖注入參數值的已知惡意有效載荷的漏洞。例如,入侵者可以使用下列請求驗證是否 Bing 視頻應用程序很容易受到跨站點腳本 (XSS) 在查詢參數中:
~~~
http://www.bing.com/videos?q=<script>alert("XSS")
</script>&form=PRUSEN&mkt=en-us
~~~
入侵者的安全漏洞掃描還將測試中響應的惡意負載注入其他參數,則在所有可能的組合。一旦發現了一個漏洞,可以發起攻擊。攻擊 Url 通常包含在垃圾郵件,希望一小部分用戶會不小心點擊鏈接。有些用戶甚至可能懷疑 Url,其中包含 JavaScript 關鍵字。然而,編碼的請求使更難及時識別攻擊:
~~~
http://www.bing.com/videos?&form=PRUSEN&mkt=en-us&q=%3CscRipt%3Ealert(%22XSS%22)%3C%2FScriPT%3E
~~~
您可以編寫應用程序接受規范請求到服務的列表作為輸入,注入惡意有效載荷為每種可能的脆弱性和檢測從服務問題答案,如果這次襲擊成功。你可以找到代碼漏洞的幾種個別的"探測器"(XSS、 SQL 注入和開放重定向) 在線。在這篇文章,我們將重點放在尋找"攻擊面"對在線服務的使用率數據日志。
## 處理環境
博客通常分布在幾個機器制作的順序日志文件讀取效率極高 (如果文件被分割成跨不同的存儲設備在分布式的文件系統中的更好)。這使得處理博客 MapReduce 框架一個偉大的應用程序。
對于這個示例,我們將放到博客微軟 Azure Blob 根據相同的容器,稱為 InputContainer。作為一種處理平臺,我們會使用 Azure HDInsight 流 MapReduce 作業。有良好的信息已經在線上可用如何設置和配置 HDInsight 集群。在這篇文章中解釋的代碼將生成二進制文件應放置在容器中 HDInsight 群集,簡稱為 ClusterBinariesContainer 可以訪問。作為代碼執行,并處理輸入,它會在另一個容器稱為 ClusterOutputContainer,以及狀態信息保存到 ClusterStatusContainer 中創建的輸出。一個可視化的 Azure HDInsight 處理配置所示**圖 1**。

**圖 1 天青 HDInsight 處理環境**
您需要替換中的占位符名稱**圖 1**?與您的特定配置的值。您可以設置這些配置文件中。Windows PowerShell 腳本將創建并執行 HDInsight 作業將讀取 XML 配置文件中所示**圖 2**。配置文件之后, 你會最有可能執行該腳本的使用率數據分析從內 Azure PowerShell 提示符下,正確配置了您 Azure 的帳戶具有授權才能訪問存儲和計算服務 (見得到 AzureAccount 和添加 AzureAccount cmdlet 幫助)。
**圖 2 Windows PowerShell 腳本 XML 配置文件**
~~~
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
? <SubscriptionName>Your-SubscriptionName</SubscriptionName>
? <ClusterName>Your-ClusterName</ClusterName>
? <ClusterStorageAccountName>Your-ClusterStorageAccountName
??? </ClusterStorageAccountName>
? <ClusterBinariesContainer>Your-ClusterBinariesContainer
??? </ClusterBinariesContainer>
? <MapperBinary>UsageDataMapper.exe</MapperBinary>
? <ReducerBinary>UsageDataReducer.exe</ReducerBinary>
? <ClusterOutputContainer>Your-ClusterOutputContainer</ClusterOutputContainer>
? <ClusterStatusContainer>Your-ClusterStatusContainer</ClusterStatusContainer>
? <InputStorageAccountName>Your-InputStorageAccountName
??? </InputStorageAccountName>
? <InputStorageAccountKey>Your-InputStorageAccountKey</InputStorageAccountKey>
? <InputContainer>Your-InputContainer</InputContainer>
? <DeployBinaries>true</DeployBinaries>
? <DeployFlavor>Release</DeployFlavor>
? <JobTimeOut>3600</JobTimeOut>
</Configuration>
~~~
## 映射到規范要求
獲取使用 MapReduce 的在線服務的受攻擊面加工環境包括創建一個映射器的應用程序從博客中提取的 Url 并將它們轉換成標準形式。該值為減速機,然后將消除重復成為關鍵。這是示例字計數應用程序中可用的 HDInsight 中使用的同一原則。刪除任何注釋和驗證代碼,下面的代碼演示映射應用程序的主入口點:
~~~
public static void Main(string[] args)
{
? Console.SetIn(new StreamReader(args[0]));
? string inputLogLine;
? while ((inputLogLine = Console.ReadLine()) != null)
? {
??? string outputKeyAndValues =
????? ExtractKeyAndValuesFromLogLine(inputLogLine);
??? Console.WriteLine(outputKeyAndValues);
? }
}
~~~
此代碼遍歷每個輸入行并提取的唯一的鍵,以及任何具有互補的價值有關的被解決的問題。舉個例子,假如你正在尋找的最常見的用戶查詢,關鍵將傳遞查詢參數的值。原始日志行如下所示:
~~~
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2014-10-27 20:46:57 127.0.0.1 GET /search q=election+results&form=PRUSEN&mkt=en-us 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.4;+WOW64;+Trident/7.0;+Touch;+rv:11.0)+like+Gecko - 200 0 0 5265
~~~
列 cs-uri 和 cs uri 查詢有你需要有經過解析來獲取請求的規范形式的相關信息 (示例代碼不包括多個宿主 pro-處理)。要提取每個日志行的鍵和值的函數所述**圖 3**。
**圖 3 從日志行提取鍵和值的函數**
~~~
private static string ExtractKeyAndValuesFromLogLine(string inputLogLine)
{
? StringBuilder keyAndValues = new StringBuilder();
? string[] inputColumns = inputLogLine.Split(DataFormat.MapperInputColumnSeparator);
? string uriReference = inputColumns[DataFormat.MapperInputUriReferenceColumn];
? string uriQuery = inputColumns[DataFormat.MapperInputUriQueryColumn];
? string parameterNames = ExtractParameterNamesFromQuery(uriQuery);
? // Key = uriReference + separator + parameterNames
? keyAndValues.Append(uriReference);
? keyAndValues.Append(DataFormat.ReferenceFromQuerySeparator);
? keyAndValues.Append(parameterNames);
? keyAndValues.Append(DataFormat.MapperOutputColumnSeparator);
? keyAndValues.Append(DataFormat.OneOccurrence);
? return keyAndValues.ToString();
}
~~~
唯一缺少邏輯涉及從查詢列中提取的參數名稱。要執行此任務的代碼所示**圖 4**。該函數的輸入 — — 以前提供的示例行 — — 將會像這樣一個字符串:
~~~
q=election+results&form=PRUSEN&mkt=en-us
~~~
**圖 4 函數來從查詢獲得只是參數的名稱**
~~~
private static string ExtractParameterNamesFromQuery(string query)
{
? StringBuilder sb = new StringBuilder();
? // Go through each parameter adding to output string
? string[] nameValuePairs = query.Split(DataFormat.ParametersSeparator);
? Array.Sort(nameValuePairs, StringComparer.InvariantCultureIgnoreCase);
? List<string> uniqueParameterNames = new List<string>();
? foreach (string nameValuePair in nameValuePairs)
? {
??? int indexOfSeparatorParameterNameFromValue =
????? nameValuePair.IndexOf(DataFormat.ParameterNameFromValueSeparator);
??? string paramName = nameValuePair;
??? paramName = nameValuePair.Substring(0,
????? indexOfSeparatorParameterNameFromValue);
??? uniqueParameterNames.Add(paramName);
??? sb.Append(paramName);
??? sb.Append(DataFormat.ParameterNameFromValueSeparator);
??? sb.Append(DataFormat.OneOccurrence);
??? sb.Append(DataFormat.ParametersSeparator);
? }
? return sb.ToString();
}
~~~
在示例代碼中使用的規范形式將刪除參數值、 排序的參數名稱和它轉變為一個仍然有效的查詢字符串:
~~~
form=1&mkt=1&q=1&
~~~
排序的參數名稱有助于避免工作重復,因為 Web 請求不依賴于參數順序。用于參數值的占位符是"1",而不是"[]",因為它是更短。它還可能與其他的東西像計數的參數將出現在所有的請求參數組合的次數,如中所示用于**圖 4**。
## 減少攻擊面
映射代碼按順序讀取日志行,然后為每個輸出的鍵和值。MapReduce 有一個"結合"的階段,由減速機代碼用相同的密鑰對加工組裝的所有記錄。如果輸入的日志有做搜索查詢的幾行,到目前為止,那些產生相同的輸出:
~~~
search?form=1&mkt=1&q=1&???????? 1
search?form=1&mkt=1&q=1&???????? 1
search?form=1&mkt=1&q=1&???????? 1
~~~
**圖 5**?已經減速機代碼大綱。它讀取輸入的行并拆分那些入鍵和值。它直到關鍵的變化,保持一個計數器,然后輸出結果。
**圖 5 減速器主回路**
~~~
public static void Main(string[] args)
{
? string currentKey, previousKey = null;
? int count = 0;
? Console.SetIn(new StreamReader(args[0]));
? string inputLine;
? while ((inputLine = Console.ReadLine()) != null)
? {
??? string[] keyValuePair =
????? inputLine.Split(DataFormat.ReducerInputColumnSeparator);
??? currentKey = keyValuePair[0];
??? if (currentKey != previousKey)
??? {
????? Console.WriteLine(DataFormat.ReducerOutputLineFormat,
previousKey, count);
????? count = 1;
????? previousKey = currentKey;
??? }
??? else count++;
? }
? Console.WriteLine(DataFormat.ReducerOutputLineFormat,
previousKey, count);
}
~~~
您可以輕松地修改代碼和用于其他目的本文中提供的腳本。更改函數 ExtractKeyAndValuesFromLogLine 有參數值作為鍵,你會有用值使用頻率的分布。在其當前的窗體,則輸出將攻擊面,顯示的請求頻率與歸一化的應用程序路徑的列表:
~~~
search?form=1&mkt=1&q=1&???????? 3
video?form=1&mkt=1&q=1&?????????? 10
~~~
## 理解服務交通
攻擊面已經將價值以幫助您了解正在發生與您的服務,即使你不執行主動滲透性測試,以暴露安全漏洞。雖然請求頻率變化每小時,每日一周內,與其他季節性的因素,正常的行為特征隨時間變化釋放,或甚至協同攻擊。例如,Bing 會收到數以億計每日請求數。攻擊表面列表通常有數以十萬計的每一天的值。即使預期并不是所有此類路徑。**圖 6**?總結了攻擊面上在典型的一天上發現了什么。第一行指示到 89.8%規范路徑的通常請求通信量,10 量最高。未來的十大路徑添加達 6.3%的請求計數 (或前 20 名的 96.1%)。那些真正頂尖的應用程序服務。一切共計少于 4%。這種請求的模式是一個網站用銀團的內容,如 MSN.com 非常不同的。
**圖 6 典型分布的請求路徑為必應在 2013 年**
| 典型的路徑 | 百分比 |
|---|---|---|
| 前 10 條 | 89.8 |
| 前 20 條 | 96.1 |
| 用路徑 < = 1000 個請求 | 99.9 |
| 用路徑 < = 100 個請求 | 99.6 |
| 用路徑 < = 10 個請求 | 97.6 |
| 路徑與 = 1 的請求 | 67.5 |
它是特別有趣地注意到大約三分之二的請求到獨特的路徑。一些這些請求可能來自攻擊者試圖探測可能觸發某些功能的應用程序參數。然而在線服務的本質會生成大量的此類通信量。鏈接到您的服務存儲幾年前仍處于可能被人類激活狀態或自動化的流程。同時尋求攻擊者,你可能發現需要有一種兼容性模式為舊的 Url,和自動重定向到新版本的應用程序。這是一個很好的業務結果。
開發該攻擊的應用程序是一段旅程,你應該小心。假設你的探測器都完美的會到您需要適當節流的服務現在施加負荷。您需要避免產生拒絕服務攻擊或影響對真正的用戶性能。此外,至關重要的是要避免許多誤報。如果發生這種情況,從攻擊服務事件報告將很快就會被忽略。
## 學習從服務數據
毫升,可以自動完成多個進程,就很難進行直接編碼指令或規則。例如,很難想象會覺察到一個人的計算機視覺應用程序的代碼是在鏡頭前。貼標數千幅圖像的深度信息,然而,在微軟的 Kinect 團隊后能夠"訓練"ML 模塊,這樣做的足夠的精度。標記的深度圖像指示不僅是人類的存在,而且也是身體的位置,使學習的過程。
生成請求已知類別的攻擊服務 (XSS、 SQL 注入等等) 自動化過程要用于 ML 方法評價在線交通的重要組成部分。它會生成大量的綜合地面真相。檢查使用日志,可以輕松地識別已知攻擊服務由在某個時間的所有此類攻擊的要求。他們現在正在與用戶請求,因為其中沒有卻已知的分類 (正常或惡意請求) 混合。
若要創建一個分層的真正匹配通信量,擊中該服務的數據,你必須了解該通信量的特點。生成實驗樣品有 0.1%的接收 1000 億請求服務的使用情況數據一天仍導致 1 億的請求。只有合成數據可以幫助創建一個初始地面的真理。
假設你有高質量地面真相和適當的工具,概述了 ML 解決方案,以評估用戶請求的學習過程的迭代周期在**圖 7**。入手綜合數據在地面的真理,你可以做實驗和開球毫升模塊進行分類的請求中的訓練過程 (分為如正常人,XSS、 SQL 注入等等) 或使 (指示請求屬于一個或多個類別的信心) 的回歸。可以部署此毫升模塊作為解決方案的一部分然后可開始接收評價要求。輸出然后有一個評分的過程,它將表明是否毫升模塊正確確定請求 (真陽性和真正的底片),錯過了可疑請求 (假陰性) 或生成虛假警報 (假陽性)。

**圖 7 學習周期,以創建一個機器學習基于解決方案**
如果最初的實驗產生足夠毫升模塊基于合成數據良好,該模塊應該是相當準確的與幾個不正確地評估實際的用戶請求。然后可以正確標簽那些被錯誤地評估并將它們添加到地面真相。幾個更多的實驗和訓練現在應該生成一個新的 ML 模塊恢復精度。當你仔細地重復這一過程,初始的合成數據變得更小的部分,在培訓過程中,使用的事實依據和迭代 ML 模塊更好地準確地評估用戶的請求。對于附加的驗證,您可以使用毫升模塊對脫機應用程序檢查使用日志和識別惡意請求。經過充分的發展,您可以部署毫升模塊在線評估請求在真正的時間,并防止攻擊過命中后端應用程序。
## 總結
而你應該繼續遵循堅實的發展過程 (包括安全開發生命周期),你應該還需要承擔你在線服務可能受到攻擊任何點。使用率日志可以為您提供關于如何發生這種攻擊有深度的信息。知道你的受攻擊面,將幫助您主動攻擊您的服務,以查明和關閉漏洞之前他們剝削。攻擊服務然后創建綜合地面真相,啟用的 ML 技術培訓毫升模塊,以評估服務請求使用的建筑。建筑攻擊服務并非微不足道的工作,但近期和長期的業務成果遠遠超過所花的投資。