一、前言
在攻防演练中大家常用的方法就是钓鱼(懂的都懂)。随着大型攻防演练常态化的实施,我们认为演练+安全意识培训相结合的方式是比较理想的。 下文就是钓鱼演练中遇到的问题与思考,结合大师傅们的开源软件整理一篇”利用开源软件进行甲方钓鱼演练“。演练最终目的是安全意识摸底,公司或者部门级别的安全意识培训,方便在钓鱼演练后有连贯性的学习,加深印象。
注意:本文仅供学习参考研究,切勿利用所学知识做违法乱纪之事,否则后果自负!
二、规划演练
钓鱼的方式选择
-
凭证类钓鱼方式选择的初衷
- 通过钓鱼获取账号凭证。我们要哪些登录权限,钓到的账号密码外网是否可用?模拟外部攻击场景,如果克隆页面外部不能访问就容易被业务挑战。确保获取内部登录页面信息的合理性,证明通过钓鱼得到的账号密码可以被进一步利用,证明危害性。 甲方优势是知道资产中的账号关联哪些敏感重要的系统和信息,账号是否被二次认证导致无法使用等各种内部信息。这里也有部分好处推动相关的账号平台增加多因子验证。
- 甲方的优势就是知道自己公司的习惯和使用细节,体现在,公司用的邮箱系统,公司员工的个人电脑配置是什么样的操作系统如研发是mac,其他业务线是windows,具体到系统版本,杀软等特性。
- 检测业务同事是否有意识将钓鱼邮件事件通过正确的渠道反馈给安全部门。
-
木马钓鱼方式与凭证类钓鱼区别
- 木马钓鱼的初衷是获取个人电脑信息和建立据点横向拓展,此时就将的演练的初衷变成与办公网的杀毒软件、流量审计、防守方的发现处置能力对抗,非特殊情况不采取该方式演练。
- 木马钓鱼更接近于红蓝对抗场景,对用户的侵入性较大,不适宜大面积演练使用,控制不好会容易导致业务的反感。
- 本次演练选择获取账号凭证,批量发送邮件方式钓鱼。
三、实施钓鱼阶段 步骤
话术与剧本
- 第一原则禁止损害国家个人利益,内容不可以是政治、疫情、舆情、绯闻相关的钓鱼内容。
- 角色扮演者 ,谁发起的一项活动,这个角色有一定的合理性。举例HR、行政、企业IT,几乎会和每一名员工有工作交集。
- 事件合理性,发起这个邮件的互动一定遵循看似合理性,习惯性。合理性就是我因为看到邮件,所以我要点击这个链接参活动。这里就要充分利用甲方的优势做信息收集加以转换。如常见的公司通知是什么样的?对比外部攻击就要更关注邮件泄露或者是发送来往邮件观察邮件习惯了。
- 驱动受害者的动作,利诱或者威逼来使其来执行你想要让其做的事情,如点击一个页面,跳转到登录页,输入账号密码。
选择钓鱼页面的原则
- 钓什么账号最有价值,我们要关心的点是得到该账号我们能做什么?登录邮箱?合同系统等,这一步骤是能够说明危害点也是真实攻防过程中的一个攻击链路。 最好的选择是具有外部sso 内部erp混用的这种登录页面作为钓鱼克隆页面首选。
- 确定克隆页面以后要考虑,该页面在钓鱼话术的合理性。 如果钓鱼邮件账密,那么就剧本就是点击修改邮箱账号密码,所以克隆的页面应该是修改邮箱密码登录页面。 如果调用erp账号密码,那么就去把剧本到erp通用账号登录页面。 所以我们在选型登录页面的时候要考虑话术配合的合理性。
克隆钓鱼页面制作
- 克隆页面是内网服务,如果是内网页面就选择用”SiteCopy“去把页面克隆回来部署到你的国外VPS上,这里讲一下为什么使用国外VPS ,因为涉及到混淆的域名,所以这里也涉及到备案的问题。解决方案 : 外网VPS + 外网域名。内网系统的登录页面会有一定的挑战,那就是会被问内网的登录是如何泄露的,这一点一定要考虑攻击场景充分且合理。
- 克隆页面是外网服务,直接用 "Pricking" , 但是有些情况可能不会成功因为有一些复杂的登录页面还是不支持”Pricking"这种方式的。所以可以用“SiteCopy” 我们在本地部署一台VPS上,在“Pricking” hook登录的账密。\
页面部署
- 克隆的的fake页面需要部署到VPS中,选择宝塔这里咱们只是从快速部署的角度触发,如果有安全问题的话自行搭建Nginx。
- 使用宝塔签https非常方便,这样能够解决浏览器上的叹号提示问题。
- 域名绑定绑定域名目录非常方便,有时候一个vps需要多个服务的时候就非常方便了。上传文件的web管理界面也非常方便。
- 关于克隆页面服务(宝塔安全)权限最小原则,服务最少原则非必要不开启服务,0day什么的就不考虑了。 用的时候开启服务不用的时候关闭。
跳转的trick
- 合理的提示+跳转,Pricking是nginx代理原理,所以他会记录我们的实际流量中的请求数据,我们为了伪造的闭环,在用户点击提交以后,也就是POST 或者 GET数据后 ,我们的fake静态页面是不支后端服务的,所以数据请求后一定是走error模块,这里设置一个alert弹框提示"xxx活动结束" 在跳转到公司的论坛或者wiki(不是Pricking不支持哦)这里利用场景不同。 我们仅仅用Pricking的hook用户名密码功能。
- 前端js提示弹框修改alert的代码
window.alert = function(msg, callback) {
var div = document.createElement("div");
div.innerHTML = "<style type="text/css">"
+ ".nbaMask { position: fixed; z-index: 1000; top: 0; right: 0; left: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); } "
+ ".nbaMaskTransparent { position: fixed; z-index: 1000; top: 0; right: 0; left: 0; bottom: 0; } "
+ ".nbaDialog { position: fixed; z-index: 5000; width: 80%; max-width: 300px; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background-color: #fff; text-align: center; border-radius: 8px; overflow: hidden; opacity: 1; color: white; }"
+ ".nbaDialog .nbaDialogHd { padding: .2rem .27rem .08rem .27rem; } "
+ ".nbaDialog .nbaDialogHd .nbaDialogTitle { font-size: 17px; font-weight: 400; } "
+ ".nbaDialog .nbaDialogBd { padding: 0 .27rem; font-size: 15px; line-height: 1.3; word-wrap: break-word; word-break: break-all; color: #000000; } "
+ ".nbaDialog .nbaDialogFt { position: relative; line-height: 48px; font-size: 17px; display: -webkit-box; display: -webkit-flex; display: flex; } "
+ ".nbaDialog .nbaDialogFt:after { content: " "; position: absolute; left: 0; top: 0; right: 0; height: 1px; border-top: 1px solid #e6e6e6; color: #e6e6e6; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); } "
+ ".nbaDialog .nbaDialogBtn { display: block; -webkit-box-flex: 1; -webkit-flex: 1; flex: 1; color: #09BB07; text-decoration: none; -webkit-tap-highlight-color: transparent; position: relative; margin-bottom: 0; } "
+ ".nbaDialog .nbaDialogBtn:after { content: " "; position: absolute; left: 0; top: 0; width: 1px; bottom: 0; border-left: 1px solid #e6e6e6; color: #e6e6e6; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleX(0.5); transform: scaleX(0.5); } "
+ ".nbaDialog a { text-decoration: none; -webkit-tap-highlight-color: transparent; }"
+ "</style>"
+ "<div id="dialogs2" style="display: none">"
+ "<div class="nbaMask"></div>"
+ "<div class="nbaDialog">"
+ " <div class="nbaDialogHd">"
+ " <strong class="nbaDialogTitle"></strong>"
+ " </div>"
+ " <div class="nbaDialogBd" id="dialog_msg2">弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内</div>"
+ " <div class="nbaDialogHd">"
+ " <strong class="nbaDialogTitle"></strong>"
+ " </div>"
+ " <div class="nbaDialogFt">"
+ " <a href="https://www.zuoyebang.cc" class="nbaDialogBtn nbaDialogBtnPrimary" id="dialog_ok2">确定</a>"
+ " </div></div></div>";
document.body.appendChild(div);
var dialogs2 = document.getElementById("dialogs2");
dialogs2.style.display = 'block';
var dialog_msg2 = document.getElementById("dialog_msg2");
dialog_msg2.innerHTML = msg;
// var dialog_cancel = document.getElementById("dialog_cancel");
// dialog_cancel.onclick = function() {
// dialogs2.style.display = 'none';
// };
var dialog_ok2 = document.getElementById("dialog_ok2");
dialog_ok2.onclick = function() {
dialogs2.style.display = 'none';
callback();
};
};
alert("很遗憾活动结束!")
- 前端任意跳转的js代码
第一种:(跳转到b.html)
<script language="javascript" type="text/javascript">
window.location.href="b.html";
</script>
第二种:(返回上一页面)
<script language="javascript">
window.history.go(-1);
</script>
第三种:
<script language="javascript">
window.navigate("b.html");
</script>
第四种:
<script language="JavaScript">
self.location=’b.html’;
</script>
第五种:
<script language="javascript">
top.location=’b.html’;
</script>
域名的准备
- 国外的域名,原因绑定国外的vps快速解析,没有域名备案的烦恼。如果实战场景需要避免被快速溯源可以选择开启域名隐私保护。
- 浏览器的对抗,chrome新版本的浏览器会有钓鱼页面风险提示,猜测是根据主域名的相似度来判断的,所以我们可以用子域名混淆的方式来绕过,当然文件名可以做的逼真一些,新版本chrome浏览器会识别钓鱼页面,如图
- login.0day.com/redict.html 被识别概率较高
- login.oday.com.sso1.xyz/redict.html 识别率低
- 223.21.233.22 ip方式暂时没有被浏览器识别风险问题
- chrome 新版本的防钓鱼功能详见 <a href=https://blog.chromium.org/2021/07/m92-faster-and-more-efficient-phishing-detection.html>chrome M92 中更快、更高效的网络钓鱼检测</a> 所以在发送邮件前测试域名是否会被识别为钓鱼页面。
获取钓鱼页面中的账号密码
- 钓鱼演练最好能够确认用户的密码是正确的,理论上应该调用sso接口查询出该账号密码是否正确,这样输出的用户名,密码是准确的业务方不会挑战数据准确性。 密码也不做保留记录只记录账号和是否是正确密码即可。
- 如果没有sso记录,就在fake页面中password获取input表单数据的地方用md5加密密码,这样保证不会看到大量的用户明文密码。避免一些不好的影响,且项目前也把代码给一些业务方去review保证整个演练流程中不存在存储用户账密行为。
四、批量发送邮件
邮箱发送的准备
- outlook首选,垃圾过滤机制这块白名单会好一些。注册的话,可以用10分钟邮箱注册,在利用接码平台认证邮箱,outlook改昵称方式来混淆邮箱地址。
- henggeFish中用的大量的163邮箱,去某些交易软件搜索关键词,163的邮箱呢在配置SMTP的时候需要手机认证,目前是1个手机号认证15个邮箱。脚本是1个邮箱发10个地址。再根据演练人数就能计算需要用多少个邮箱账号了。 SMTP邮箱开启后会有个临时密码,这个密码才是发送邮件脚本使用的。
- 密送方式发送,用邮箱发送邮件的时候选择密送方式发送,这样收件人无法查看到这封邮件同时还发送给谁。但是小心会因为数据量大被ban。切记不要随便找一个邮件组就发送邮件,导致超出演练范围的人收到邮件。
- 所有工作准备好以后整体的去测试下全流程。