webForumDet fria alternativet

stor säkerhetsfråga!

PHP

7 svar · 675 visningar · startad av egxezex

Medlem sedan jan. 200786 inlägg
Frågan#1

Tänkte fråga angående säkerhet på vissa delar av vårat system vi precis byggt.

Vi har funktioner som möjliggör att igenom ett administrationsgränssnitt skapa konton, ta bort konton, lägga till filer i okila kategorier med kommentarer till specifika konton, lägga upp nyhetsbrev till alla kunder och mycket mer.

Kontona som skapas, skapas med användarnamn och lösenord, med den informationen kan man logga in på sin konto sida. Vi undrar hur stor chansen är för 2 konton att se varrandras filer.

Detta är en del av konto sidan

//#####################################################
//Hämtar filnamnet som valdes vid inläggning av filen##
//#####################################################

	if ($_GET['Kategori'] == "Marketing"){
			
		$kat = 'marketing';
	}
	if ($_GET['Kategori'] == "Purchase"){
		
		$kat = 'purchase';
	}
	if ($_GET['Kategori'] == "Development"){
			
		$kat = 'development';
	}
	if ($_GET['Kategori'] == "Newsletter"){
		
		$kat = 'newsletter';
	}

	if ($_GET['Kategori']){	
		echo "<table align=\"center\">\n"; 
		echo "<td class=\"text3\"><strong>Files</strong></td>"; 
		echo "<td class=\"text3\"><strong>Comments</strong></td>";
		echo "<td class=\"text3\"><strong>Date</strong></td>"; 
		echo "</tr>"; 

		
	

$query2 = "SELECT id, Filename, Kommentar, Kategori, Date FROM $file_table WHERE RefID = 'all' && Kategori = '$kat' || RefID = '$refID' && Kategori = '$kat' ORDER BY 'Date' DESC, 'id' DESC";
$result2 = mysql_query($query2) or die('Query failed: ' . mysql_error());

while($resultRow = mysql_fetch_array($result2, MYSQL_ASSOC)) {
// För lite extra säkerhet så kollar vi att filen finns i verkligheten också
if(file_exists($uploadFolder."/".$resultRow['fileName']))
?>
<tr> 

<td class="text"><img src="setts/img/folder.gif" width="10" hight="10"> <a target="blank" href="<?php echo "download/$kat/".$resultRow['Filename']."" ?>  "> <?php echo $resultRow[Filename]?></a></td> 
<td class="text"><?php echo $resultRow[Kommentar]?></td> 
<td class="text"><?php echo $resultRow[Date]?></td>
</tr> 

<?
}
echo "<a href=\"konto.php?RefID='$refID'\">Home</a>\n"; 
}
ob_end_flush();
?>
</body>
</html>

Detta är delar utav filuppladdningen till specifik konto. naturligtvis finns det mer kod i denna funktion, där kollar vi filnamn,storlek,typ och mycket mer.

f (isset($_POST['komment'])) {
		if ($_POST['kategori'] && $line[user] != NEWSLETTER){
		
		$query3 = "INSERT INTO UserFiles (filename, RefID, Kommentar, Date) VALUES ('$thefile','$RefID','$komment3', $date)";
		mysql_query($query3) or die('Query failed query3: ' . mysql_error());
			
			$selected_radio = $_POST['kategori'];
			
				if($selected_radio == 'marketing'){
	
				if (is_uploaded_file($_FILES['uplfile']['tmp_name']) && move_uploaded_file($_FILES['uplfile']['tmp_name'],$upload_dir_mark.$thefile)) {
				
					echo"<br><strong><p class=\"warning\">Success!</strong><p>";
					echo "<br>Filen <strong>$thefile</strong> har nu laddats upp till användaren <strong>$line[user]</strong> <br> med kommentaren: <strong>$komment3 </strong>";

				}
				$query5 = "UPDATE UserFiles SET Kategori='marketing' WHERE Filename = '$thefile' ";
				mysql_query($query5) or die('Query failed query5: ' . mysql_error());
			}	
	
			
			if($selected_radio == 'purchase'){
	
				if (is_uploaded_file($_FILES['uplfile']['tmp_name']) && move_uploaded_file($_FILES['uplfile']['tmp_name'],$upload_dir_purc.$thefile)) {
				echo"<br><strong><p class=\"warning\">Success!</strong><p>";
					echo "<br>Filen <strong>$thefile</strong> har nu laddats upp till användaren <strong>$line[user]</strong> <br> med kommentaren: <strong>$komment3 </strong>";
				}
				$query5 = "UPDATE UserFiles SET Kategori='purchase' WHERE Filename = '$thefile' ";
				mysql_query($query5) or die('Query failed query5: ' . mysql_error());
			}	
	
			if($selected_radio == 'development'){
	
				if (is_uploaded_file($_FILES['uplfile']['tmp_name']) && move_uploaded_file($_FILES['uplfile']['tmp_name'],$upload_dir_deve.$thefile)) {
				echo"<br><strong><p class=\"warning\">Success!</strong><p>";
					echo "<br>Filen <strong>$thefile</strong> har nu laddats upp till användaren <strong>$line[user]</strong> <br> med kommentaren: <strong>$komment3 </strong>";
				}
				$query6 = "UPDATE UserFiles SET Kategori='development' WHERE Filename = '$thefile' ";
				mysql_query($query6) or die('Query failed query6: ' . mysql_error());
			}	
			
			

			}	
			

		if ($_POST['submit'] && $line[user] == NEWSLETTER){
					
				$query3 = "INSERT INTO UserFiles (filename, RefID, Kommentar, Date) VALUES ('$thefile','$RefID','$komment3', $date)";
				mysql_query($query3) or die('Query failed query3: ' . mysql_error());
						
								
						
				if (is_uploaded_file($_FILES['uplfile']['tmp_name']) && move_uploaded_file($_FILES['uplfile']['tmp_name'],$upload_dir_news.$thefile)) {
					echo"<br><strong><p class=\"warning\">Success!</strong><p>";
					echo "<br>Filen <strong>$thefile</strong> har nu laddats upp till  <strong>alla</strong> <br> med kommentaren: <strong>$komment3 </strong>";
					}
					$query7 = "UPDATE UserFiles SET Kategori='newsletter' WHERE Filename = '$thefile' ";
					mysql_query($query7) or die('Query failed query7: ' . mysql_error());
			
 					$query8 = "UPDATE UserFiles SET RefID='all' WHERE Filename = '$thefile' ";
 					mysql_query($query8) or die('Query failed query8: ' . mysql_error());
						
				}

		}
	if (!$_POST['kategori'] && $line[user] != NEWSLETTER){
		echo"<br><br><strong><p class=\"warning\">Du har inte valt någon kategori. Filen laddades INTE upp!</strong><p>";
	}
	} 

  ?>

Användarna läggs in genom att skriva in användarnamn, lösenord,lösenord,kontonamn. Alla dessa fält testas så att t ex innehåller rätt längd på lösenord, repetera lösenord mm. kontrollerar även case-sensetivity, magicqoates samt så används md5 vid lösenord inlägg. addslashes används också samt så sätts alla skapade användare som users i databasen medans admin har en annan benämning.

När en fil skickas till en specifik användare läggs filnamnet in i databasen, datum, kategori samt ett referens id som klargör till vilken användare den tillhör. När filer hämtas gämnförs det id't som finns under RefID i tablen UserFiles med kontona i tablen members där ID står. Innan uppladdning utav filerna väljs naturligtvis till vilken användare man ska ladda upp till, användarna hämtas ifrån members tablen.

Alla filer som laddas upp hamnar i /download/valdkategori, så alla kontofilerna ligger blandade med varrandra, men vad som visas för varje konto vid inlogging sker genom kontroll utav filnamn, refid(kontot) mm så att rätt filer ska visas.

Hur stor är sannolikehten att de inloggade på något sätt får tag på andras filer genom vårt system? Kanske s är informationen jag gett er inte är tillräcklig för att få en uppfattning.

Medlem sedan jan. 200786 inlägg
#2

Vill också tillägga att när man loggar in, skapas en session. I sessionen finns ID't på den den som loggar in, rätt id't är hämtat ifrån databasen när vi jämnför användarnamn och lösenord . Det är på det sättet vi tar reda på vilka filer som den inloggade har tillåtelse till eftersom vid inläggning utav filer, läggs också ID't på kontot in i samma table, samt filnamnet. Sen jämnför vi ID i members tablen mot refID i fil tablen och skapar sökvägen till filen med hjälp utav filnamnet i databasen.

Väl inloggad har man ingen databas kontakt mer än "Select", så varken delete, insert, update mm finns placerad i filerna de inloggade får tillgång till. Det är bara administrationsfilerna som har detta. På så sätt hoppas vi ha tagit bort en del av säkerhetsriskerna.

Jag hoppas ni orkar läsa allt detta :)

Medlem sedan dec. 19996 721 inlägg
#3

Visst finns det säkerhet, på så vis att filerna inte kommer att listas för obehöriga, men de är ju ändå fullständigt tillgängliga, eftersom de ligger i publika mappar. Lägg dem hellre utanför webbroten, eller i undermappar med slumpnamn (som du lagrar i UserFiles, tillsammans med filen).

Sedan var det väldigt mycket kodduplicering i den kod du visade. Samla ihop till ett par funktioner, så blir det mer överskådligt.

Medlem sedan aug. 2004903 inlägg
#4

ok. Tack för att du orkade läsa :) Vi har bara arbetat imot vår egen server än så länge men ska snart flytta allting till webhotell. jag tror att den lättaste löstningen hade varit att lägga mapparna utanför webbroten, om webhotellet tillåter det (ska inspekteras). Vi har säkerhet som prio 1 i detta system, så jag uppskattar dina synpunkter :) Angående funktioner så har det funnits, men efter alla ändrar vi gjort verkade det lättast att ha det så här medas vi konstruerar.. men att ha funktioner eller inte ha det påverkar väl inte säkerhet i övrigt.

Angående sql injections: Vi använder Magiq Quates, addslashes samt md5 och case-sensetivity (vet inte om det skyddar riktigt mot det), är detta fullt tällräckligt? Med tanke på att inga användare har sidor som använder delete, insert eller liknande utan bara select så borde databassabotage vara lite svårare, har jag rätt?

p.s jag och han som postade inlägget arbetar ihop. bara så att ni inte blir förvirrade eftersom jag svarar :)

Medlem sedan dec. 19996 721 inlägg
#5

Tulork skrev:

Vi har säkerhet som prio 1 i detta system

I så fall ska ni definitivt placera filerna utanför webbroten, och servera dem genom någon form av "download.php?fileid=234sdfj2357fdjk", som verifierar användarens rättigheter.

Tulork skrev:

men att ha funktioner eller inte ha det påverkar väl inte säkerhet i övrigt.

Nej, men det är enklare undvika säkerhetsluckor om man kodar med struktur.

Tulork skrev:

Angående sql injections: Vi använder Magiq Quates, addslashes samt md5 och case-sensetivity (vet inte om det skyddar riktigt mot det), är detta fullt tällräckligt?

Det är en god bit på väg, men om ni ändå håller på så rekommenderar jag parametriserade frågor i stället. Det är så säkert det kan bli och dessutom roligare. :)

http://php.net/manual/en/function.mysqli-stmt-bind-param.php

Tulork skrev:

Med tanke på att inga användare har sidor som använder delete, insert eller liknande utan bara select så borde databassabotage vara lite svårare, har jag rätt?

Japp, det blir svårare, men i princip så är SQL Injections inte begränsade av detta, eftersom många implementeringar tillåter multipla SQL-frågor. En SQL-injection kan få en enkel SELECT-fråga att bli en SELECT och en DELETE. MySQL-funktionerna i PHP tillåter inte detta, men det är ändå en god vana att skydda sig mot detta. Ett vanligare problem är att en injection får en SELECT att returnera mer eller andra saker än det önskade.

Medlem sedan aug. 2004903 inlägg
#6

hmm, hur länkar man igentligen till en fil som finns utanför webroten? alltså hur ska utomstående få tillgång till att ladda hem en fil när dem inte kan komma längre än till webroten?

lätt exempel: i weboreten ligger mappen "Hej" i denna mappen ligger en .html fil och i den filen finns en länk till filen "bil.gif" som ligger i mappen innan webroten.

<a href="../../bil.gif">bilen</a> går ju inte längre tillbaka än webroten.

EDIT: Inser att det inte går.. så jag är smått förbryllad på hur i h**e jag ska skydda filer mot att folk bara skriver http://adress/mapp/fil.fil

Medlem sedan dec. 19996 721 inlägg
#7

Du gör det genom att göra en php-fil som läser filen och skickar ut innehållet till klienten.

http://se.php.net/readfile

Medlem sedan aug. 2004903 inlägg
#8

men går det att skicka en fil till den mappen utanför? För vi har ju uppladdning till specifikt konto också. Sen förstår jag inte riktigt hur den där funktionen fungerar :(

Funkar det inte att ha htaccess på dem mapparna med filer? och i så fall, påverkar detta nedladdningen av filer genom vårt script?

269 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2
128 ms — deklarationer (db)
0 ms — hämta statistik (cache)
138 ms — hämta tråd, inlägg och bilagor (db)
117 ms — ändringar (db)