A few years ago, we saw how a browser extension introduced a threat to serve unwanted ads. Today, the number of browser extensions available to users has grown, along with the risk for this similar behavior to occur.
We recently came across a similar case where several completely different websites contained what appeared to be a base64-encoded image, only visible from source-code view.
Base64 Encoded Images
There are a variety of approaches to displaying images on websites. The most common method is to upload the file to the server and use an <img> tag pointing to it.
This tag is pretty versatile. In addition to accepting image files hosted on the same server, it accepts remote files. And believe it or not, the entire image encoded as a base64 string.
For example, if you place this code directly onto your browser URL bar, what you get is our logo:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF4AAAAhCAYAAABQphx6AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAPvSURBVGhD7ZlPSNRBFMd/RV1qDx3KFCHQDh6CskuH8hBCISVGlw5CCIpS4ElqQQhREcQ1vHlRDEwQCozyKLp1sA4dcoOCAjOIQo0OHSqEDtWbfe/n7Oz83Z3dn8bvA8O8N7759933+83suufPP4KYsrMX65gyEwsfEbHwEWF8x/f09ASZTAY9NZWVlcHs7CyzGxsbWS2STqfR2sYlFlDF80BfXZw4tm2szdxAzY19aOUzdW2B1dqMh4lsRAc2NjbQKh22G5+enkbLDzCv7dy2KIX3PVExLC8vO62nra0NrfKjelJFvL3jbScshL6+PrT+H6TCd3V1oZUPCCyWUmLKdHEdpV6PCD+/y9xS4VdXV9Gyo9ybJcR5y7UOeJXphIYDlEp7dX9QsXImLIT0VgMHKtxmZNTX1wdjY2PoyVFlqWyhpliXsXh0T4rYV4w1jU2sr68HVVVV6G3T23sHrXyGh4dYrbxO6hZOqBboIpYuFm4nqhuKSRwX4U0sLqaDpSV5HxKSx0Z45eFqszjYHJS5uTls8YuvayHshS86JienmHBUAJXoxaC91diID4yPj2szLApshQZ4odfWPmJraTFeJ20XD/j+EgXniW8oi6PGKDxBH8D8/Dy25NPa2oqWH1SHuG0iAHw27xTRAWvhiUQi4bRxHzQ0NIQfvKvoOxWt8KlUCq1cCj30Wlpa0LIHhB4cHERPT7nezz4o6jopA4Qqpq8tAwNDwdbWFnq50JXNR8bDWLpxvF8nC6GpqYnVLgLCz8kQb9sHNgVFJfpuQSp8oRmbTCbRMkNi02/4JkhwF2TZuFPwlvFixoI/MTGBXha4HpLgroCIzc2X0NPDf0DFiF9bW4OWf5TveEKX/YUI6AtZ9tuIDN9MVYdwZ2eHVGzdkyab0ybeKHxMafB6uMbYIxW+4+HFsNjw5O1MTqxrfxm2fV3nEWOpf+rZbWwpDOj//utr9MwoMx5+xD+wP4Fe7gZ//f6R48ugfwRQjBgv+gMLN5n/6fsHbMly7+Vd1r7y5QW25MPPQ2ujeLChwDgqoH/y/CizKZ7gfV1dd+RkUFdxKtwHFeDbz83QDoF3vEj7gwthIZ/g7cdv7oe1GEOFfIJvB8QYUy0C7VC6H10Nfb4mdO2yv/HthBgH9avPz5lNWgAjT2+xWozn0Wa8DD67dECcbAzVuCZ0/UYuz7BM56F401ppnWKc7TpPV59FKx/ZuIT2cKWOVNMgxw4dZ/aVE9eZb4LvD68S3gebAL/7XD96WeDxpViAap7DB4+ilf0Q+HhA1oegWFiHbp0Eb6uAdz0fR3vM6YuZHzmyx3G3824zo9xXfI+PiPgeHwlB8BdHxcoc+I6iOAAAAABJRU5ErkJggg==
Although using base64-encoded image files as a method to make pages load faster (fewer GET requests to image files), there are some drawbacks as well. The disadvantages to this method include CDNs and caches, file size, and CPU overhead for decoding the string.
This optimization technique stores images in the page source, which the browser directly interprets. This avoids the request and transfer of additional files from the server to the client.
Unwanted Code Snippets
We found the following code on several websites using a variety of plugins and themes on entirely different servers altogether.
<p><span style="border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font-style: normal; font-variant-caps: normal; font-weight: bold; font-stretch: normal; font-size: 11px; line-height: 20px; font-family: 'Helvetica Neue', Helvetica, sans-serif; color: #ffffff; background-image: url(data:image/svg+xml; base64,phn2zyb4bwxucz0iahr0cdovl3d3dy53my5vcmcvmjawmc9zdmciighlawdodd0imzbwecigd2lkdgg9ijmwchgiihzpzxdcb3g9ii0xic0xidmxidmxij48zz48cgf0acbkpsjnmjkundq5lde0ljy2mibdmjkundq5ldiyljcymiaymi44njgsmjkumju2ide0ljc1ldi5lji1nibdni42mzismjkumju2idaumduxldiyljcymiawlja1mswxnc42njigqzaumduxldyunjaxidyunjmyldaumdy3ide0ljc1ldaumdy3iemymi44njgsmc4wnjcgmjkundq5ldyunjaxidi5ljq0oswxnc42njiiigzpbgw9iinmzmyiihn0cm9rzt0ii2zmziigc3ryb2tllxdpzhropsixij48l3bhdgg+phbhdgggzd0itte0ljczmywxljy4nibdny41mtysms42odygms42njusny40otugms42njusmtqunjyyiemxljy2nswymc4xntkgns4xmdksmjquodu0idkuotcsmjyunzq0iem5ljg1niwyns43mtggos43ntmsmjqumtqzidewljaxniwymy4wmjigqzewlji1mywymi4wmsaxms41ndgsmtyuntcyidexlju0ocwxni41nzigqzexlju0ocwxni41nzigmteumtu3lde1ljc5nsaxms4xntcsmtqunjq2iemxms4xntcsmtiuodqyideyljixmswxms40otugmtmuntiyldexljq5nsbdmtqunjm3ldexljq5nsaxns4xnzusmtiumzi2ide1lje3nswxmy4zmjmgqze1lje3nswxnc40mzygmtqundyylde2ljegmtqumdkzlde3ljy0mybdmtmunzg1lde4ljkznsaxnc43ndusmtkuotg4ide2ljayocwxos45odggqze4ljm1mswxos45odggmjaumtm2lde3lju1niaymc4xmzysmtqumdq2iemymc4xmzysmtauotm5ide3ljg4ocw4ljc2nyaxnc42nzgsoc43njcgqzewljk1osw4ljc2nya4ljc3nywxms41mzygoc43nzcsmtqumzk4iem4ljc3nywxns41mtmgos4ymswxni43mdkgos43ndksmtcumzu5iem5ljg1niwxny40odggos44nzismtcunia5ljg0lde3ljczmsbdos43ndesmtgumtqxidkuntismtkumdizidkundc3lde5ljiwmybdos40miwxos40nca5lji4ocwxos40otegos4wncwxos4znzygqzcunda4lde4ljyymia2ljm4nywxni4yntigni4zodcsmtqumzq5iem2ljm4nywxmc4yntygos4zodmsni40otcgmtuumdiyldyundk3iemxos41ntusni40otcgmjmumdc4ldkunza1idizlja3ocwxmy45otegqzizlja3ocwxoc40njmgmjaumjm5ldiylja2miaxni4yotcsmjiumdyyiemxnc45nzmsmjiumdyyidezljcyocwyms4znzkgmtmumzayldiwlju3mibdmtmumzayldiwlju3miaxmi42ndcsmjmumdugmtiundg4ldizljy1nybdmtiumtkzldi0ljc4ncaxms4zotysmjyumtk2idewljg2mywyny4wntggqzeylja4niwyny40mzqgmtmumzg2ldi3ljyznyaxnc43mzmsmjcunjm3iemyms45nswyny42mzcgmjcuodaxldixljgyocayny44mdesmtqunjyyiemyny44mdesny40otugmjeuotusms42odygmtqunzmzldeunjg2iibmawxspsijymqwodfjij48l3bhdgg+pc9npjwvc3znpg==); background-size: 14px 14px; background-color: #bd081c; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; border: none; -webkit-font-smoothing: antialiased; top: 1271px; left: 1022px; background-position: 3px 50%; background-repeat: no-repeat no-repeat;">Save</span>
As we can see, the code above loaded a base64-encoded image as a background for the paragraph. This snippet fails to form an image. As such, it’s not visible to visitors. Only the webmaster can detect it. This is most likely due to the fact that the entire string is in lowercase, a problem when we are talking about base64, which is case sensitive.
Although the HTML looks harmless, the website owner didn’t add them himself. The injection reoccurred on any posts the owner edited.
In order to identify the vector causing these unwanted injections, we investigated the common plugins, themes, and users among all the sites showing this odd behavior. And what was the prevalent common element between them? The webmaster. The same person manages all of the websites. This opened the possibility that the cause of these injections was an extension within the browser itself.
Pinterest Browser Extensions Leaking Malformed HTML
We know that browser extensions can go “rogue”, but we have to keep in mind that these extensions are still prone to buggy code that can cause those adverse effects.
Upon further inspection, we found the culprit to be Pinterest’s Browser button.
To decode an extension in FireFox, the easiest way to proceed is to open the .xpi file as if it was a normal zip file. This gives us all of the files involved. Within one of those files, namely local/ext/v3/js/logic.js, we find the following:
style: { // base rules for all Save buttons 'border-radius': '2px', 'text-indent': '20px', 'width': 'auto', 'padding': '0 4px 0 0', 'text-align': 'center', 'font': '11px/20px "Helvetica Neue", Helvetica, sans-serif', 'font-weight': 'bold', 'color': '#ffffff, 'background': '#bd081c url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzBweCIgd2lkdGg9IjMwcHgiIHZpZXdCb3g9Ii0xIC0xIDMxIDMxIj48Zz48cGF0aCBkPSJNMjkuNDQ5LDE0LjY2MiBDMjkuNDQ5LDIyLjcyMiAyMi44NjgsMjkuMjU2IDE0Ljc1LDI5LjI1NiBDNi42MzIsMjkuMjU2IDAuMDUxLDIyLjcyMiAwLjA1MSwxNC42NjIgQzAuMDUxLDYuNjAxIDYuNjMyLDAuMDY3IDE0Ljc1LDAuMDY3IEMyMi44NjgsMC4wNjcgMjkuNDQ5LDYuNjAxIDI5LjQ0OSwxNC42NjIiIGZpbGw9IiNmZmYiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxIj48L3BhdGg+PHBhdGggZD0iTTE0LjczMywxLjY4NiBDNy41MTYsMS42ODYgMS42NjUsNy40OTUgMS42NjUsMTQuNjYyIEMxLjY2NSwyMC4xNTkgNS4xMDksMjQuODU0IDkuOTcsMjYuNzQ0IEM5Ljg1NiwyNS43MTggOS43NTMsMjQuMTQzIDEwLjAxNiwyMy4wMjIgQzEwLjI1MywyMi4wMSAxMS41NDgsMTYuNTcyIDExLjU0OCwxNi41NzIgQzExLjU0OCwxNi41NzIgMTEuMTU3LDE1Ljc5NSAxMS4xNTcsMTQuNjQ2IEMxMS4xNTcsMTIuODQyIDEyLjIxMSwxMS40OTUgMTMuNTIyLDExLjQ5NSBDMTQuNjM3LDExLjQ5NSAxNS4xNzUsMTIuMzI2IDE1LjE3NSwxMy4zMjMgQzE1LjE3NSwxNC40MzYgMTQuNDYyLDE2LjEgMTQuMDkzLDE3LjY0MyBDMTMuNzg1LDE4LjkzNSAxNC43NDUsMTkuOTg4IDE2LjAyOCwxOS45ODggQzE4LjM1MSwxOS45ODggMjAuMTM2LDE3LjU1NiAyMC4xMzYsMTQuMDQ2IEMyMC4xMzYsMTAuOTM5IDE3Ljg4OCw4Ljc2NyAxNC42NzgsOC43NjcgQzEwLjk1OSw4Ljc2NyA4Ljc3NywxMS41MzYgOC43NzcsMTQuMzk4IEM4Ljc3NywxNS41MTMgOS4yMSwxNi43MDkgOS43NDksMTcuMzU5IEM5Ljg1NiwxNy40ODggOS44NzIsMTcuNiA5Ljg0LDE3LjczMSBDOS43NDEsMTguMTQxIDkuNTIsMTkuMDIzIDkuNDc3LDE5LjIwMyBDOS40MiwxOS40NCA5LjI4OCwxOS40OTEgOS4wNCwxOS4zNzYgQzcuNDA4LDE4LjYyMiA2LjM4NywxNi4yNTIgNi4zODcsMTQuMzQ5IEM2LjM4NywxMC4yNTYgOS4zODMsNi40OTcgMTUuMDIyLDYuNDk3IEMxOS41NTUsNi40OTcgMjMuMDc4LDkuNzA1IDIzLjA3OCwxMy45OTEgQzIzLjA3OCwxOC40NjMgMjAuMjM5LDIyLjA2MiAxNi4yOTcsMjIuMDYyIEMxNC45NzMsMjIuMDYyIDEzLjcyOCwyMS4zNzkgMTMuMzAyLDIwLjU3MiBDMTMuMzAyLDIwLjU3MiAxMi42NDcsMjMuMDUgMTIuNDg4LDIzLjY1NyBDMTIuMTkzLDI0Ljc4NCAxMS4zOTYsMjYuMTk2IDEwLjg2MywyNy4wNTggQzEyLjA4NiwyNy40MzQgMTMuMzg2LDI3LjYzNyAxNC43MzMsMjcuNjM3IEMyMS45NSwyNy42MzcgMjcuODAxLDIxLjgyOCAyNy44MDEsMTQuNjYyIEMyNy44MDEsNy40OTUgMjEuOTUsMS42ODYgMTQuNzMzLDEuNjg2IiBmaWxsPSIjYmQwODFjIj48L3BhdGg+PC9nPjwvc3ZnPg==) 3px 50% no-repeat', 'background-size': '14px 14px', // extra rules for extensions only 'position': 'absolute', 'opacity': '1', 'zIndex': '8675309', 'display': 'none', 'cursor': 'pointer', 'border': 'none', 'font-weight': 'bold', '-webkit-font-smoothing': 'antialiased', '-moz-osx-font-smoothing': 'grayscale' },
This time, the base64 code is correctly cased. The results are a valid Pinterest icon.
When we convert the base64 code to a complete lower-case string, the exact string is injected onto the website.
Is This Injection Serious?
Well, yes and no. In its current state, the browser extension simply adds a buggy piece of code to any content you write – including posts, emails, and chat boxes. No visible impact is made to other users since the HTML is malformed.
However, if we’re talking about the fact that it’s an extension that causes code to jump onto whatever content you write, this becomes more critical. Imagine the severity of this injection if you are browsing your bank’s website, sending an important email, or submitting your personal information on a purchase page? What if it opens a vulnerability on your website?
Moral of the Story
A quick look through the web indicates that there are at least 5,000 websites impacted by this bug. This malformed HTML is hidden in their posts.
Even though this injection is not malicious in its current form (caused by malware or actually displaying anything to your website visitors), it’s still an unintended behavior by a browser extension which has probably resulted from a bug within the extension itself.
The key takeaway is to be mindful of what extensions we use on our browsers as they can directly interact with what is presented to us, especially when we are handling sensitive data or areas.