PHP Code "Register Globals=off" tauglich machen?

neutron

New Member
Hi,

Ich verzweifel bald. Zugegeben, ich bin ein PHP Depp, kleinere Sachen bekomme ich hin, aber hier hörts leider schon auf. Ich will eine Webseite zu mir auf den Server umziehen, diese ist selbstgebaut und nutzt eine mysql Datenbank, der php Code dazu um die Datenbank abzufragen bzw. in diese zu schreiben ist von 2001 und besteht auf "Register Globals=on" aufgrund der Variablen. Nun wollte ich das ganze eben tauglich machen wie im Betreff geschrieben, bekomms aber nicht hin. wir reden hier von vielleicht 10-15 Zeilen Code, für einen erfahrenen PHP Programmierer also 5 Minuten Arbeit. Könnte mir da wer Hilfestellung leisten?

PHP:
<? include "class.Database_MySQL.php";				// öffnet die datenbank

$myDB = new Database;

if ($function == "post") {
	// wir kommen von der formular seite und wollen änderungen speichern

	if ($id > 0) {
		// wir wollen eine änderung zu einem vorhandenen datensatz speichern
		$sql = "UPDATE aktuelles SET 
					datum = '$datum',
					titel = '$titel',
					quelle = '$quelle',
					text = '$text',
					anzeigen = '$anzeigen' 
		   		WHERE id=$id";
		$myDB->query($sql);
	} else {
		// wir wollen einen neuen datensatz anlegen
		$sql = "SELECT MAX(id)+1 as neue_id FROM aktuelles";
		$myDB->query($sql);
		$myDB->fetchRow();
		$id = $myDB->getField("neue_id"); 

		$sql = "INSERT INTO aktuelles (id,datum, titel, quelle, text, anzeigen) 
						  VALUES ('$id','$datum', '$titel', '$quelle', '$text', '$anzeigen')";
		$myDB->query($sql);
	}
}

$sql = "SELECT * FROM aktuelles WHERE id=$id";
$myDB->query($sql);
$myDB->fetchRow();

?>

Und hier noch die Include Datei falls gebraucht:

PHP:
<?
/******************************************************************************
** FILENAME:		class.Database_MySQL.php
**
** DESCRIPTION:		class for transparent database access to a mysql database
**
** CREATED:			2001-01-23
**
******************************************************************************/

/* 	
	// EXAMPLE OF CLASS USAGE:
	
	$myDB = new Database();									// instantiate a Database object
	
	$sql = "SELECT * FROM tablename";
	$myDB->query($sql);										// execute SQL statement
	
	echo "Showing results 1-".$myDB->getNumRows()."<br>";	// display number of rows retrieved by query
	echo "of following query: ".$myDB->getSql()."<br>";		// display performed query
	
	while ($myDB->fetchRow()) {								// loop through all result rows
		echo $myDB->getField("fieldname")."<br>";			// echo value of fieldname for current result row
	}
*/


		define ("DATABASE_SERVER", 		"localhost");	// mysql server url
		define ("DATABASE_USER", 		"xxxx");	// mysql server username
		define ("DATABASE_PASSWORD", 	"xxxx");	// mysql server password
		define ("DATABASE_NAME",		"xxxx");	// database to be selected

	class Database {

		// class attribute definitions
		var $dbHandle;		// database connection handle
		var $sql;			// last performed query
		var $result;		// result identifier of a successful query
		var $row;			// contains a hash with the current result row

		// class constructor
		function Database() {
			/*=============================================================================
			 * DESCRIPTION:		initializes a persistent database connection when a new database 
			 *					object is created (if there already is an existing DB connection,
			 *					it will be reused rather than creating a new one)
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * 
			 * RETURN VALUE:	None
			 * 
			 * PREREQUISITES:	None
			 *
			 * SIDE EFFECTS:	$this->dbHandle is set
			 * 
			 *============================================================================*/
			
			$this->dbHandle = mysql_pconnect ( DATABASE_SERVER,
											   DATABASE_USER,
											   DATABASE_PASSWORD)
							  or die ("<p align=center><font color=#FF0000>Unable to connect to SQL server</font></p>");
			
			mysql_select_db (DATABASE_NAME)
				or die("<p align=center><font color=#FF0000>Unable to select database</font></p>");
		} // end method Database


		function query ($sql) {
			/*=============================================================================
			 * DESCRIPTION:		excutes the SQL query stored in $this->sql and stores the result
			 *					identifier in $this->result
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * $sql					string			contains query to be performed
			 * 
			 * RETURN VALUE:	true / false (query success / failure)
			 * 
			 * PREREQUISITES:	open database connection
			 *
			 * SIDE EFFECTS:	$this->result is set
			 * 
			 *============================================================================*/
			
			$this->sql = $sql;
			
			$this->result = mysql_query ($sql, $this->dbHandle);
			
			if (mysql_errno($this->dbHandle)) {
				// query was not successful, start error handling
				
				echo "<p align=center><font color=#ff0000>Error " . mysql_errno($this->dbHandle) . ": " .mysql_error($this->dbHandle) . "<br>";
				echo $sql."</font></p>";
				
				//mail ("xxxx@xxx","sql fehler ".mysql_errno($this->db_handle), mysql_error($this->db_handle)."\n\n".$this->sql);
				
				return false;
			} else {
				return true;
			}
		} // end method query


		function fetchRow () {
			/*=============================================================================
			 * DESCRIPTION:		fetches a row from a valid mysql result and stores it as a
			 *					hash in $this->row
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * 
			 * RETURN VALUE:	true / false (success / failure) - one reason for failing would 
			 *					be that there are no further rows to be fetched from the result
			 * 
			 * PREREQUISITES:	$this->result must contain a valid mysql result identifier
			 *
			 * SIDE EFFECTS:	$this->row is set
			 * 
			 *============================================================================*/
			
			$this->row = mysql_fetch_array ($this->result);
			
			if ($this->row) {
				return true;
			} else {
				return false;
			}
		} // end method fetchRow


		function getField ($fieldName) {
			/*=============================================================================
			 * DESCRIPTION:		fetches a field value from the current $this->row and returns it
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * $fieldName			string			name of key in $this->row hash for which the
			 *										corresponding value should be retrieved
			 * 
			 * RETURN VALUE:	true / false (success / failure) - one reason for failing would 
			 *					be that there are no further rows to be fetched from the result
			 * 
			 * PREREQUISITES:	$this->row must contain a valid result row
			 *
			 * SIDE EFFECTS:	None
			 * 
			 *============================================================================*/
			
			return $this->row[$fieldName];
		} // end method getField


		function getNumRows () {
			/*=============================================================================
			 * DESCRIPTION:		determines the number of result rows yielded by the last query
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * 
			 * RETURN VALUE:	number of result rows yielded by the last query
			 * 
			 * PREREQUISITES:	$this->result must contain a valid mysql result identifier
			 *
			 * SIDE EFFECTS:	None
			 * 
			 *============================================================================*/
			
			return mysql_num_rows ($this->result);
		} // end method getNumRows

		function getSql () {
			/*=============================================================================
			 * DESCRIPTION:		returns the last Query performed
			 * 
			 * PARAMETERS:
			 * NAME					TYPE			DESCRIPTION
			 * 
			 * RETURN VALUE:	string containing the last query statement
			 * 
			 * PREREQUISITES:	None
			 *
			 * SIDE EFFECTS:	None
			 * 
			 *============================================================================*/
			
			return $this->sql;
		} // end method getSql

	} // end class
?>
 
Hallo,

wozu raten, wenn's im Formular eindeutig drinsteht?

Code:
if (isset($_REQUEST['xx'])) { $xx=$_REQUEST['xx']; } else { $xx=''; }
statt xx die Variablen einsetzen, für jede Variable eine solche Zeile und ganz oben reinpacken zwischen "<?" und "include".
 
Dies steht noch oben in der index.php drin, von wo aus auch die einzelnen scripte aufgerufen werden:

PHP:
<? include "class.Database_MySQL.php";                          // öffnet die datenbank

$myDB = new Database;

if ($id > 0) {
        // wir wollen den datensatz mit der id $id löschen, wenn $id angegeben wurde
        $sql = "DELETE FROM aktuelles WHERE id=$id";
        $myDB->query($sql);
}

// abfrage aller datensätze (zeilen) in der tabelle "aktuelles"
$sql = "SELECT * FROM aktuelles";
$myDB->query($sql);

//echo 'Übergebene ID: $id';


?>

@charli, da werd ich leider nicht schlau draus, was du schreibst, wie gesagt PHP depp.
 
Code:
<? 
if (isset($_REQUEST['function'])) { $function=$_REQUEST['function']; } else { $function=''; }
if (isset($_REQUEST['datum'])) { $datum=$_REQUEST['datum']; } else { $datum=''; }
if (isset($_REQUEST['titel'])) { $titel=$_REQUEST['titel']; } else { $titel=''; }
if (isset($_REQUEST['quelle'])) { $quelle=$_REQUEST['quelle']; } else { $quelle=''; }
if (isset($_REQUEST['text'])) { $text=$_REQUEST['text']; } else { $text=''; }
if (isset($_REQUEST['anzeigen'])) { $anzeigen=$_REQUEST['anzeigen']; } else { $anzeigen=''; }
if (isset($_REQUEST['id'])) { $id=$_REQUEST['id']; } else { $id=''; }

include "class.Database_MySQL.php";
ersetzt die erste Zeile in Deinem Script, Rest bleibt gleich.
 
Hatte es in der Zwischenzeit genau so eben mal probiert und klappt natürlich, bin doch nich so doof wie's scheint, aber natürlich danke dafür, ich ersetze nun quasi einfach nur die entsprechenden cvar's durch korrekt die unter register globals=off laufen wenn ich das mal laienhaft ausdrücken würde, richtig ? Hab das auch so überall entsprechend geändert, funzt 1a. Wieder was gelernt.
 
Wobei ich mir ehrlich gesagt keine Gedanken darüber machen würde diese Dateien umzusetzen.
Vielmehr solltest du mal jemanden daran lassen der das ganze neu macht, ich denke nur an so Sachen wie SQL-Injection usw...
 
Du meinst weil nun alles per $_REQUEST läuft? Mir ist bewusst das es mit $_GET und/oder $_POST besser wäre, oder redest du von "noch mehr" Problemen in diesem Code ?
 
Hallo,

nö, er meint was schlimmeres: vor 7 Jahren wurden Lücken in schlechtem PHP-Code kaum ausgenutzt, entsprechend unsauber wurde programmiert, und das Wissen über Angriffspunkte in PHP-Code hat sich in den letzten 7 Jahren auch massiv vergrößert. So alter Code ist nur noch zum Füllen von /dev/null geeignet. :D
 
Nun dann müsste ich die gesamte Webseite neu schreiben (lassen) und das ist kaum der Aufwand wert. Aber ich glaub auch nicht das die Seite so ein Massenpublikum hat das da wer unbedingt dran rumhacken wird, zumal die Skripte hier die zum schreiben, ändern der Datenbank sind nochmal hinter eine Passwortabfrage kommen.
 
...zumal die Skripte hier die zum schreiben, ändern der Datenbank sind nochmal hinter eine Passwortabfrage kommen.

War es nicht so, dass die meisten Angriffe von innen kommen?!?

Naja egal, wie charlie schon sagte, es entspricht halt nicht dem "aktuellen Standard". Die Folgen für dich bzw. deine Anwendung (oder auch andere Anwendungen die auf dem MySQL-Server laufen) falls doch jemand eine Lücke ausnutzt, musst du schon selbst einschätzen können...
 
Es ist eigentlich auch nicht schwer, diese Variablen zu überprüfen. Dazu braucht man eigentlich nur zwei oder drei Funktionen, und ein paar gut erstellte RegEx.
 
Dafür kann ich zu wenig PHP. Und ja sicherlich sagt man das die meisten Angriffe von innen kommen. Ich weiß die Sicherheitsbedenken hier auch durchaus zu schätzen, aber es hat außer mir keiner Zugriff sonst auf den Server, zumindest nicht mit genügend Rechten.
 
Na wie schon gesagt, generell sollte es so sicher wie möglich sein. Was du daraus machst, ist aber deine Sache. Sollte dich das mit den regulären Ausdrücken weiter interessieren, meld dich einfach nochmal. die einfachen Dinge sind garnicht so schwer, wenn man sich da reindenken will.

Ausserdem kann man mit relativ einfachen Mitteln auch SQL-Anweisungen so schreiben, dass SQL-Injections schwieriger werden.
 
Du, ich nehme das Angebot gerne an mit dem RegEx und/oder sicherer SQL-Anweisungen zu schreiben. Ich hab PHP nie gelernt, bin aber technisch denke ich genug bewandert und mich in sowas reindenken zu können. Ich denk nur manchmal das ist bestimmt schwer, obwohl es dann genau so funktioniert wie ich mir das gedacht habe, von daher vielleicht immer die Zurückhaltung bei sowas :)
 
Wenn ich mir die Skripte hier anschaue, sollte man auch dringend mal über SQL Injection nachdenken. Grade wenn man Input-Parameter direkt in eine SQL-Anweisung reinpackt, kann man allerlei Unsinn treiben.
 
Was für Reguläre Ausdrücke interessant sein dürfte ist auf jeden Fall mal das hier:
Regulärer Ausdruck - Wikipedia
Sollte zumindest mal eine gute Grundlage bieten. Die Funktionen die dir in PHP dazu zur Verfügung stehen sind beispielsweise
Code:
preg_match()
preg_split()
preg_replace()
Wobei hier nur preg_match dazu da ist, um Variablen zu überprüfen. Die anderen beiden Funktionen dienen dazu eine Variable zu teilen oder bestimmte Dinge auszutauschen.

Gehen wir mal davon aus, dass eine Variable ein Datum enthalten soll. Dieses Datum soll so aussehen:

tt.mm.jjjj

Jetzt kann man einen regulären Ausdruck schreiben, der nur diese Form des Datums zulassen wuerde:
Code:
//zu testender String
$datum = '21.11.2007';

//Testargument
$test = '^([0-9]{2}\.){2}([0-9]{4})$';

//Ueberpruefung
if(preg_match("/$test/", $datum)
{
    echo 'Das Datum ist richtig';
}
else
{
    echo 'Das Datum ist falsch';
}

Was passiert hier?
Als erstes setzen wir eine Variable die wir überprüfen möchten. Das ist
Code:
$datum = '21.11.2007';
Als nächstes setzten wir eine Variable, die das Schema des zu überprüfenden Strings enthält. Wenn dieses Schema zutrifft, ist die Ausgabe von preg_match wahr.
Code:
^([0-9]{2}\.){2}([0-9]{4})$
Das "^" Zeichen sagt aus, dass wir vom Anfang des Strings beginnen. Danach wird es etwas schwieriger.
Code:
([0-9]{2}\.)
Dieser Ausdruck sagt aus, dass eine Zeichenfolge vorkommt, die eine Zahl von 0-9 enthält. Das ist das was in den eckigen klammern steht. die Zwei dahinter sagt aus, dass diese Zeichen genau zweimal hintereinander vorkommen müssen. daraus ergeben sich Ketten wie 01,20,23, 45, 67 oder auch 99. Der Punkt dahinter sagt aus, dass dieser Zeichenenkette ein Punkt folgen muss. Der Backslash dient dazu, den Punkt zu negieren, da der Punkt ein Platzhalter für beliebige Zeichen bei RegEx ist. Jetzt werden also zeichen wie "01.", "22.", "54." usw. zugelassen. Das ganze wird in Rundeklammern gesetzt. Es gehört also zusammen.
Die Zwei in den geschweiften klammern dahinter sagt aus, dass das was wir in runden Klammern beschrieben haben, genau zweimal vorkommen darf. Es ergeben sich also Dinge wie "11.02.", "99.14." usw.
Kommen wir zum Schluss:
Code:
([0-9]{4})
Hier passiert was ähnliches wie in den anderen Teilen. Es sind wieder Zahlen von 0-9 zugelassen, die genau vier mal vorkommen müssen. Also 1234, 0192, 2450, 2007.
Setzen wir das ganze also zusammen erhalten wir folgendes:
22.99.2007, 12.34.5678 usw.
Am ende Steht dann noch das $-Zeichen. Es sagt, dass das Ende genau hier ist. Dieser Ausdruck lässt also nur einen String zu, der so aussieht:
xx.xx.xxx
Wobei die x nur Zahlen sein dürfen.

Und das ist ein regulärer Ausdruck. Sieht kompliziert aus, erspart einem aber ziemlich viel arbeit.

Der RegEx ist mit Sicherheit nicht perfekt, denn er lässt auch Datumsangaben zu, die es garnicht gibt. So wäre beispielsweise auch 99.99.9999 möglich. Er lässt jedoch keine anderen Zeichen zu. So kann niemand Code einschleusen, oder etwas eingeben, was man nicht möchte.

Gruß Mordor
 
Back
Top