webForumDet fria alternativet

Säkerhet i uploadscript

29 svar · 1 550 visningar · startad av learn

learnMedlem sedan jan. 20051 143 inlägg
#1

Jag har ett upload-script i PHP. Det fungerar hur bra som helst, men hur är det med säkerheten egentligen..?? Filen laddas upp i en katalog, och endast den som har loggat in kan se den i listan. MEN, vet man eller kan gissa sig till filnamnet så kan man ju utan att logga in öppna filen genom att skriva in URL:en i webbläsaren..!

Har någon en bra lösning på detta problem? Alla förslag mottages med tacksamhet!

MeleaMedlem sedan juli 20032 667 inlägg
#2

Uhm, du kan ju lösa det så att när man är inloggad öppnar man filen genom att första hämta sökvägen i databasen.
Annars, för att folk inte ska kunna ladda hem filerna, är väl en lösning att lägga dem utanför rooten.

learnMedlem sedan jan. 20051 143 inlägg
#3

Hmm, ja filens namn och sökväg ligger lagrad i en databas men sökvägen till, låt säga bilden, syns ju antingen i webbläsarens adressrad ("www.sidan.se/filer/bild.gif") eller i källkoden ("...img src=filer/bild.gif...") när den är öppnad...

Ett alternativ kanske skulle vara att ändra sökvägen (filnamnet), både i databasen och själva filens namn, varje gång någon öppnar den... Känns dock lite omständigt.

Någon som har ngt tips??

The_HulkMedlem sedan juni 20031 937 inlägg
#4

du kan ju skicka filen till användaren via ett PHP-skript.
Du skickat med ett ID-nummer till PHP-skriptet som sedan skicka filen till användaren.
Tänk på att du inte ska göra någon "redirect" utan läsa in filen och sedan skicka innehållet till användaren. Ska du skicka t.ex. bilder måste du ändra i headern. Du bör spara filerna utanför rooten till webservern så man inte kan komma åt dem. Du kan även lägga in htaccess som block för en viss katalog men jag vet inte hur säkert det är.

Kommer inte ihåg vad man ska skriva men det vet säkert andra.

När någon försöker komma åt ditt PHP-skript kan du kontrollera om användaren är inloggad och har rättigheter att hämta just den filen.

Tänk dock på att det blir mer belastning för servern att göra så här än att ha filerna liggande så man kan nå de direkt på servern.

Det var lite ideer från mig.

learnMedlem sedan jan. 20051 143 inlägg
#5

The_Hulk, tack för tipsen! Det låter ju helt klart som en smidig lösning! Hur pass stor skillnad på belastningen talar vi om..?

Någon som kan hjälpa mig lite på traven när det gäller denna typ av PHP-script?? Oerhört tacksam för er hjälp!

hanzukunMedlem sedan nov. 20058 inlägg
#6

.htaccess

Jag skulle personlige rekommendera en .htaccess-fil. Då kan bilderna ligga i en underkatalog till scriptet och på så sätt få fin ordning på servern. Det borde väl räcka med

deny from all

i filen för att ingen ska kunna få tillgång till någon bild.

learnMedlem sedan jan. 20051 143 inlägg
#7

Jag vet inte mycket om .htaccess-filer, kan du ge mig ett konkret exempel, kanske bifoga denna fil.. Tack

learnMedlem sedan jan. 20051 143 inlägg
#8

Har fortfarande inte kommit någon vart med detta problem. Hur gör "de stora" vad gäller säkerhet i filuppladdning/nedladdning(så att endast de som har en viss behörighet kan komma åt)? Det The_Hulk skrev verkar ju smart, kan någon ge mig ett konkret exempel?

Tack på förhand!

sl0kMedlem sedan maj 2005523 inlägg
#9

finns flera sätt att göra det på

ex

<?php

header("Content-type: image/png");
if (checkUser()) {
  $bild  = $_GET['bild'];
  $file = "bilder/" . $bild . ".jpg";
}
else { $file = "ingenAccess.gif"; }
waterMark($file, "copy.gif", 60, 10, 5);

function waterMark($fileInHD, $wmFile, $transparency = 50, $marginX = 10, $marginY = 10) 
{
    $wmImg  = imageCreateFromGIF($wmFile);
    $jpegImg = imageCreateFromJPEG($fileInHD);
    $wmX = (bool)rand(0,0) ? $margin : (imageSX($jpegImg) - imageSX($wmImg)) - $marginX;
    $wmY = (bool)rand(0,0) ? $margin : (imageSY($jpegImg) - imageSY($wmImg)) - $marginY;
    imageCopyMerge($jpegImg, $wmImg, $wmX, $wmY, 0, 0, imageSX($wmImg), imageSY($wmImg), $transparency);
    imagePNG($jpegImg);
} 
?>

exemplet lägger även på en vattenstämpel .. där du ex kan ha sitens namn lr dyl..
om användaren inte har access visas filen ingenAccess.gif istället ..

learnMedlem sedan jan. 20051 143 inlägg
#10

Ok tack!

1. "Vattenstämpeln" är inget som ska vara med.

2. Funkar detta även för andra filtyper (tex .doc, .pdf, .xls)?

3. Om nu någon lyckas lista ut vilken mapp som filerna ligger i så är det ju bara att testa sig fram till filnamnet, tex "www.sidan.se/mapp/filnamn.pdf". Eller kan man låsa detta på ngt sätt, så det bara går att nå filerna via scriptet?

4. Jag förstår att det tar längre tid att ladda (tex en bild) med denna metod, men är det märkbart?

Vilket tillvägagångssätt rekomenderar ni för detta ändamål till ett större community med relativt många användare samtidigt? Vanligaste filtyperna kommer förmodligen vara jpg och doc.

sl0kMedlem sedan maj 2005523 inlägg
#11

2. ja .. du får ändra headern till korrekt för det bara så.. kan även va bra att ex då använda header('Content-Disposition: attachment; filename="downloaded.pdf"')
http://se.php.net/manual/sv/function.header.php

3. mappen kan ligga utanför wwwrooten..

learnMedlem sedan jan. 20051 143 inlägg
#12

sl0k skrev:

3. mappen kan ligga utanför wwwrooten..

Vad menar du med "utanför". Filen kan väl nås ändå, "www.sidan.se/mapp/mapp/filen.doc", eller kanske man låsa detta...Hur?

sl0kMedlem sedan maj 2005523 inlägg
#13

fast det där är inte utanför wwwrooten ..
det jag menade var att du ex kanske har en mapp som heter ex /home/dindomän.se/www/ .. går du in på http://www.dindomän.se/ så kommer du till den mappen ..
de bilder som du vill skydda kan du då ha i en mapp utanför , ex /home/dindomän.se/minaskyddadebilder/ .. php skriptet kan fortfarande läsa in bilderna men det går inte i direkt genom webbläsaren komma åt filerna.

learnMedlem sedan jan. 20051 143 inlägg
#14

Aha, ok. Ska kika på det. Tack!

learnMedlem sedan jan. 20051 143 inlägg
#15

sl0k skrev:

fast det där är inte utanför wwwrooten ..
det jag menade var att du ex kanske har en mapp som heter ex /home/dindomän.se/www/ .. går du in på http://www.dindomän.se/ så kommer du till den mappen ..
de bilder som du vill skydda kan du då ha i en mapp utanför , ex /home/dindomän.se/minaskyddadebilder/ .. php skriptet kan fortfarande läsa in bilderna men det går inte i direkt genom webbläsaren komma åt filerna.

OK, men hur når man bilderna genom php-scriptet då? Om det går så borde det ju också gå via webbläsaren...Eller?? Hur funkar det?

henkeMedlem sedan dec. 1999271 inlägg
#16

Du kan skicka filen via ett php-script. Här är ett exempel på hur du skickar en jpeg-bild:

<?php
	header("Content-type: image/jpeg");
	$file = fopen("path/filename");
	fpassthru($file);
	fclose($file);
?>

Om ovanstående script heter image.php skriver du image.php i webläsaren och då kommer bilden att visas i webläsaren.

sl0kMedlem sedan maj 2005523 inlägg
#17

learn skrev:

OK, men hur når man bilderna genom php-scriptet då? Om det går så borde det ju också gå via webbläsaren...Eller?? Hur funkar det?

php har tillåtelse att läsa filer utanför wwwrooten..
säg att din wwwroot/documentroot är ex /home/learn/public_html/
går folk in på din sida ex https://www.dinsida.se/ så kommer de till din documentroot, de har där ingen möjlighet att gå högre upp i ditt filträd.
dock kan du med ett php skript läsa filer som ligger högre upp m.m

RyzzenMedlem sedan mars 2000279 inlägg
#18

Själv har jag löst problemet genom att när en fil laddas upp så kör jag md5 med ett slumpat unikt id och spara den uppladddade filen med det namnet. Det är i stort sett omöjligt att luska ut vad filerna heter. Sen kör jag ett PHP script som anropas och sänder filen till användaren.

learnMedlem sedan jan. 20051 143 inlägg
#19

Okej, jag börjar hajja hur man kan göra. Hittade följande på php.net:

// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');

Här öppnas ju en PDF va jag förstår. Men låt säga att jag inte vet vilken typ av fil som användaren vill visa. Det kan vara en bild av olika typer (jpg, jpeg, gif, png) och det kan vara ett dokument av olika typer (pdf, txt, doc, xls). Hur ska jag på ett snyggt sätt tillverka en funktion/skript som utifrån "anropet" tar reda på vilken typ av fil det är och sedan öppnar/visar den.

Någon som vill hjälpa mig? Vore oerhört tacksam!!! :bire :bire :)

sl0kMedlem sedan maj 2005523 inlägg
#20

du får bestämma filtyp utefter filändelsen och lita på att det stämmer.

preg_match("|.*\.([\w]*)$|", $filename, $match);
$content="";
switch ($match[1]) {
  case 'jpeg':
  case 'jpg':
  $content = "image/jpeg";
  break;

  case 'png':
  $content = "image/png";
  break;

  // osv osv... 

  default:
  $content = "text/plain";
  break;

}

header("Content-type: $content");

**/red #1 efter lite eftersökning hittade jag en annan lösning , har testat o verkar fungera.

/red #2 visade sig att system file osv tryckte ut ett svar.. skrev om funktionen lite, fångade upp utskriften och rensade den..
Obs .. denna lösning intefererar troligen med tidigare ob_ buffers.. har inte testat så**

$content = getMimeType($filename);
header ("Content-type: $content");

function getMimeType($filename) {
  ob_start();
  if (function_exists("mime_content_type"))
    $return = mime_content_type($filename);
  else
    $return = system ( trim( 'file -bi ' . escapeshellarg($filename)));
  ob_end_clean();
  return $return;
}
Genererad på 389 ms · cache AV · v20260730165559-full.f96bc7eb