Savoir avec certitude quel domaine appelle une image hotlinkée ?

WRInaute accro
Savoir avec certitude quel domaine appelle une image hotlink

Bonjour à tous.

J'aimerais donner la possibilité à certains domaines (ou sous-domaines) d'afficher une image dynamique. Est-ce quelqu'un aurait une idée de la façon la plus simple de vérifier (en php) que le l'URL qui appelle cette image distante fait partie d'une liste de noms de domaines "identifiés" et autorisés.

Je voudrais éviter qu'un tiers puisse se faire passer pour un des domaines en question: l'image ne devrait donc pouvoir être affichée que sur les domaines précisément autorisés, voire même sur une "URL type".

Exemple: l'image peut s'afficher sur -http://www.example.com/tests/* ou sur -http://site2.com/log/check.html qui sont des urls autorisés (stockés en db), mais pas sur *.site3.net/* qui ne l'est pas.

Je ne sais pas si c'est très clair ? :)

D'avance merci !
 
WRInaute accro
Tu peux faire ça directement via le htaccess il me semble, en spécifiant de manière explicite les sites qui doivent pouvoir hotlinker tes images. J'ai un exemple de ça (mais pas sous la main là) que je peux te coller ici tantôt (je m'en sers pour permettre aux agrégateurs d'afficher les images dans les flux rss).

Edit : si ton image est dans un dossier à elle tu peux donc utiliser ce genre de choses : http://blogtoolbox.fr/empecher-le-hotlinking-dimages/
 
WRInaute occasionnel
Est-ce que la variable d'environnement $_SERVER['HTTP_REFERER'] ne suffit pas ?
Même si elle peut etre falsifiée, ça stoppera l'immense majorité des cas, non?

Tu fais
Code:
if (strpos($_SERVER['HTTP_REFERER'], 'tondomaine') === FALSE) {
 C'est bon, renvoie l'image
} else {
 Renvoie une image faisant de la pub pour ton site, ou pas d'image du tout.
}

Note les trois === parce que strpos peut renvoyer 0 si la chaine recherchée est trouvée dès le début de la chaine.
 
WRInaute accro
Merci pour ces premières pistes ;)

En fait les deux contraintes principales sont:

1. uniquement php: les domaines autorisés sont stockés en db (gestion des accès, voire des abonnements).

2. ne doit pas être falsifiable (ok, c'est toujours possible, mais disons que seul un gros félé doit pouvoir y arriver ;) ).


Je vais néanmoins voir dans quelle mesure on peut falsifier $_SERVER['HTTP_REFERER']: si ça se trouve, le niveau de sécurité sera suffisant.

Est-ce que, pour améliorer la sécurité du principe, il serait envisageable de récupérer l'ip du serveur qui héberge le site "demandeur" de l'image ?
 
WRInaute occasionnel
Ca a mon avis tu ne peux pas car c'est le client qui demande l'image, donc la demande vient de l'ip du client. Et le http_referrer n'est qu'une variable transmise avec la demande de l'image, c'est pour ca qu'elle peut etre falsifiée, mais franchement ca sera tellement minime que ca ne vaut pas le coup d'aller plus loin dans la recherche de solutions, a moins bien sur que ton public soit des geeks, dans ce cas le minime peut se transformer en presque moitié, surtout si des geeks publient sur leur blog la façon de contourner ta protection.
 
WRInaute impliqué
à voir du coté de javascript à ce moment là car google avec son api maps filtre parfaitement par domaine ...
 
WRInaute accro
julienr, comment ferais-tu, toi, dans ce cas, en JS par exemple (je n'y connais RIEN en js).

Voici la démarche, un peu plus clairement.

1. un client (un site web, autorisé) appelle un marqueur (ce sera plus simple de le nommer comme ça), incluant une variable (disons qu'il faut que je sache que $foo=bar dans sa demande.

2. je dois pouvoir récupérer l'info suivante:

- quel est le site demandeur ?
- quelle est la valeur de $foo

3. sur base de ces infos, je fais un petit tour dans ma db, et je renvoie:

- soit une image indiquant qu'il n'est pas autorisé
- soit une image dépendante de ce que je trouve dans la db pour $foo (si foo est positif j'envoie une image verte, si foo est négatif j'envoie une image rouge).


Peu importe quel IP client demande l'image, tant que c'est au sein d'une page d'un site autorisé.
 
WRInaute passionné
ne peux-tu pas passer par un script sur le site distant qui serve de passerelle?
Après tu peux contrôler a 100% l'origine car c'est le serveur de ce site.
 
WRInaute accro
Pas vraiment: je n'ai pas le contrôle du site distant.
C'est supposé par exemple être ton site à toi, si tu souhaitais faire appel à ce service. Je voudrais que tu n'aies qu'à coller un truc du genre dans ton code:

Code:
<img src="example.com/get/'.$foo.'.gif" />

ou une alternative JS à ce genre de méthode ;)
 
WRInaute discret
pas mieux que le referer en php et meme en htaccess c'est basé sur la verif du referer dans les exemples proposés. Si tu veux l'ip du referer http://fr.php.net/gethostbyname mais ça te changera pas grand chose. Sinon le mieux serait de faire des clés entre les serveurs du genre :

Ton client fait un truc du genre :
Code:
<img src="img.gif?"<?php echo md5('la clé que tu donnes a ton client'.$nomdelimage)?>"...

et toi de ton cotés :
Code:
$monclient = parse_url (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', PHP_URL_HOST);
/*comme certain navigateur ne passe pas de referer tu peux pas verifier a 100% */
if($monclient !== '')
{
$laclédemonclientdansmabasededonnées = SELECT CLE FROM CLIENT WHERE DOMAIN = $monclient;
if(md5($laclédemonclientdansmabasededonnées.nondelimagedemandée) !== querystring)
{
image non valide
}
}
imagevalide

Je sais pas trop si c'est compréhensible et le code n'est que la pour te donner une idée de ce que je veux dire mais la j'ai pas trop le temps :D. bon courage.
 
WRInaute impliqué
du coté du js rien d'infaillible non plus, je suis persuadé que le contrôle de domaine de l'api gmaps peux se casser aussi, mais vu l'ampleur du code js derrière c'est relativement facile de le planquer d'autant plus que leurs js sont factorisés et compactés...

sinon la façon de faire en js serait :

inclusion d'un script js sur le site de ton client qui pointe sur ton serveur avec en variable une clé unique pour le client

<script src="http://mondomaine.com/monjs.php?key=azerty"></script>

là vérif que azerty est déjà bien un client plus éventuellement contrôle de referer

ca renvoi du js qui va récupérer le nom de domaine du site, ainsi que la clé du client pour demander l'image sur ton serveur :

document.write( '<img src="http://mondomaine.com/monimage.php?key=azerty&domain=' + document.location + '" alt="" />' );

et du coup dans monimage.php tu peux faire un 2ème contrôle à partir du domain passé en paramètre

a+
 
WRInaute accro
Je vais commencer par creuser dans la proposition de petitchevalroux, parceque le JS et moi ça fait 12 ;)

Question subsidiaire: imaginons que j'aie envie d'utiliser ce "service" sans y être autorisé: comment pourrais-je cloaker le referer ? (je veux juste apprécier le niveau de difficulté de la chose: si c'est complexe, les gars capables d'abuser du service ont déjà en main leurs propres infos potentiellement plus intéressantes que la solution que je vais proposer*).

*désolé de la jouer mystère: j'en dirai plus bientôt, c'est promis ;)
 
WRInaute accro
HawkEye a dit:
imaginons que j'aie envie d'utiliser ce "service" sans y être autorisé: comment pourrais-je cloaker le referer ?
Le seul qui pourrait trafiquer le referrer est l'internaute qui visite le site hotlinker. Le site hotlinker lui-même ne sait pas t'envoyer un faux referrer.

La méthode de test du referrer est généralement efficace, parce qu'elle a pour effet que la plupart des internautes (pas tous) vont voir l'image "Accès interdit" quand ils afficheront la page du site hotlinker. C'est suffisant pour décourager les hotlinkers non autorisés qui n'ont généralement pas envie de devoir expliquer à une grande partie de leurs visiteurs qu'ils piquent des images ailleurs. :lol:

Jean-Luc
 
WRInaute accro
jeanluc a dit:
HawkEye a dit:
imaginons que j'aie envie d'utiliser ce "service" sans y être autorisé: comment pourrais-je cloaker le referer ?
Le seul qui pourrait trafiquer le referrer est l'internaute qui visite le site hotlinker. Le site hotlinker lui-même ne sait pas t'envoyer un faux referrer.

depuis quand on ne peut pas pas trafiquer le referer depuis un serveur déterminé a hotlinker (refere et tout le reste soit dit en passant) ?

Code:
	// obtenir l'image
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url_image);
	curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.8) Gecko/20050609 Firefox/1.0.4");
	curl_setopt($ch, CURLOPT_REFERER, "http://www.toto.fr/");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$media = curl_exec($ch);
	$info = curl_getinfo($ch);
	curl_close($ch);

si le code risque de donner trop d'idées a des petits TDC dites moi j'édite ou place aux modos ...

mais bon le TDC moyen qui va copier l'url de l'image ne va pas s'en sortir avec ça.
Pour la petite histoire, j'ai été confronté a ce problème avec un site d'images libre de droits (contre liens vers l'origine), qui permettait une copie depuis le navigateur mais qui bloquait autrement. sachant qu'il me falait une centaine de ses images, j'ai du chercher 5 mn pour automatiser.
 
WRInaute occasionnel
Oui la facon de contourner le probleme est de faire un wrapper, c'est a dire que le site pirate, ne va pas mettre l'url de ton image dans son image, il va mettre l'url de son script, qui lui va se charger de recuperer l'image avec un referrer qui fonctionne puis de la retourner.

Donc il faut deja qu'il connaisse un nom de domaine sur lequel ca marche, il faut qu'il developpe ce script wrapper, et donc il faut vraiment en avoir envie, c'est pour ca que je te disais c'est une très petite minorité qui vont le faire, sauf si ton public c'est des geeks et que l'un d'eux publie la façon de faire, avec les scripts tout fait et que l'information se propage bien.

Il faut que ton service en vaille la peine aussi!
 
WRInaute accro
zeb a dit:
depuis quand on ne peut pas pas trafiquer le referer depuis un serveur déterminé a hotlinker (refere et tout le reste soit dit en passant) ?
On ne peut pas, mais il y a de nombreux autres moyens pour pirater des images et tu en donnes un exemple.

Il faudrait que HawkEye en dise un plus sur son problème précis pour savoir ce qu'il veut exactement éviter, sinon on va proposer un marteau pour tuer une mouche. :wink:

Jean-Luc
 
WRInaute accro
Bon... ;)

En fait, je pense partager ma blacklist: je voudrais proposer à certains gestionnaires d'annuaires d'insérer dans leur formulaire d'édition une image qui affiche la réponse de ma blacklist à l'url qu'ils sont en train de traiter.

ie: http://test.indexweb.info/dstimg/check. ... heck=check

http://test.indexweb.info/dstimg/check. ... heck=check

http://test.indexweb.info/dstimg/check. ... heck=check

C'est un formulaire pour tester: le webmaster, lui, devra simplement hotlinker l'image dynamique -http://blacklist.indexweb.info/chk/$url

...et je voudrais essayer de m'assurer de son identité pour empêcher xyz d'utiliser le service, donc d'afficher les images suivantes:

http://blacklist.indexweb.info/chk/http ... r-mois.com
http://blacklist.indexweb.info/chk/http ... nkinfo.com
http://blacklist.indexweb.info/chk/http ... asseur.com

(qui sont visibles si tu spoof le referer en 'http://test.indexweb.info/')

;)
 
WRInaute impliqué
pas mal :)
le plus sécure c'est de protéger ton répertoire par un .htaccess, qui controle l'accès par login / mot de passe.
maintenant je ne sais pas et je vais tester, si tu places dans une page web une image dont l'url est une url protégé si ton navigateur va te demander le login et le mot de passe ou si rien ne va s'afficher à cause du forbiden renvoyé...

edit: ie et ff demande le login / mot de passe, donc ça peux être une solution, si j'ai bien compris, si c'est une fonctionnalité backoffice.
 
WRInaute impliqué
de rien :)

une autre méthode qui demande pas de config de .htpassword c'est le principe du webauth

tu proposes une interface ou ton partenaires se log avec son login mot de passe

si enregistres son ip si l'authent est ok

ainsi tu te constitues une liste d'ip authorisées qui peuvent accèder à ton service

çà évite du coup la popup à chaque nouvelle session ;-)
 
WRInaute discret
Est-ce que la méthode de blocage par .htaccess pourrait marcher avec d'autres types de fichiers? Moi par exemple, ça pourrait m'intéresser de bloquer certains sites qui repiqueraient mes vidéos :wink:

C'est correct ça?
Code:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?myspace\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blogspot\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?livejournal\.com/ [NC]
RewriteRule .*\.(flv)$ /images/nohotlink.jpe [L]

j'ai repris le code de http://altlab.com/htaccess_tutorial.html

Enfin, est-ce que c'est applicable à n'importe quel type de fichier: flv, pdf, mp3, etc.
 
WRInaute discret
Je crois que oui, je l'ai appliqué à un de mes sites pour les videos aussi
Code:
RewriteRule .*\.(jpeg|JPEG|mpeg|MPEG|mpg|MPG|mp3|MP3)$ - [F]
 
WRInaute occasionnel
Merci pour le code afin d'éviter le hotlinking.
Je viens de le mettre en place à l'instant et j'ai regardé les autres sites ayant affichés mes images le résultat est stupéfiant. Je suis très content. Merci.
J'ai rajouté en plus une variable pour que google image puisse quand même les lire :)
 
WRInaute discret
NetFly a dit:
C'est correct ça?
Code:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?myspace\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blogspot\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?livejournal\.com/ [NC]
RewriteRule .*\.(flv)$ /images/nohotlink.jpe [L]

Pour que ce soit que ton site autorisé
Code:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?mysite\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .*\.(flv|FLV)$ - [F]
ça devrait fonctionner :)
 
WRInaute accro
Re:

LiFi a dit:
Aucun rapport mais je vois que tu es co-auteur d'urlrewriting.fr, snippet s'écrit avec deux p.

On va corriger ce probleme en partie car ce mot fait maintenant partie du dico, c'est tout frais car mon dico familiale n'a pas ce mot en stock et il date de 2007. Le larrouse en ligne donne aujourd'hui une définition encore bien maigrichonne : "fragment - masculin"

En programmation nous ne parlons jamais de "fragment", nous parlerons de "partie", de "portion" voir de "block"

vu comment les langues sont compliqués, il est fort possible que "snipet" avec 1 seul p finisse par intégrer notre dico pour réellement spécifié qu'il s'agit ici d'informatique.

Autant on va corriger les mots "snipet" en "snippet" tout de suite, mais on va attendre que le dico étaye sa définition avant de toucher aux urls

Merci pour ton oeil de snipeur!
 
Discussions similaires
Haut