安全態勢,互動發現 —— 基於阿里雲輕鬆搭建安全大屏

dicyt發表於2017-07-26

摘要: 使用DataV大屏展現態勢感知 DNS 會話日誌,從而實現互動式安全威脅發現。

2017年,阿里雲啟動MVP(Most Valuable Professional)專案。顧名思義,MVP正在尋找阿里雲最有價值專家,那些能夠,並且願意幫助他人,充分了解和使用阿里雲技術的意見領袖。

本文是阿里雲MVP 傅奎的實踐分享,今天和大家講講 “安全態勢,互動發現 —— 基於阿里雲輕鬆搭建安全大屏 ”

  • 一句話概述

  • 背景介紹

  • 產品介紹

  • 需求分析

  • 實現方法

    • 匯出態勢感知 DNS 日誌

    • 定製返回 JSON 串的資料來源API

    • 定製 DataV 大屏,指定 API 資料來源

    • 釋出監控大屏,看效果

  • 互動式發現

  • 補充說明

    • 替你踩過的坑

    • Show you the code

  • 一些期待

    • 關於“互動式”

    • 鳴謝

一句話概述

使用DataV大屏展現態勢感知 DNS 會話日誌,從而實現互動式安全威脅發現。

劇透一下最終效果,絕對值得試試:

所有 DNS 日誌的節點(源地址、DNS伺服器地址、要解析的域名)關係圖。點選其中任一節點,關聯點自動高亮,非關聯節點則進入蒙版狀態,要是有什麼可疑的節點、關係、類目,一眼就看出來!

背景介紹

自打“態勢感知”上線了新版的“日誌”功能,團隊成員就在摩拳擦掌尋思如何充分挖掘日誌資訊的價值,而不僅僅是用於故障診斷或事件調查。其中,通過圖形化展現不同網路資源節點的相互關係,進而實現互動式安全威脅發現,是最為理想的實現方式。此前嘗試過 Graphviz、yEd、NetworkX 等方式,後來都因配置複雜,使用繁瑣等問題放棄。

直到MVP 技術群裡李文毅向大家推薦了 DataV,我想:是時候“make it true ”了!

產品介紹

以下材料援引自官方介紹,描述不準與我無關:

  • 態勢感知

“態勢感知提供的是一項SAAS服務,即在大規模雲端計算環境中,對那些能夠引發網路安全態勢發生變化的要素進行全面、快速和準確地捕獲和分析,並提供一個體系化的安全解決方案。”

  • DataV 資料視覺化

“DataV旨讓更多的人看到資料視覺化的魅力,幫助非專業的工程師通過圖形化的介面輕鬆搭建專業水準的視覺化應用。DataV提供豐富的視覺化模板,滿足您會議展覽、業務監控、風險預警、地理資訊分析等多種業務的展示需求。”

需求分析

態勢感知的日誌功能非常強大,目前支援查詢:所有入站的7層資料、出入站棧的4層會話以及DNS雙向日誌。其中 DNS 日誌有助於安全團隊分析伺服器是否遭受入侵,被植入木馬病毒,存在異常請求等問題。

我們最關心的是:哪臺伺服器,通過哪個 DNS Server,解析了哪個域名?

針對該需求,如果有視覺化的節點關係圖輔助分析,那麼威脅識別的效率將大幅提升。在沒有使用 DataV 之前,通常的辦法是使用一些圖表工具進行展現,而且少不了定製化開發的工作量。DataV 的出現,大大解放了資料分析人員的雙手,從而可以用於拖動進度條。僅僅通過少量的滑鼠點選和基本的 API 配置,就能瞬間讓你的資料充滿活力,開口說話。DataV 自帶節點關係圖,並內嵌原生ECharts ,完全可以滿足此類需求。

實現方法

你一定很期待強勁的態勢感知與性感的 DataV強強聯合會是什麼樣子。期待不如行動,我們一起動手去實現吧。

匯出態勢感知 DNS 日誌

登入阿里雲控制檯,進入安全(雲盾)|態勢感知功能頁,通過子選單選擇日誌 new專案。

設定DNS 日誌查詢條件,分別是:

  • 日誌源:DNS

  • 欄位:qtype

  • 判斷條件:包含(目前只能選包含)

  • 關鍵字:A

再設定好查詢時間,點選搜尋就可以啦。

系統很快就能返回查詢結果,通過右上角匯出結果將當前頁(沒錯,,是當前頁,,一次100條-_-)日誌匯出到Excel 中。如果需要更多資料,得依次翻頁匯出-_-。當然也有程式化解決方案,請往後看。

定製返回 JSON 串的資料來源API

對匯出的 Excel 檔案進行資料抽取,關鍵是:

  • 源地址:src_ip

  • DNS Server:dst_ip

  • 嘗試解析的域名:qname

將源地址、DNS 地址、域名三項都納入節點範疇,同時將源地址->DNS 地址、DNS 地址->域名納入關係範疇,通過 HTTP 將節點 nodes 和關係 links 輸出為 JSON 就是一個可用的API資料輸入源。

彆著急,作為良心分享,怎麼能少了技術細節呢?為了不影響閱讀,我把資料格式化和 API 相關的具體內容放在後面環節。

定製 DataV 大屏,指定 API 資料來源

通過阿里雲控制檯大資料(數加)|DataV資料視覺化進入定製介面,直接選擇新建視覺化

建立大屏模板,設定一個你喜歡的名字。

向大屏圖層新增資料展示元件, 這裡可以選擇關係網路或原生的 Echarts 網路圖。

點選圖表元件,進入右側資料選項卡,修改預設的資料來源型別靜態資料為 API

填寫滿足系統要求的 API,如:http://www.test.com/datav.json,滑鼠離開輸入框,左側設計區會即時展現效果。

釋出監控大屏,看效果

資料除錯和預覽成功後,可通過右上角的釋出按鈕,正式釋出報表。DataV 考慮得很周到,為報表提供了密碼和 Token 兩種安全保護機制。

訪問釋出後的報表連結:http://datav.aliyun.com/share/ef9aa**********a3fd8(這是他們的祕密不可訪問的哈)

互動式發現

好吧,放一些我在測試環境模擬出來的資料。下面是一段時間內,所有 DNS 日誌的節點(源地址、DNS伺服器地址、要解析的域名)關係圖。

點選其中任一節點,關聯點自動高亮,非關聯節點則進入蒙版狀態,相當炫酷啊!

來,再看另外一組測試資料。要是有什麼可疑的節點、關係、類目,一眼就看出來!

小提示:萬一發現了什麼神奇的域名或 IP 地址,可以直接上微步威脅情報查詢,例如:https://x.threatbook.cn/domain/google.com。是不是壞人立即遁形,這個庫太全了……

補充說明

替你踩過的坑

  • 如果不打算使用伺服器代理方式呼叫API,那麼一定要設定好 API 的 HTTP 頭部跨域引數

  • 如果使用了 HTTPS 訪問DataV 監控大屏,那麼 API 介面也必須是 HTTPS 形式

  • API 介面返回的資料要和靜態資料輸入框中的格式完全一樣——JSON 串

  • 如果你遇到了一些神奇的 Bug,請把圖層或元件刪除後從頭再來一遍(不要問我怎麼知道的)

  • DataV 自帶的關係圖和內嵌的原生 ECharts 在資料格式上有一定的區別,要看仔細

Show you the code

下面這段程式碼可以幫助使用者在登入態勢感知後,自動獲取 DNS 會話日誌,並按照 DataV 關係圖所適配的資料格式生成 JSON 串。非專業開發人員的臨時程式碼,寫得比較醜,別太當真。

#!/usr/bin/python# -*- coding:utf8 -*-import json# pip install requestsimport requests# 成功登入態勢感知後,通過 Chrome 複製當前會話的 Cookie。cookie_str = 'aliyun_country=CN; aliyun_site=CN;'\             'UM_distinctid=***; JSESSIONID=***; '\             'consoleNavVersion=1.1.1; _yundun_session0=***; '\             'aliyun_choice=CN; isg=***E-'nodes_client = []  # 客戶端 IPnodes_server = []  # DNS Server IPnodes_domain = []  # 解析的域名def get_yundun_DNS_log(http_session=None, page_num = 1):
    """
    訪問阿里雲後臺,請求 DNS 日誌
    :param http_session: requests.session()
    :param page_num: page number
    :return: HTTP Response
    """
    global cookie_str
    url = 'https://yundun.console.aliyun.com/sas/slssearch/'\          'getLogList.json?__preventCache=1500********2&_timeScope=1800000'\          '&currentPage=%d&endTime=2017-07-19+19:00:00'\          '&pageSize=100&query=dns@qtype:A&reverse=true'\          '&startTime=2017-07-19+12:30:00'
    req = http_session.request('GET', url=(url % page_num), 
                                headers={'cookie': cookie_str})
    if req.status_code == 200:
        return req.text    return {}def get_group_name(node):
    """
    根據不同的節點型別,返回不同的類目組。相同組的節點將使用相同的顏色顯示。
    :param node: node_name
    :return: group_name
    """
    global nodes_client, nodes_server, nodes_domain    if node in nodes_client:
        return 'group1'
    if node in nodes_domain:
        if 'ali' in node:
            return 'group2'
        return 'group3'
    if node in nodes_server:
        if node in ('114.114.114.114'):
            return 'group4'
        if node.startswith('192'):
            return 'group5'
    return 'group6'def get_DNS_log_json_list():
    """
    返回所有 DNS 日誌記錄 JSON
    :return:
    """
    dns_log_json = []
    sessionX = requests.session()
    # 翻頁10次
    for i in range(10):
        res = get_yundun_DNS_log(sessionX, i+1)
        log_json = json.loads(res)
        dns_log_json += log_json['data']['list']
    return dns_log_jsondef geenrate_nodes_and_links():
    """
    生成所有節點和關係的List
    :return: (nodes[], links[])
    """
    global nodes_client, nodes_server, nodes_domain
    nodes = []  # 所有節點
    links = []  # 所有關係
    for log in get_DNS_log_json_list():
        (client, domain, server) = ('','','')
        for mContent in log['mContents']:
            if mContent['mKey'] == 'src_ip':
                client = mContent['mValue']
            if mContent['mKey'] == 'qname':
                domain = mContent['mValue']
            if mContent['mKey'] == 'dst_ip':
                server = mContent['mValue']
        if client == '' or domain == '' or server =='':
            continue
        #print (client, domain, server)

        if domain == 'shcmsproxy.aliyun.com':
            continue

        if client not in nodes_client:
            nodes_client.append(client)
        if client not in nodes:
            nodes.append(client)

        if domain not in nodes_domain:
            nodes_domain.append(domain)
        if domain not in nodes:
            nodes.append(domain)

        if server not in nodes_server:
            nodes_server.append(server)
        if server not in nodes:
            nodes.append(server)

        if (client, server) not in links:
            links.append((client, server))
        if (server, domain) not in links:
            links.append((server, domain))
    return (nodes, links)def get_datav_json():
    (nodes, links) = geenrate_nodes_and_links()
    graph = {'nodes':[], 'links':[]}

    for node in nodes:
        graph['nodes'].append({
                "imgPath": "",
                "name": node,
                "type": get_group_name(node)
        })
    for link in links:
        graph['links'].append({
                "source": link[0],
                "target": link[1],
                "value": 10
        })
    return '[%s]' % json.dumps(graph)if __name__ == '__main__':
    print get_datav_json()

以下是API輸出結果示例:

[
  {
    "nodes": [
      {
        "imgPath": "",
        "name": "192.168.1.1",
        "type": "group1"
      },
      {
        "imgPath": "",
        "name": "114.114.114.114",
        "type": "group2"
      },
      {
        "imgPath": "",
        "name": "taobao.com",
        "type": "group3"
      }
    ],
    "links": [
      {
        "source": "192.168.1.1",
        "target": "114.114.114.114",
        "value": 10
      },
      {
        "source": "114.114.114.114",
        "target": "taobao.com",
        "value": 15
      }
    ]  }
]

將上述內容作為企業自身 API 介面的輸出,同時設定 HTTP HEAD 相關的引數,即可通過 DataV 大屏呼叫並展現啦!

self.set_header('Access-Control-Allow-Origin', '*.aliyun.com')self.set_header('Content-Type', 'application/json;charset=UTF-8')

跨域相關的問題請參考:瀏覽器的同源策略和跨域問題詳解

一些期待

關於“互動式”

這篇文章的標題中有兩個字我很喜歡——“互動”。

除了檢視上的互動,實際上使用者還花了很長的時間用在態勢感知日誌查詢、 匯出和格式化上。

這也算是一種“互動”,一種比較笨的互動。希望未來阿里雲能在多個產品之間的資料引用、內部介面互動上再做些升級,讓我們這樣的使用者少發揮技能,直到我們徹底“自廢武功”。

就這些,如果您有什麼問題歡迎在這裡留言與我交流。

想和我成為工作夥伴一起探索雲平臺上的安全技術實踐,也一樣歡迎哦~

鳴謝

  • 木醬

  • 花肉醬

  • 李文毅

  • @葦如|巢甜

  • @卡密

  • @杜仲

原文連結:http://click.aliyun.com/m/26776/


相關文章