使用mitmproxy阻止员工访问黑名单网站

原创内容,转载请注明来源https://songyue.wang

在实现用mitmproxy和QRadar SIEM审计员工浏览记录之后,我们继续探索mitmproxy开源web代理在防止信息泄露,恶意网站威胁,以及员工行为合规中的应用。通过编写mitmproxy脚本,实现对黑名单网站/IP地址进行封锁,并将事件上报QRadar SIEM分析。

用户访问代码共享工具被拦截

前置条件

  • 已安装IBM Security QRadar SIEM Community Edition免费版
  • 已在另一台主机安装mitmproxy
  • 熟悉QRadar的DSM编辑器

关于安装mitmproxy,设置客户代理,连接QRadar等细项均可参考这篇笔记

黑名单

通常情况下,企业的web黑名单主要包含以下几类网站:

  • 易发生信息泄露的应用:例如个人网盘服务(OneDrive Personal, Google Drive, 百度云盘),图床,在线记事本,代码共享工具,云IDE等。
  • 违反员工守则/AUP的内容:成人内容,在线娱乐场,以及其它与工作需求不相关/不适当的应用(游戏,视频等)。
  • 已知恶意网站/攻击者IP/钓鱼链接:从Threat Intelligence所获取的恶意域名,已知的攻击者IP,钓鱼邮件里按钮所指向的网站/下载链接等。

GitHub里可以找到很多开源的域名列表项目,例如StevanBlack/hosts,按类别列出域名,其中最大的Unified Host文件包含110K+记录。对开源项目下载的列表进行Data Massaging转成RegEx之后,得到一个这样的blacklist.csv,供拦截脚本使用:

.*twitter\.com,Social Media
.*codeshare\.io,Cloud Storage
.*ladbrokes\.com,Gambling
.*4399\.com,Entertainment
.*hacker\.com,Malicious Host
...
...

mitmproxy拦截脚本

import requests
import ipaddress
from mitmproxy import http
from datetime import datetime
import csv
import re

SIEM_HOST = 'http://192.168.1.135' # 你的QRadar服务端IP
SIEM_PORT = 12469 # 你的QRadar日志源的监听端口
SIEM_URL = f"{SIEM_HOST}:{SIEM_PORT}"

BLACKLIST_PATH = "./blacklist.csv" # 黑名单文件路径
BLACKLIST = []
with open(BLACKLIST_PATH, mode='r') as file:
  reader = csv.reader(file)
  for row in reader:
    if row:
      BLACKLIST.append([row[0], row[1]])

# 发送流量日志到QRadar SIEM
def send_to_siem(log):
  headers = {'Content-Type': 'application/json'}
  requests.post(SIEM_URL, json=log, headers=headers)

# IPv4-mapped IPv6转换成IPv4
def convert_ipv6_to_ipv4(ipv6):
  try:
    ip = ipaddress.ip_address(ipv6)
    if ip.ipv4_mapped:
      return str(ip.ipv4_mapped)
    return str(ip)  
  except ValueError:
    return "Invalid IP address"  

# 用正则表达式判断是否在黑名单内,如果是则返回封锁类型
def is_blacklisted(destination):
  for pattern in BLACKLIST:
    if re.fullmatch(pattern[0], destination):
      return pattern[1]
  return None

# 截获客户端请求时执行的操作
def request(flow: http.HTTPFlow) -> None:
  destination_ip = flow.server_conn.ip_address[0]
  destination_host = flow.request.host

  blacklisted = is_blacklisted(destination_ip) or is_blacklisted(destination_host)
  
  # 封锁请求时发送给SIEM的有效荷载
  if blacklisted:
    log = {
      # 事件名为封锁类型
      "eventName": blacklisted,
      "eventCategory": "BlockedHTTPRequest",
      "timestamp": datetime.utcnow().isoformat() + "Z",
      "sourceIP": convert_ipv6_to_ipv4(flow.client_conn.address[0]),
      "destinationIP": destination_ip,
      "destinationPort": flow.server_conn.ip_address[1],
      "destinationHost": destination_host,
      "method": flow.request.method,
      "url": flow.request.url,
      "status": f"Blocked - {blacklisted}",
      "bytes": len(flow.request.content)
    }
    print(f"Blocked request log entry: {log}")
    send_to_siem(log)

    # 向用户浏览器发送请求被封锁的提示信息
    flow.response = http.HTTPResponse.make(
      403,  
      b"Access to this site is blocked.\nPlease contact IT Support if you have valid business reasons to request for access.",
      {"Content-Type": "text/plain"}
    )

  # 放行请求时发送给SIEM的有效荷载
  else:
    log = {
      "eventName": "AllowedHTTPRequest",
      "eventCategory": "AllowedHTTPRequest",
      "timestamp": datetime.utcnow().isoformat() + "Z",
      "sourceIP": convert_ipv6_to_ipv4(flow.client_conn.address[0]),
      "destinationIP": destination_ip,
      "destinationPort": flow.server_conn.ip_address[1],
      "destinationHost": destination_host,
      "method": flow.request.method,
      "url": flow.request.url,
      "status": "Allowed",
      "bytes": len(flow.request.content)
    }
    print(f"Request log entry: {log}")
    send_to_siem(log)

把拦截脚本和blacklist.csv上传到代理服务器,./mitmweb -s proxy_with_blacklist.py启动mitmweb,再使用设定代理的设备访问4399.com,发出去的HTTP Request就会被代理drop,并返回以下页面:

Access to this site is blocked.
Please contact IT Support if you have valid business reasons to request for access.

更新事件对映

我们的mitmproxy的脚本会在JSON中的eventName填入被封锁的网站类型。在DSM编辑器打开mitmproxy日志源,给eventCategory=blockedHTTPRequest下不同eventName的事件添加事件对映。QRadar内置有相关的QID,把高层次种类低层次种类选为应用程式Web可以检索到,例如社交类网站。

对于已知恶意主机,可疑的活动=>黑名单位址里有一个贴近的Hit on an IP/domain known to serve malicious file,全部设置好的事件对映如下图。

新建攻击规则

在所有试图访问被封锁域的事件中,“已知的恶意网站/IP”是最需要被关注的。这可能意味着环境内有其它攻击活动,例如已经存在系统内的恶意脚本自动访问外网下载payload,向外界发送窃取的信息,或者出现未被SEG标识的钓鱼邮件。因此,我们建立攻击规则,让QRadar把mitmproxy收集到的这类事件归为攻击。

QRadar主控台攻击=>规则=>动作=>新建事件规则

测试群组中,选择when the event QID is one of the following QIDs,把QID补充为96500143,即试图访问已知恶意站点事件绑定的QID记录,并给这个攻击规则起个名字。

最后,定义这个攻击的严重性,可靠性和相关性,并勾选“请确保侦测到的事件是攻击的一部分”。如果需要执行一些自动化响应,例如邮件通知或者调用某个外部API。

再次测试,就可以看到QRadar把mitmproxy发来的相关安全事件归为新的攻击。用户在短时间内访问多个不同的已知恶意主机会被合并为同一攻击供安全人员调查。

Previous
Next