Is it possible to put binary image data into html markup and then get the image displayed as usual in any browser?

85,679

Solution 1

There are other (better) ways, described in other answers, to secure your files, but yes it is possible to embed the image in your html.

Use the <img> tag this way:

<img src="data:image/gif;base64,xxxxxxxxxxxxx...">

Where the xxxxx... part is a base64 encoding of gif image data.

Solution 2

If I needed security on my images directory I wouldn't expose the directory at all. Instead my img src attributes would reference a page that would take a userid and an image id as a parameter.

The page would validate that that user did indeed have access to see that picture. If everythings good, send the binary back. Otherwise send nothing.

for example:

<img src="imgaccess.php?userid=1111&imgid=223423" />

Also, I wouldn't use guessable id's. Instead sticking to something like base 64 encoded guid's.

Solution 3

I'm not sure I understand, but here goes. Instead of serving up static images that reside in an images folder - why couldn't you, using your server side technology of choice, have the images dynamically sent down to the client? That way your server side code can get in the mix and allow or deny access programmatically?

<img src="/images/getImage.aspx?id=123353 />

Solution 4

You could move the pictures out of the document root into a private directory and deliver them through your application, which has access to that directory. Each time your app generates an image tag, it then also generates a short-lived security token which must be specified when accessing a particular image:

<img src="/app/getImage.xyz?image=12345&token=12a342e32b321" />

Chances are very rare that someone will brute force the right token at the right time with the right image. There are at least to possibilities to verify the token in "getImage":

  1. Track all image tags in your app and store records in a database which link the randomly generated tokens and image IDs to the requesting users. The "getImage" action then checks the supplied parameters against that database.
  2. Generate the token as a checksum (MD5, CRC, whatever) over the user ID, the image ID and maybe the current day of the year, and be sure to mix in an unguessable salt. The "getImage" action will then recompute the checksum und check it against the specified one in order to verify the user's access. This method will produce less overhead than the first one.

PHP example:

$token = md5($_SESSION['user_id'].' '.$imageID.' '.$SECRET_SALT.' '.date('z'));
Share:
85,679
Joern Akkermann
Author by

Joern Akkermann

I'm a freelancing web-developer with the will to learn more and more and more and more :)

Updated on February 14, 2022

Comments

  • Joern Akkermann
    Joern Akkermann over 2 years

    It's an important security issue and I'm sure this should be possible.

    A simple example:

    You run a community portal. Users are registered and upload their pictures. Your application gives security rules whenever a picture is allowed to be displayed. For example users must be friends on each sides by the system, in order that you can view someone else's uploaded pictures.

    Here comes the problem: it is possible that someone crawls the image directories of your server. But you want to protect your users from such attacks.

    If it's possible to put the binary data of an image directly into the HTML markup, you can restrict the user access of your image dirs to the user and group your web application runs of and pass the image data to your Apache user and group directly in the HTML.

    The only possible weakness then is the password of the user that your web app runs as.

    Is there already a possibility?

  • Nightwolf
    Nightwolf about 14 years
    +1, good answer, but if your code validates the user's access, should it matter if the IDs are guessable?
  • the-banana-king
    the-banana-king about 14 years
    Thinking this over I find that it is easier to just apply the access constraints of the referencing HTML page again to the "getImage" action as someone wrote above. Nevertheless the checksum method may reduce the performance impact since it does not access any external resources to verify the request.
  • Admin
    Admin about 14 years
    +1 What would you think about doing some .htaccess magic and outputting something like <code>src="userid/user-image/"</code> and, treating that as a directory, lock or unlock it on a per-user basis?
  • Joern Akkermann
    Joern Akkermann about 14 years
    but then I have binary data in the src="" part. and I would take the userid from the current session, that's more secure.
  • Joern Akkermann
    Joern Akkermann about 14 years
    so xxxxxxxxxx is for the to_blob/read/to_binary command / for the binary data of the image? and must there be an "=" in the end?
  • Nightwolf
    Nightwolf about 14 years
    You will have to convert your binary data to base64 encoding. The result is a string of printable characters that will usually end in 1 or 2 "=" symbols, according to the base64 spec. You will need to replace the xxx's with that string, all on one line.
  • NotMe
    NotMe about 14 years
    @bmb: It wouldn't matter so much about the file id's. However, it would for member id's.
  • NotMe
    NotMe about 14 years
    @D_N: That sounds like an interesting approach. I'm not too familiar with the linux side of things, so it's hard to comment.
  • NotMe
    NotMe about 14 years
    @Joern Akkermann: I'm not sure why you'd have binary data in the src part... However, taking the userid from session is a valid approach. I tend to stay away from any session variables myself which is why I said put the userid in the src tag.
  • Joern Akkermann
    Joern Akkermann about 14 years
    I run IE tests always with the standard version that is shipped with Windows XP - I guess still many people use it...
  • mgutt
    mgutt about 9 years
    Some older browsers (IE7-IE9) have limitations
  • vol7ron
    vol7ron about 8 years
    I don't know how I stumbled across this old question/answer, but it's important to note that this is not binary as the OP mentioned. This is base64 ASCII encoding. The source was originally binary.
  • Steevie
    Steevie almost 8 years
    Found this conversation because I was looking for the same thing. The solution from @bmb just works great! Thanks.
  • FluorescentGreen5
    FluorescentGreen5 about 7 years
    Should mention that they're called data urls
  • Steve Kline
    Steve Kline over 6 years
    I'm surprised it's been so long and no one told you that you introduce a security vulnerability of local-file inclusion when you use PHP in this manor. It can lead to a remote-code execution exploit.
  • user3773048
    user3773048 over 5 years
    Thanks for this. I had not realized that I could simply parse a query parameter name token on my Express server middleware where I checked if the user was authenticated with their token... This is much cleaner than needing to perform an explicit GET request, then figuring out how to properly load the binary image data into the img HTML tag.... Doing it this way looks more like a proper API / like how Google Maps requires users provide them an access token, ie.
  • Lajos Arpad
    Lajos Arpad over 2 years
    This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review