前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >企业威胁情报平台建设之暗网监控

企业威胁情报平台建设之暗网监控

作者头像
知识与交流
发布2021-04-02 14:30:14
1.7K0
发布2021-04-02 14:30:14
举报
文章被收录于专栏:黑客技术家园

一、前言

相信大家对暗网这个概念并不陌生,众所周知,暗网藏着一个暗黑版的交易市场,各种违法工具比比皆是,俨然一个网络犯罪分子聚集的“虎狼之穴”。我们使用Tor浏览器等可以轻松访问暗网中的浅层网,主要是黄赌毒和数据情报信息,如丝绸之路等。

对于企业而言,往往不免被黑客攻击而被获取大量的数据,而这些数据一般会优先在暗网售卖,如近年来的12306、各大互联网公司等的数据泄露事件。为了及时响应突发的数据泄露事件,企业需要一款实时监控暗网数据泄露的威胁情报平台,用来监控敏感数据泄露、薅羊毛、业务安全风险等事件。

二、代理服务器搭建

由于国内网络环境的原因,为了顺利访问暗网,我们需要一台海外服务器,系统版本是ubuntu 18.04(当然其他系统也可以,只是本文会把这个版本的系统作为例子),同时需要在这台服务器上安装Tor与Privoxy用作访问代理服务器。

本文的系统版本:

代码语言:javascript
复制
root@536ef99cab94:/# cat /etc/issue.netUbuntu 18.04.2 LTS

2.1 整体架构

从图上可以看到,Privoxy作为一个中转代理,主要是把http协议转socks5协议,而Tor则负责把socks5转Tor协议。所以整个代理访问过程为:

1.用户输入后缀为onion的地址,由Privoxy暴露的8118端口访问http协议; 2.Privoxy把http协议转发给Tor,Tor获取该网站公钥进行加密,通过Tor通信链路发送信息给Tor节点,由该节点转发请求到.onion网站。

2.2 安装Tor

可能很多人一开始会直接执行这条命令:sudo apt-get install tor,从这个命令安装的Tor是v2版本的,不支持较新的加密算法,所以导致访问不到某些使用最新加密算法的暗网网址。

Tor v2到Tor v3的转变主要表现为如下几点:

1.签名算法从SHA1/DH/RSA1024升级到SHA3/ed25519/curve25519; 2.改进的Tor directory protocol,安全性更高; 3.更好的洋葱地址,换成sha3,可以提高枚举生成一样地址的难度; 4.可拓展的交换协议。

参考官网的安装方法,安装最新版(v3版本)的Tor步骤如下:

1.在/etc/apt/sources.list添加如下源:

代码语言:javascript
复制
deb https://deb.torproject.org/torproject.org bionic maindeb-src https://deb.torproject.org/torproject.org bionic main

2.添加gpg密钥,执行如下命令:

代码语言:javascript
复制
代码语言:javascript
复制
3.安装Tor:
代码语言:javascript
复制
apt updateapt install tor deb.torproject.org-keyring

4.查看安装好Tor的版本,可知本文安装的Tor版本为0.3.5.8:

代码语言:javascript
复制
root@536ef99cab94:/# tor -vJun 18 14:30:43.530 [notice] Tor 0.3.5.8 running on Linux with Libevent 2.1.8-stable, OpenSSL 1.1.1, Zlib 1.2.11, Liblzma 5.2.2, and Libzstd 1.3.3.Jun 18 14:30:43.531 [notice] Tor can\\\\\\\\\\\'t help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warningJun 18 14:30:43.531 [warn] Command-line option \\\\\\\\\\\'-v\\\\\\\\\\\' with no value. Failing.Jun 18 14:30:43.531 [err] Reading config failed--see warnings above.

2.3 配置Tor

Tor配置文件位于/etc/tor/torrc与/etc/tor/torsocks.conf:

/etc/tor/torsocks.conf定义了让socks协议转Tor协议的端口与地址;

/etc/tor/torrc是Tor的用户配置,在这个文件里我们修改http代理(polipo、privoxy)、即时通信(pidgin、lrssi)、TorDNS等。

为了支持Torv3版本,需要在/etc/tor/torrc文件中加上:

代码语言:javascript
复制
HiddenServiceDir /var/lib/tor/other_hidden_service/HiddenServicePort 80 127.0.0.1:80HiddenServiceVersion 3

修改完成后,在命令行输入service tor start或tor即可启动Tor。

2.4 安装与配置Privoxy

这里暂时没有什么版本要求,所以可以直接执行apt-get install privoxy。

安装好后,为了让Privoxy把http协议转发到Tor,需要编辑/etc/privoxy/config加上:

代码语言:javascript
复制
forward-socks5 / 127.0.0.1:9050 listen-address 0.0.0.0:8118

修改后,重启服务service privoxy restart。

2.5 验证代理器是否可用

Tor浏览器虽然可以使用meek-azure来访问暗网网站,但是访问速度较慢。为了验证我们搭好的代理服务器是否可用,我们可以修改Tor浏览器的网络设置(假设我们的代理服务器ip为:11.11.11.11):

设置完成后访问一个暗网网站,如果能访问成功的话即说明我们的代理服务器可用,同时访问速度也比meek-azure快得多。

当然,我们也可以更快捷地输入下面的命令进行测试:

代码语言:javascript
复制
➜  ~ curl -x 11.11.11.11:8118 https://httpbin.org/ip{  "origin": "178.175.132.225, 178.175.132.225"}

可以查询到178.175.132.225的所在地为国外的摩尔多瓦,为Tor节点的出口地址。

三、开发实时监控程序

在上一章节我们搭好了代理服务器,相当于拥有了访问暗网的钥匙,虽然可以用Tor浏览器+代理更快访问暗网网址,但是人工并不能做到24小时监控而及时发现数据泄露事件,因此我们需要开发一个爬虫程序实时监控暗网网站。

3.1 暗网网站的特点

暗网网站不同于表层网网站,没有太多花里胡哨的动态js与强大的反爬策略,因此对暗网网站爬虫也相对简单。在总结了几个常见的暗网网站后,发现暗网网站的反爬策略一般是如下几种情况:

1.Referer; 2.针对Cookie的请求频率限制; 3.User-Agent; 4.验证码; 5.对网站代码进行更新,修改html标签名字或位置。

3.2 暗网网站的反反爬虫

针对3.1的反爬虫策略我们可以设法绕过,由于本文的主旨并不在探究反爬虫策略,故简单地说下绕过方法:

1.指定请求头的referer为访问暗网网站的域名; 2.建立多账号Cookie池,同时使用Redis对url去重实现增量爬取减少请求量; 3.指定User-Agent为FireFox浏览器:{‘User-Agent’: ‘Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0’}; 4.暗网网站的验证码一般比较简单,可以简单使用ocr技术识别,如tesseract; 5.需要及时更新爬虫代码,有针对地修改反反爬虫代码。

3.3 暗网监控的爬虫架构

Scrapy是用Python实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。Scrapy常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。通常我们可以很简单的通过Scrapy框架实现一个爬虫,抓取指定网站的内容。

本文在Scrapy基础上结合3.2小节的反爬虫绕过方法实现了一个实时监控程序,其架构如下:

3.4 监控程序的具体实现

本文的监控程序是同时监控几个常见的暗网网站,由于篇幅有限,故只拿某暗网网站作为例子。

Scrapy代理设置:

代码语言:javascript
复制
class DarkwebSpiderDownloaderMiddleware(object):

    def process_request(self, request, spider):
        request.meta[\\\\\\\\\\\'proxy\\\\\\\\\\\'] = \\\\\\\\\\\'http://11.11.11.11:8118\\\\\\\\\\\'

多账号登录核心代码:

代码语言:javascript
复制
for accounts in Accounts:    count = 0    try:        logging.info(\\\\\\\\\\\'Account %s is logining ......\\\\\\\\\\\' % accounts)        cookie, sid = get_CookieSid(accounts, \\\\\\\\\\\'Testtest\\\\\\\\\\\')        __i__ = {\\\\\\\\\\\'cookie\\\\\\\\\\\': cookie, \\\\\\\\\\\'sid\\\\\\\\\\\': sid}        # print(__i__)        logging.info(\\\\\\\\\\\'Account %s finish login !\\\\\\\\\\\' % accounts)        __value__.append(__i__)    except Exception as e:        logging.error(\\\\\\\\\\\'[*] 超时,忽略一个账户!\\\\\\\\\\\')        count += 1        if(count > 7):            logging.error(\\\\\\\\\\\'[*] 用户登录个数过少~\\\\\\\\\\\')            return        continue

去重组件,主要用来减少请求量:

代码语言:javascript
复制
class DuplicateRequestMiddleware(object):

    #初始化redis
    def __init__(self):
        self.RedisQuery = RedisOpera(\\\\\\\\\\\'query\\\\\\\\\\\')

    #根据redis去重url
    def process_request(self, request, spider):
        spider.logger.info(\\\\\\\\\\\'duplicating >>>>>> %s\\\\\\\\\\\' % request.url)
        u = request.url
        import hashlib
        if \\\\\\\\\\\'vpic\\\\\\\\\\\' in request.url:
            b = u.index(\\\\\\\\\\\'=\\\\\\\\\\\') + 1
            MD5 = hashlib.md5()
            MD5.update(bytes(str(b), \\\\\\\\\\\'utf-8\\\\\\\\\\\'))
            if self.RedisQuery.query(MD5.hexdigest()):
                spider.logger.info(\\\\\\\\\\\'duplicate >>>>>> %s\\\\\\\\\\\' % request.url)
                raise IgnoreRequest("IgnoreRequest : %s" % request.url)
        else:
            spider.logger.info(\\\\\\\\\\\'ignore duplicate >>>>>> %s\\\\\\\\\\\' % request.url)
            return None
代码语言:javascript
复制
指定请求头的referer及User-Agent:
代码语言:javascript
复制
LOGIN_HEADERS = {    \\\\\\\\\\\'Host\\\\\\\\\\\': \\\\\\\\\\\'%s\\\\\\\\\\\' %load()[\\\\\\\\\\\'domain\\\\\\\\\\\'].split(\\\\\\\\\\\',\\\\\\\\\\\')[index],    \\\\\\\\\\\'Accept\\\\\\\\\\\': \\\\\\\\\\\'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\\\\\\\\\\\',    \\\\\\\\\\\'Accept-Encoding\\\\\\\\\\\': \\\\\\\\\\\'gzip, deflate\\\\\\\\\\\',    \\\\\\\\\\\'Referer\\\\\\\\\\\': \\\\\\\\\\\'http://%s/index.php\\\\\\\\\\\' %load()[\\\\\\\\\\\'domain\\\\\\\\\\\'].split(\\\\\\\\\\\',\\\\\\\\\\\')[index],    \\\\\\\\\\\'Content-Type\\\\\\\\\\\': \\\\\\\\\\\'application/x-www-form-urlencoded\\\\\\\\\\\',    \\\\\\\\\\\'Connection\\\\\\\\\\\': \\\\\\\\\\\'keep-alive\\\\\\\\\\\',    \\\\\\\\\\\'User-Agent\\\\\\\\\\\': \\\\\\\\\\\'Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0\\\\\\\\\\\'}

解析网页,主要是取出内容存入数据库:

代码语言:javascript
复制
def parse(self, response):
    item = DarkwebSpiderItem()
    soup = BeautifulSoup(response.text, \\\\\\\\\\\'lxml\\\\\\\\\\\')
    # 交易价格
    table = soup.find_all(name = \\\\\\\\\\\'table\\\\\\\\\\\', attrs = {\\\\\\\\\\\'class\\\\\\\\\\\':\\\\\\\\\\\'v_table_1\\\\\\\\\\\'})
    tr_list = table[0].find_all(\\\\\\\\\\\'tr\\\\\\\\\\\')
    td_list_price = tr_list[4].find_all(\\\\\\\\\\\'td\\\\\\\\\\\')
    price_list = re.findall(r\\\\\\\\\\\'d+.?d*\\\\\\\\\\\', td_list_price[3].get_text())
    price = price_list[0]
    # 成交数量
    td_list_volume = tr_list[6].find_all(\\\\\\\\\\\'td\\\\\\\\\\\')
    volume_list = re.findall(r\\\\\\\\\\\'d+\\\\\\\\\\\', td_list_volume[3].get_text())
    volume = volume_list[0]
    # 帖子内容
    content_list = soup.find_all(name=\\\\\\\\\\\'div\\\\\\\\\\\', attrs={\\\\\\\\\\\'class\\\\\\\\\\\': \\\\\\\\\\\'content\\\\\\\\\\\'})
    if len(content_list):
        content = content_list[0].get_text()
    else:
        content = \\\\\\\\\\\'\\\\\\\\\\\'
    # 图片url
    img_list = soup.find_all(name = \\\\\\\\\\\'img\\\\\\\\\\\', attrs = {\\\\\\\\\\\'class\\\\\\\\\\\':\\\\\\\\\\\'postimage\\\\\\\\\\\'})
    item[\\\\\\\\\\\'image_urls\\\\\\\\\\\'] = []
    if len(img_list) > 0 :
        url_list = []
        for img_url in img_list:
            if img_url[\\\\\\\\\\\'src\\\\\\\\\\\'].find(self.image_domain) > 0:
                download_url = img_url[\\\\\\\\\\\'src\\\\\\\\\\\']
            else:
                download_url = self.target_url + img_url[\\\\\\\\\\\'src\\\\\\\\\\\'].replace(\\\\\\\\\\\'./\\\\\\\\\\\', \\\\\\\\\\\'\\\\\\\\\\\')
            url_list.append(download_url)
        item[\\\\\\\\\\\'image_urls\\\\\\\\\\\'] = url_list
    # 发布时间
    p_author = soup.find_all(\\\\\\\\\\\'p\\\\\\\\\\\', attrs={\\\\\\\\\\\'class\\\\\\\\\\\': \\\\\\\\\\\'author\\\\\\\\\\\'})
    origin_publish_time = p_author[0].contents[4].strip()
    if len(origin_publish_time):
        # origin_publish_time = pt_str
        ptr_list = [x for x in filter(str.isdigit, str(origin_publish_time))]
        pt_str = "".join(ptr_list)
        y = pt_str[:4]
        d = pt_str[-6:-4]
        h = pt_str[-4:-2]
        min = pt_str[-2:]
        if len(pt_str) == 12:
            m = pt_str[4:6]
        else:
            m = \\\\\\\\\\\'0\\\\\\\\\\\' + pt_str[4]
        publish_time = y + \\\\\\\\\\\'-\\\\\\\\\\\' + m + \\\\\\\\\\\'-\\\\\\\\\\\' + d + " " + h + ":" + min + ":00"
    else:
        publish_time = \\\\\\\\\\\'\\\\\\\\\\\'
    dt = datetime.datetime.strptime(publish_time, "%Y-%m-%d %H:%M:%S")
    publish_time = dt.astimezone(pytz.timezone(\\\\\\\\\\\'UTC\\\\\\\\\\\')).strftime(\\\\\\\\\\\'%Y-%m-%d %H:%M:%S\\\\\\\\\\\')

    b = response.meta[\\\\\\\\\\\'content_url\\\\\\\\\\\'].index(\\\\\\\\\\\'=\\\\\\\\\\\') + 1
    item[\\\\\\\\\\\'title_id\\\\\\\\\\\'] = (response.meta[\\\\\\\\\\\'content_url\\\\\\\\\\\'])[b:]
    item[\\\\\\\\\\\'title\\\\\\\\\\\'] = response.meta[\\\\\\\\\\\'title\\\\\\\\\\\']
    item[\\\\\\\\\\\'url\\\\\\\\\\\'] = response.meta[\\\\\\\\\\\'content_url\\\\\\\\\\\']
    item[\\\\\\\\\\\'content\\\\\\\\\\\'] = content
    item[\\\\\\\\\\\'price\\\\\\\\\\\'] = price
    item[\\\\\\\\\\\'volume\\\\\\\\\\\'] = volume
    item[\\\\\\\\\\\'visits\\\\\\\\\\\'] = response.meta[\\\\\\\\\\\'visits\\\\\\\\\\\']
    item[\\\\\\\\\\\'publish_time\\\\\\\\\\\'] = publish_time
    yield item

当发现监控的关键字新增记录时,通过邮件通知:

代码语言:javascript
复制
def send_html_email(title, html, content, mailto, cc=None):
html_content = render_to_string(html, content)
send_mail = settings.EMAIL_TO.split(\\\\\\\\\\\',\\\\\\\\\\\') if mailto == \\\\\\\\\\\'\\\\\\\\\\\' else settings.EMAIL_TO

msg = EmailMultiAlternatives(title, html_content,
                             settings.EMAIL_LUCKY_NAME +    \\\\\\\\\\\'<\\\\\\\\\\\' + settings.EMAIL_HOST_USER + \\\\\\\\\\\'>\\\\\\\\\\\', send_mail, cc=cc)
msg.attach_alternative(html_content, "text/html")
msg.send()

四、可视化爬虫数据

Grafana是一个跨平台的开源的度量分析和可视化监控工具,可以通过将采集的数据查询然后可视化的展示,并及时通知,4.3以后的版本已支持MySQL数据源,因此读者可以使用Grafana来可视化同时配置邮件告警,具体操作方法还请自行查阅。

但是本文的暗网实时监控程序接入了安全管理平台,故采用自研的管理页面,可以更方便地搜索与查看暗网爬虫数据,大致效果如下:

五、总结

暗网监控对于大多数人是一个神秘的存在,本文一步一步地带领读者揭开这层神秘的面纱,从搭建代理服务器开始,在解释常见的反爬策略后,讲解了如何从零开发一个暗网网站监控程序,最后介绍了Grafana可视化监控工具,可以结合监控程序使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑客技术家园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、代理服务器搭建
    • 2.1 整体架构
      • 2.2 安装Tor
        • 2.3 配置Tor
          • 2.4 安装与配置Privoxy
            • 2.5 验证代理器是否可用
            • 三、开发实时监控程序
              • 3.1 暗网网站的特点
                • 3.2 暗网网站的反反爬虫
                  • 3.3 暗网监控的爬虫架构
                    • 3.4 监控程序的具体实现
                    • 四、可视化爬虫数据
                    • 五、总结
                    相关产品与服务
                    云数据库 Redis
                    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档