Author Topic: Pic Security  (Read 39279 times)

0 Members and 1 Guest are viewing this topic.

Offline thr0ne

  • Newbie
  • *
  • Posts: 34
    • View Profile
Pic Security
« on: September 02, 2002, 03:29:11 PM »
Quote
leider nützt das Skript das die Bilder vor dem unbefugten speichern Schützen sollte nicht viel. Wie bei meisten dieser Skripts gibts hier einen einfachen Trick:

- Rechte Maustaste gedrückt halten
- Dialog (Copyright....) mit Return schließen
- anschließend die rechte Maustaste wieder loslassen.

=> Schwupp das Context-Menü ist da  

Gibts keine Abhilfe? Wer hat ne Idee das besser zu schützen?


Ich sichere nur kleine Firmennetzwerke keine Bilder :) trotzdem hab ich eine Methode:



1. Verzeichnis schützen

Schützen sie Ihr Verzeichnis mit einer .htaccess Datei.
(leere Datei oder Errordokumentangabe)


2. Grafik anzeigen

Das Script zum Anzeigen der Grafik zeigt das Bild mit
Hilfe einer Tabelle an. Der Trick: Das eigentliche Bild wird als
Hintergrundbild eingebaut, als Inhalt für die Tabellenzelle verwenden
wir ein transparentes Gif. Somit ist das Abspeichern der Grafik
per Rechts-Klick auch unterbunden.

Der Trick in Html:
Code: [Select]

<table CELLSPACING=0 CELLPADDING=0 COLS=1 WIDTH="100" HEIGHT="100">
<tr><td BACKGROUND="ihrbild.gif">
<img SRC="transparent.gif" height=100 width=100>
</td></tr></table>

Dieses Wissen verwenden wir nun in den PHP Dateien:

Quellcode "view_image.php":
Code: [Select]

<?php 

session_start
(); 

// Cache deaktivieren 
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 
header("Last-Modified: " gmdate("D, d M Y H:i:s") ." GMT"); 
header("Pragma: no-cache"); 
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate"); 

// Challenge-ID 
mt_srand((double)microtime()*1000000); 

$random mt_rand(); 
$random md5(uniqid($random,TRUE)); 

$sess_challenge_id $random

if(!
session_is_registered("sess_challenge_id")): 
  
session_register("sess_challenge_id"); 
endif; 

// Grafik auslesen 
$pic    "tolle-grafik.jpg"
$img    = @GetImageSize("/absoluter/pfad/zu/verzeichniss/images/".$pic); 
$width  $img[0]; 
$height $img[1]; 

// HTML-Tabelle anzeigen 
printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%s\" height=\"%s\">\n",$width,$height); 
print 
"<tr>\n"
printf("<td width=\"%s\" height=\"%s\" background=\"read_image.php?img=%s&challenge=%s\">",$width,$height,rawurlencode($pic),$sess_challenge_id); 
printf("<img border=\"0\" src=\"blind.gif\" width=\"%s\" height=\"%s\">",$width,$height); 
print 
"</td>\n"
print 
"</tr>\n"
print 
"</table>\n"

?>


Erklärung:
Als allererstes müssen Sie eine Session starten.
Danach deaktivieren Sie sicherheitshalber noch den
Cache und erzeugen eine 32 Zeichen lange "Challenge-ID".
Solche Challenge-ID's kann man übrigens auch gut verwenden,
um beispielsweise Reloads zu erkennen.
Diese Challenge-ID registrieren wir als Session-Variable.
Nun müssen Sie nur noch mit GetImageSize()
die Grösse der Grafik auslesen.

Nun kommt der eigentliche Trick:
Anstatt die Grafik direkt einzusetzen,
starten wir dagegen ein zweites Script
"read_image.php" und hängen als GET-Parameter
den Namen der Grafik-Datei und unsere
Challenge-ID hinten dran.

3. Grafik auslesen:

Nun benötigen Sie ein zweites Script, um Ihre
Grafik aus dem geschützten Verzeichnis auszulesen.
Der Quellcode dazu sieht folgendermaßen aus:
Code: [Select]

<?php 

session_start
(); 

// Challenge-ID OK -> Bild anzeigen 
if(session_is_registered("sess_challenge_id") and $sess_challenge_id == $challenge): 

  
session_unregister("sess_challenge_id"); 

  
$path "/asoluter/pfad/zu/verzeichniss/images/"
  
$img  rawurldecode($img); 
  
$read = @GetImageSize($path.$img); 
  
$type $read[2]; 

  
// Nun bestimmen wir den Datei-Typ, damit wir dem Browser sagen können 
  // welcher Grafik-Typ er nun vorgeschmissen bekommt 
  
switch($type
    { 
    case 
1
      
$mime "image/gif"
    break; 
    case 
2
      
$mime "image/jpeg"
    break; 
    case 
3
      
$mime "image/png"
    break; 
    case 
4
      
$mime "application/x-shockwave-flash"
    break; 
    } 

  
// Nun senden wir die Header und lesen mit readfile() unsere 
  // Grafik aus und senden diese direkt an den Browser 
  
header("Content-Type: $mime"); 
  
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 
  
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); 
  
header("Pragma: no-cache"); 
  
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate"); 
  
readfile($path.$img); 

// Unerlaubter Zugriff -> Transparentes GIF *ätsch* 
else: 
  
header("Content-type: image/gif"); 
  
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 
  
header("Last-Modified: " gmdate("D, d M Y H:i:s") ." GMT"); 
  
header("Pragma: no-cache"); 
  
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate"); 
  
readfile("blind.gif"); 
endif; 

?>


Als erstes überprüfen Sie, ob Ihre Session-Variable
registriert wurde und wenn ja, ob diese mit der übermittelten
Variable "challenge" übereinstimmt. Ist dies der Fall,
befreien Sie zuerst Ihre Session-Variable,
damit man die URL nicht per Copy & Paste aus dem
Quelltext in den Browser übernehmen kann.
Danach bestimmen Sie wieder mit GetImageSize() den
Grafiktyp, damit Sie dem Browser die richtigen Header übermitteln können.
Nun müssen Sie nur noch die Grafik per readfile() direkt an den Browser senden.

Falls jedoch keine Session-Variable registriert wurde bzw.
die beiden Challenge-ID's nicht übereinstimmen,
wird lediglich ein transparentes Gif ausgelesen und angezeigt.

Fassen wir das Ganze noch einmal zusammen und sehen uns an,
auf welche Arten unsere Grafik geschützt wurde:

Verzeichnisschutz per .htaccess
-> kein Zugriff per Browser
Grafik als Tabellen-Hintergrund mit transparentem Gif als Inhalt
-> beim Speichern wird nur das transparente GIF abgespeichert
Session-Variable wurde nicht registriert bzw. Challenge-ID's stimmen nicht überein
-> transparentes Gif wird angezeigt

Somit sind die Bilder vor so gut wie allen bekannten Zugriffs-
methoden sicher.


Ach ja - Jan - falls du das liest, ich würde niemals verlangen das du sowas ganz einbindest, aber den HTML-Trick von 2., wie würde man den
am besten in 4images umsetzen?

greets, phil

Offline Jan

  • Administrator
  • 4images Guru
  • *****
  • Posts: 5.024
    • View Profile
    • 4images - Image Gallery Management System
Pic Security
« Reply #1 on: September 02, 2002, 03:56:37 PM »
Spar Dir am besten das rumgefummel, Bilder lassen sich nicht schützen. Trotz aller Anstrengungen kann man am Ende einfach einen Screenshot machen und schon hat man das Bild.

Jan
Your first three "must do" before you ask a question:
1. Forum rules
2. FAQ
3. Search

Offline Chris

  • 4images Moderator
  • 4images Guru
  • *****
  • Posts: 4.487
  • Did u ever stop to think and then forget to start?
    • View Profile
Looks very interesting
« Reply #2 on: September 02, 2002, 10:18:50 PM »
thr0ne:

Any chance you could repost this in english?

By the way, I've also seen javascript that triggers a history.back() if the onBlur event happens.  That way if the user presses any key to take a screen shot, or switches windows, the picture can't be grabbed.

Offline bernd

  • Full Member
  • ***
  • Posts: 214
    • View Profile
Pic Security
« Reply #3 on: September 03, 2002, 12:59:40 AM »
Quote from: Jan
Spar Dir am besten das rumgefummel, Bilder lassen sich nicht schützen. Trotz aller Anstrengungen kann man am Ende einfach einen Screenshot machen und schon hat man das Bild.


Trägt nicht zum Thema bei aber trotzdem: genau meine Meinung

cheers,
Bernd[/b]

Offline thr0ne

  • Newbie
  • *
  • Posts: 34
    • View Profile
Pic Security
« Reply #4 on: September 03, 2002, 02:02:06 PM »
ja kommt, ausser meinen beitrag runterzumachen kommen hier keine kommentare?

ich finde dieser vorgang hat vorteile:
- kein besucher kann ein ganzes verz. voller bilder
  ziehen/ drauf zugreifen

- die lästige rechtsclicksperre ist nicht mehr unbedingt
  nötig

- kein besucher wird sich die mühe machen 100+ Bilder
  per Screenshot zu zocken, während die oben genannte
  Methode mit der Javascriptüberbrückung recht einfach ist.

ok...Chris , i ll try to send this in short summary to your email soon

Offline Jan

  • Administrator
  • 4images Guru
  • *****
  • Posts: 5.024
    • View Profile
    • 4images - Image Gallery Management System
Pic Security
« Reply #5 on: September 03, 2002, 03:34:37 PM »
Quote
ja kommt, ausser meinen beitrag runterzumachen kommen hier keine kommentare?

Es war nicht meine Absicht Deinen Beitrag runterzumachen. Sorry, wenn es so rübergekommen ist.

Quote
- kein besucher kann ein ganzes verz. voller bilder ziehen/ drauf zugreifen

Das sollte bei einem richtig konfigurierten Server sowieso nicht möglich sein.

Quote
- die lästige rechtsclicksperre ist nicht mehr unbedingt nötig

Das war vor einiger Zeit ein Wunsch mehrerer User und nie wirklich als Schutz gedacht.

Quote
- kein besucher wird sich die mühe machen 100+ Bilder
  per Screenshot zu zocken, während die oben genannte
  Methode mit der Javascriptüberbrückung recht einfach ist.

Die meisten möchtes ja sowieso nur 1 oder 2 Bilder haben. Die Leute die wirklich alle Bilder ziehen wollen, schaffen es dann auch trotzdem.

Kennst Du diesen Beitrag schon: http://www.4homepages.de/forum/viewtopic.php?p=4769#4769

Gruß Jan
Your first three "must do" before you ask a question:
1. Forum rules
2. FAQ
3. Search

Offline bernd

  • Full Member
  • ***
  • Posts: 214
    • View Profile
Pic Security
« Reply #6 on: September 03, 2002, 08:45:00 PM »
Quote from: thr0ne
ja kommt, ausser meinen beitrag runterzumachen kommen hier keine kommentare?


Sorry thr0ne - auch nicht meine Absicht. Technisch sehr interessant und ausgebufft; ich würd's nicht hinbekommen (zum Glück muß ich's auch nicht). Aber wie Jan denke ich auch, daß es den Aufwand nicht wert ist - wer die Bilder haben will, der kriegt sie auch - so ist das leider.

Just my 0.02€
cheers,
Bernd

Offline JMS

  • Newbie
  • *
  • Posts: 44
    • View Profile
Pic Security
« Reply #7 on: September 10, 2002, 03:21:50 PM »
Quote from: bernd
Technisch sehr interessant und ausgebufft


... klingt irgendwie untertrieben. Ich habe mir gestern 'nen Wolf getippt, selber was gestrickt aber richtig funktioniert hat's erst nicht. Ich werd's mal mit dem Scrpit ausprobieren!

Gruss

JMS

Offline Nossie

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • GothicWinter.Com
Pic Security
« Reply #8 on: September 14, 2002, 12:44:50 PM »
or you could just retrieve the images from the cache no ? :P
MOTD: LINUX IS LIKE A WIGWAM - NO WINDOWS, NO GATES, APACHE INSIDE !!!

Offline Chris

  • 4images Moderator
  • 4images Guru
  • *****
  • Posts: 4.487
  • Did u ever stop to think and then forget to start?
    • View Profile
Perhaps not
« Reply #9 on: September 29, 2002, 06:06:14 PM »
Quote
or you could just retrieve the images from the cache no ?


Code: [Select]
header("Pragma: no-cache");
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");

Offline Chris

  • 4images Moderator
  • 4images Guru
  • *****
  • Posts: 4.487
  • Did u ever stop to think and then forget to start?
    • View Profile
English translation of the posted method
« Reply #10 on: September 29, 2002, 06:18:25 PM »
For everyone's benefit in this forum, here is the english translation I received from thr0ne.  Sorry it's so late, I received it very shortly after asking for it, I just didn't think of posting it here until now.

Quote

1. Secure your Directory

Secure it with a .htaccess file in it.
(empty file)


2. View the Pic

The viewscript shows the Picture in a table.
the trick: the real pic is the background, the
content a transparent .gif. there is no way to
rightclick the background.



in Html:
Code:

<table CELLSPACING=0 CELLPADDING=0 COLS=1 WIDTH="100" HEIGHT="100">
<tr><td BACKGROUND="ihrbild.gif">
<img SRC="transparent.gif" height=100 width=100>
</td></tr></table>
 

Our Knowledge in the PHP Files:

Sourcecode "view_image.php":
Code:

<?php

session_start();

// deactivate cache
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT");
header("Pragma: no-cache");
header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");

// Challenge-ID
mt_srand((double)microtime()*1000000);

$random = mt_rand();
$random = md5(uniqid($random,TRUE));

$sess_challenge_id = $random;

if(!session_is_registered("sess_challenge_id")):
  session_register("sess_challenge_id");
endif;

// Read image
$pic    = "tolle-grafik.jpg";
$img    = @GetImageSize("/absoluter/pfad/zu/verzeichniss/images/".$pic);
$width  = $img[0];
$height = $img[1];

// show HTML table
printf("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%s\" height=\"%s\">\n",$width,$height);
print "<tr>\n";
printf("<td width=\"%s\" height=\"%s\" background=\"read_image.php?img=%s&challenge=%s\">",$width,$height,rawurlencode($pic),$sess_challenge_id);
printf("<img border=\"0\" src=\"blind.gif\" width=\"%s\" height=\"%s\">",$width,$height);
print "</td>\n";
print "</tr>\n";
print "</table>\n";

?>
 

Description:
You have to start a session first.
After this, we deaktivate the Cache because of
security reasons and build a 32 chars long "challenge-id"
these challenge ids can be also used to notice reload.
now just read the image size with GetImageSize()

Now the real trick:
Instead of pointing to the image
directly, we start another Script,
"read_image.php" and attach as Get-Parameter
the Name of the Image-File and our
Challenge-ID.


3. Reading the Image

We need another Script, for reading
the Image out of the secured dir.
The Sourcecode:

<?php

session_start();

// Challenge-ID OK -> Show Pic
if(session_is_registered("sess_challenge_id") and $sess_challenge_id == $challenge):

  session_unregister("sess_challenge_id");

  $path = "/asoluter/pfad/zu/verzeichniss/images/";
  $img  = rawurldecode($img);
  $read = @GetImageSize($path.$img);
  $type = $read[2];

  // Set kind of File

  switch($type)
    {
    case 1:
      $mime = "image/gif";
    break;
    case 2:
      $mime = "image/jpeg";
    break;
    case 3:
      $mime = "image/png";
    break;
    case 4:
      $mime = "application/x-shockwave-flash";
    break;
    }

  // Send Header and read the image with readfile()  
  // sending the graphic to the browser
  header("Content-Type: $mime");
  header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  header("Pragma: no-cache");
  header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
  readfile($path.$img);

// Access denied -> Transparent GIF *doh*
else:
  header("Content-type: image/gif");
  header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT");
  header("Pragma: no-cache");
  header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
  readfile("blind.gif");
endif;

?>
 
At first we test the Session-Value and compare it
with the challenge. if its ok, we delete the session
variable to prevent copy and paste out of the
page-source.
now getimagesize() again, to give the browser
the right header.
readfile() the image to the browser.

if there's no session-variable or the challenger-IDs
don't match, there will be only a transparent .gif.

Summary of security methods:

Directory secured with .htaccess
No Access with browser
Graphic as Table-Background
Transparent Gif
Session Variables and Challenge IDs

Offline Nossie

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • GothicWinter.Com
You know its hilarious....
« Reply #11 on: September 30, 2002, 06:23:53 PM »
to think that you could slow the php process right  down.. disabling this... disabling that...

and then someone comes along, takes a screendump and pastes it into photoshop...

why bother?
MOTD: LINUX IS LIKE A WIGWAM - NO WINDOWS, NO GATES, APACHE INSIDE !!!

Offline Chris

  • 4images Moderator
  • 4images Guru
  • *****
  • Posts: 4.487
  • Did u ever stop to think and then forget to start?
    • View Profile
It's encouraging
« Reply #12 on: September 30, 2002, 08:38:12 PM »
At least this thread is encouraging some thought and discussion on the topic.  My guess is the solution provided here would work for what has to be an overwhelming majority of web visitors.  You're right in that the user could still try to capture the screen.

Now if you *really* wanted to discourage screen shots, you could try using javascript's onblur event to trigger a history.back or window.close or image swap or something else for when the window loses focus.  Additional javascript code could detect when keys are hit and take the same possible set of actions.

Personally I use a watermark on all my images just to be extra safe.

Offline Nossie

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • GothicWinter.Com
Pic Security
« Reply #13 on: September 30, 2002, 08:54:03 PM »
heh sorry I didnt mean to be negative......

yeah it is good to come up with ideas etc

I just always think that crippling performace to improve security is something that microsoft would do  :lol: especially when it can be evaded by using print screen... of some other form of screen capture that doesnt use keypresses (or product keys)

ahh well...

I agree with you Chris... watermarks (no matter how ugly they might look) are probaly the best way to keep your files safe..
MOTD: LINUX IS LIKE A WIGWAM - NO WINDOWS, NO GATES, APACHE INSIDE !!!

Offline Chris

  • 4images Moderator
  • 4images Guru
  • *****
  • Posts: 4.487
  • Did u ever stop to think and then forget to start?
    • View Profile
Implementation help needed
« Reply #14 on: October 07, 2002, 04:51:45 AM »
Well I tried this code and on its own it works nicely.  I couldn't get it to work with the default 4images details.html template.

Even so, using the script on its own I was able to get the image by saving the HTML page using IE 6 File>Save As...