日常的安全运营中总是发现很多开发的同学将代码片段和一些技术文档在企业内部搭建的wiki中进行记录,其中经常会包含一些密码、数据库连接字符串、认证token之类的敏感信息。而这些文章往往是public的权限任何wiki普通用户都可以浏览到,因此带来了极大的内部安全风险。一旦黑客获得其中一个员工的账号权限进入内网,wiki往往是获得大量可用敏感信息的首选途径,因此减少public权限的公开敏感信息就尤为重要。另外账号的暴露也不利于内部的安全审计,账户、口令被员工获取后恶意利用,进行未授权的访问,增加了企业的内部风险,而因为账号密码的泄漏往往会使安全事件的调查更加困难。
(2018.9.7 丰宁坝上草原)
在此背景下,搜索了网上也没找到针对wiki的审查工具,那么古语云“工欲善其事必先利其器”,既然没有现成的工具就自己new一个吧。
wikiscan是根据password、key等关键词在企业内网搭建的confluence wiki平台审计相关敏感文件和内容暴露的扫描工具,其设计思路如下:
此外,我们通过参数可以支持两种扫描模式,全局扫描和单页扫描。全局扫描可以通过参数指定扫描搜索结果的url条数,单页扫描可以通过参数输入具体的wiki url来扫描这个页面是否包含敏感内容。
wikiscan v1.0 命令行参数方式执行:
USAGE:
-l wiki url,singlepage scan mode use.
-c Number of search results.
-h Show help information.
-l:选填参数,单页扫描某个wiki url是否有敏感关键字;
-c:必填参数,用于全局模式设置扫描搜索的结果条数;
-h:帮助信息。
参数使用说明:-l 仅用于单页模式,-c 全局模式必填,单页模式无需填写
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#author:Darkpot
import requests
import json
import re
import yagmail
import argparse
class MyClass:
parser = argparse.ArgumentParser(description='wiki 敏感信息扫描')
parser.add_argument("-l", help="wiki url,singlepage scan mode use", type=str)
parser.add_argument("-c", help="Number of search results", type=int)
args = parser.parse_args()
input1 = args.l
count = args.c
def globalScan(self,count):
try:
#请求参数头设置
keydict = ['siteSearch+~+"password"','siteSearch+~+"密码"','siteSearch+~+"pwd"','siteSearch+~+"Authorization"']
url = 'http://wiki.com/rest/searchv3/1.0/cqlSearch'
headers = {'cookie':'wiki.sso.cookie='}
alist = []
keywords=[]
keyword_suffix=[]
#白名单
whitelist=['/pages/viewpage.action?pageId=12345']
#根据关键词将搜索结果uri全部收集起来
for b in keydict:
params = {"cql":b,"start":0,"limit":count,"includeArchivedSpaces":"false"}
req = requests.get(url,params=params,headers=headers)
a = req.text
middle = json.loads(a)
size = middle["size"]
for i in range(size):
href = middle["results"][i]["url"]
if href not in (alist+whitelist):
alist.append(href)
#将xml等数据格式的直接挑出来,其他的正则匹配关键字
#正则匹配样例:password= “”、password “”、password=12345、123
for q in alist:
url1='http://wiki.com'+q
houzui = re.findall(r"(\.txt|\.xml|\.csv|\.xsl|\.log|\.py|\.php|\.go|\.java|\.jsp)$",url1)
if houzui:
keyword_suffix.append(url1)
else:
req1 =requests.get(url1,headers=headers)
text =req1.text
password = re.findall(r"(?i)(password(s)?|pwd(s)?)\s*(={0,1}\s*(\"|')((?!密码|'|,)\S)+(\"|')|=\s*((?!密码|\")\S)+(,|\b))",text)
password1 = re.findall(r"(?i)\-p\s+(((?!密码|\"|123456)\S)+(,|\b)|(\"|')((?!密码|123456)\S)+(\"|'))",text)
password2 = re.findall(r"密码:((?!密码)\S)+(,|\b)",text)
password3 = re.findall(r"(?i)\<password(s)?\>((?!密码)\S)+\</password(s)?\>",text)
password6 = re.findall(r"\"\s*(password(s)?|pwd(s)?|Authorization)\s*\":\"\s*((?!密码)\w)+\s*\"",text)
password10 = re.findall(r"\s+(password(s)?|pwd(s)?|Authorization)\s*(:|:)\s*((?!密码|\")\S)+(,|\b)",text)
password12 = re.findall(r"\"(password(s)?|pwd(s)?)\"\s*(,\s*\[\"((?!密码)\S)+\"\]|=>\s*\"((?!密码)\S)+\",)",text)
if password:
keywords.append(url1)
elif password1:
keywords.append(url1)
elif password2:
keywords.append(url1)
elif password3:
keywords.append(url1)
elif password6:
keywords.append(url1)
elif password10:
keywords.append(url1)
elif password12:
keywords.append(url1)
yag = yagmail.SMTP(user = '[email protected]', password = 'password', host = 'smtp.163.com')
yag.send(to = ['[email protected]'], subject = 'wiki 敏感信息扫描', contents = ['关键词正则匹配:\n',str(keywords),'关键词+数据文件后缀匹配:\n',str(keyword_suffix)])
except:
print("\n程序执行失败\n")
def singlePage(self,wiki):
try:
keywords0=[]
keyword_suffix0=[]
headers = {'cookie':'wiki.sso.cookie='}
houzhui = re.findall(r"(\.txt|\.xml|\.csv|\.xsl|\.log|\.py|\.php|\.go|\.java|\.jsp)$",wiki)
if houzhui:
keyword_suffix0.append(wiki)
else:
req0 =requests.get(wiki,headers=headers)
text0 =req0.text
password0 = re.findall(r"(?i)(password(s)?|pwd(s)?)\s*(={0,1}\s*(\"|')((?!密码|'|,)\S)+(\"|')|=\s*((?!密码|\")\S)+(,|\b))",text0)
password7 = re.findall(r"(?i)\-p\s+(((?!密码|\"|123456)\S)+(,|\b)|(\"|')((?!密码|123456)\S)+(\"|'))",text0)
password8 = re.findall(r"密码:((?!密码)\S)+(,|\b)",text0)
password9 = re.findall(r"(?i)\<password(s)?\>((?!密码)\S)+\</password(s)?\>",text0)
password5 = re.findall(r"\"\s*(password(s)?|pwd(s)?|Authorization)\s*\":\"\s*((?!密码)\w)+\s*\"",text0)
password4 = re.findall(r"\s+(password(s)?|pwd(s)?|Authorization)\s*(:|:)\s*((?!密码|\")\S)+(,|\b)",text0)
password11 = re.findall(r"\"(password(s)?|pwd(s)?)\"\s*(,\s*\[\"((?!密码)\S)+\"\]|=>\s*\"((?!密码)\S)+\",)",text0)
if password0:
keywords0.append(wiki)
elif password7:
keywords0.append(wiki)
elif password8:
keywords0.append(wiki)
elif password9:
keywords0.append(wiki)
elif password5:
keywords0.append(wiki)
elif password4:
keywords0.append(wiki)
elif password11:
keywords0.append(wiki)
print("关键词正则匹配:\n"+str(keywords0))
print("关键词数据文件后缀匹配:\n"+str(keyword_suffix0))
except:
print("\n程序执行失败\n")
x = MyClass()
if x.input1:
x.singlePage(x.input1)
else:
x.globalScan(x.count)
以上就是分享的wiki敏感字段的扫描工具,后续会继续更新对token、key、secret等关键词以及jira系统的支持。大家可以参考这个思路定制符合自己企业的内部系统敏感信息收集工具,感谢大家关注。
Github:(https://github.com/hashwormer/wikiscan)