Als eerste mis ik bij de code de statement:
PHP:
1
| mysql_free_result($result); |
Ten tweede zie ik nogal wat ongecontroleerde acties. Het meest nette is werken met
registerglobals = false, dat voorkomt heel wat ellende.
Daarnaast zou ik post values anders afvangen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
| $sEmail = trim(isset($_POST['email']?$POST['email']:'');
$sName = trim(isset($_POST['name']?$POST['name']:'');
// andere acties
if (strlen($sEmail)>0) && (strlen($sName)>0))
{
// Voer andere controles uit, bijvoorbeeld foute letters of andere zaken zoals lengte.
}
else
{
die('Piss off!');
} |
Wanneer je de waarden op basis eisen hebt gevalideerd kan je verder gaan. Je kan injection voorkomen door types toe te passen en strings voor te bereiden:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| $sEmail = trim(isset($_POST['email']?$POST['email']:'');
$sName = trim(isset($_POST['name']?$POST['name']:'');
$sMsg = trim(isset($_POST['msg']?$POST['msg']:'');
$iAge = trim(isset($_POST['age']?$POST['age']:0);
settype($sEmail,'string');
settype($sName,'string');
settype($sMsg,'string');
settype($iAge,'integer');
$aSpam= array('sex','porn','teens','slut'); // Zelf voorbereiden
// andere acties
if (strlen($sEmail)>0) && (strlen($sName)>0) && ($iAge>0) && ($iAge<150) && strlen($Msg)>10))
{
// Voer andere controles uit, bijvoorbeeld foute letters of andere zaken zoals lengte.
// We gaan even filteren
$sSearch= $sEmail . $sName . $sMsg;
$bError= FALSE;
foreach($aSpam as $sTest)
{
$bError= (stripos($sSearch,$sTest)>0?TRUE:$bError);
}
if (!$bError)
{
// We kunnen verder
}
else
{
die("Don't try me!");
}
}
else
{
die('Piss off!');
} |
Natuurlijk kunnen ze grapjes uithalen met HTML code en hidden zaken. Dus kan je nog wat extra doen om dat te voorkomen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
| $sEmail = trim(isset($_POST['email']?$POST['email']:'');
$sName = trim(isset($_POST['name']?$POST['name']:'');
$sMsg = trim(isset($_POST['msg']?$POST['msg']:'');
$iAge = trim(isset($_POST['age']?$POST['age']:0);
settype($sEmail,'string');
settype($sName,'string');
settype($sMsg,'string');
settype($iAge,'integer');
$aSpam= array('sex','porn','teens','slut'); // Zelf voorbereiden
// andere acties
if (strlen($sEmail)>0) && (strlen($sName)>0) && ($iAge>0) && ($iAge<150) && strlen($Msg)>10))
{
// Voer andere controles uit, bijvoorbeeld foute letters of andere zaken zoals lengte.
// We gaan even filteren (aangepast met functie)
$sSearch= StripTheShit($sEmail . $sName . $sMsg);
$bError= FALSE;
foreach($aSpam as $sTest)
{
$bError= (stripos($sSearch,$sTest)>0?TRUE:$bError);
}
if (!$bError)
{
// We kunnen verder
}
else
{
die("Don't try me!");
}
}
else
{
die('Piss off!');
}
function StripTheShit($sDocument)
{
$aSearch = array ('@<script[^>]*?>.*?</script>@si', // Strip out javascript
'@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
'@([\r\n])[\s]+@', // Strip out white space
'@&(quot|#34);@i', // Replace HTML entities
'@&(amp|#38);@i',
'@&(lt|#60);@i',
'@&(gt|#62);@i',
'@&(nbsp|#160);@i',
'@&(iexcl|#161);@i',
'@&(cent|#162);@i',
'@&(pound|#163);@i',
'@&(copy|#169);@i',
'@&#(\d+);@e'); // evaluate as php
$aReplace = array ('',
'',
'\1',
'"',
'&',
'<',
'>',
' ',
chr(161),
chr(162),
chr(163),
chr(169),
'chr(\1)');
return preg_replace($aSearch, $aReplace, strip_tags($sDocument));
} |
Maar dit is natuurlijk niet genoeg. De database moet worden bijgewerkt en er moet wat op het scherm gegooid worden:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
| $sEmail = trim(isset($_POST['email']?$POST['email']:'');
$sName = trim(isset($_POST['name']?$POST['name']:'');
$sMsg = trim(isset($_POST['msg']?$POST['msg']:'');
$iAge = trim(isset($_POST['age']?$POST['age']:0);
settype($sEmail,'string');
settype($sName,'string');
settype($sMsg,'string');
settype($iAge,'integer');
$aSpam= array('sex','porn','teens','slut'); // Zelf voorbereiden
// andere acties
if (strlen($sEmail)>0) && (strlen($sName)>0) && ($iAge>0) && ($iAge<150) && strlen($Msg)>10))
{
// Voer andere controles uit, bijvoorbeeld foute letters of andere zaken zoals lengte.
// We gaan even filteren (aangepast met functie)
$sSearch= StripTheShit($sEmail . $sName . $sMsg);
$bError= FALSE;
foreach($aSpam as $sTest)
{
$bError= (stripos($sSearch,$sTest)>0?TRUE:$bError);
}
if (!$bError)
{
// We gaan strings voorbereiden:
$sDBEmail= mysql_real_escape_string($sEmail);
$sDBName= mysql_real_escape_string($sName);
$sDBMsg= mysql_real_escape_string($sMsg);
$iDBAge= $iAge;
$sEmail= htmlentities($sEmail);
$sName= htmlentities($sName);
$sMsg= htmlentities($sMsg);
// Niet nodig $iAge= $iAge;
// Database bijwerken
$sSql= "INSERT INTO `mytable` SET `email`='".$sDBEmail."', ".
" `name`='".$sDBName."', ".
" `age`=".$iDBAge.", ".
" `msg`='".$sDBMsg."';";
if (mysql_query($sSql))
{
// Dump hier de tekst naar het scherm
}
else
{
die('Update failed!');
}
}
else
{
die("Don't try me!");
}
}
else
{
die('Piss off!');
}
function StripTheShit($sDocument)
{
$aSearch = array ('@<script[^>]*?>.*?</script>@si', // Strip out javascript
'@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
'@([\r\n])[\s]+@', // Strip out white space
'@&(quot|#34);@i', // Replace HTML entities
'@&(amp|#38);@i',
'@&(lt|#60);@i',
'@&(gt|#62);@i',
'@&(nbsp|#160);@i',
'@&(iexcl|#161);@i',
'@&(cent|#162);@i',
'@&(pound|#163);@i',
'@&(copy|#169);@i',
'@&#(\d+);@e'); // evaluate as php
$aReplace = array ('',
'',
'\1',
'"',
'&',
'<',
'>',
' ',
chr(161),
chr(162),
chr(163),
chr(169),
'chr(\1)');
return preg_replace($aSearch, $aReplace, strip_tags($sDocument));
} |
Natturlijk kan je hiermee nog niet alles voorkomen. Een simpele doch doeltreffende methode is gebruik maken van een aantal technieken zonde javascript.
De code van je post form:
PHP:
1
2
3
4
5
6
7
8
9
10
11
| // headers etc.
echo '<form method="post" action="formhandler.php">';
echo '<input type="hidden" name="ip" value="'.$_SERVER['REMOTE_ADDR'].'">'; // Dummy voor de afleiding, doen we niet echt veel mee.
echo '<input type="text" name="email" size="50" maxlength="50" /><br />';
echo '<input type="text" name="name" size="50" maxlength="50" /><br />';
echo '<input type="text" name="age" size="4" maxlength="4" /><br />';
echo '<textarea name="msg" rows="10" cols="50"></textarea><br />';
// Nu een stukje funny code
echo '<input type="submit" value="Add to guestbook" name="'.base64_encode(md5($_SERVER['REMOTE_ADDR'])).'" />';
echo '</form>';
// Footers etc. |
Let nu goed op, de Submit actie wordt gewoon doorgegeven als een $_POST veld. De voorgaande code kunnen we als volgt aanpassen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
| // We maken gebruik van de data zoals in de form is meegegeven:
// Bereken de naam van het button veld.
$sTest= base64_encode(md5($_SERVER['REMOTE_ADDR']));
$bButton= (isset($_POST[$sTest])?TRUE:FALSE);
$sIp= trim(isset($_POST['ip']?$POST['ip']:'');
settype($sIp,'string');
if (($bButton) && ($_SERVER['REMOTE_ADDR']))==$sIp))
{
$sEmail = trim(isset($_POST['email']?$POST['email']:'');
$sName = trim(isset($_POST['name']?$POST['name']:'');
$sMsg = trim(isset($_POST['msg']?$POST['msg']:'');
$iAge = trim(isset($_POST['age']?$POST['age']:0);
settype($sEmail,'string');
settype($sName,'string');
settype($sMsg,'string');
settype($iAge,'integer');
settype($sIp,'string');
$aSpam= array('sex','porn','teens','slut'); // Zelf voorbereiden
// andere acties
if (strlen($sEmail)>0) && (strlen($sName)>0) && ($iAge>0) && ($iAge<150) && strlen($Msg)>10))
{
// Voer andere controles uit, bijvoorbeeld foute letters of andere zaken zoals lengte.
// We gaan even filteren (aangepast met functie)
$sSearch= StripTheShit($sEmail . $sName . $sMsg);
$bError= FALSE;
foreach($aSpam as $sTest)
{
$bError= (stripos($sSearch,$sTest)>0?TRUE:$bError);
}
if (!$bError)
{
// We gaan strings voorbereiden:
$sDBEmail= mysql_real_escape_string($sEmail);
$sDBName= mysql_real_escape_string($sName);
$sDBMsg= mysql_real_escape_string($sMsg);
$sDBIp= mysql_real_escape_string($sIp);
$iDBAge= $iAge;
$sEmail= htmlentities($sEmail);
$sName= htmlentities($sName);
$sMsg= htmlentities($sMsg);
// Niet nodig $iAge= $iAge;
// Database bijwerken
$sSql= "INSERT INTO `mytable` SET `email`='".$sDBEmail."', ".
" `name`='".$sDBName."', ".
" `age`=".$iDBAge.", ".
" `ip`='".$iDBIp."', ".
" `msg`='".$sDBMsg."';";
if (mysql_query($sSql))
{
// Dump hier de tekst naar het scherm
}
else
{
die('Update failed!');
}
}
else
{
die("Don't try me!");
}
}
else
{
die('Piss off!');
}
}
else
{
die('Try to play with your IP?');
}
function StripTheShit($sDocument)
{
$aSearch = array ('@<script[^>]*?>.*?</script>@si', // Strip out javascript
'@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
'@([\r\n])[\s]+@', // Strip out white space
'@&(quot|#34);@i', // Replace HTML entities
'@&(amp|#38);@i',
'@&(lt|#60);@i',
'@&(gt|#62);@i',
'@&(nbsp|#160);@i',
'@&(iexcl|#161);@i',
'@&(cent|#162);@i',
'@&(pound|#163);@i',
'@&(copy|#169);@i',
'@&#(\d+);@e'); // evaluate as php
$aReplace = array ('',
'',
'\1',
'"',
'&',
'<',
'>',
' ',
chr(161),
chr(162),
chr(163),
chr(169),
'chr(\1)');
return preg_replace($aSearch, $aReplace, strip_tags($sDocument));
} |
Uiteindelijk wordt het volgende bereikt:
- Vreemde woorden,
- Verborgen HTML en andere zaken zoals javascripts, php etc,
- Request en post vanaf verschillende adressen,
- SQL injection (door gebruik van mysql_real_escape_string en backtics (`)),
- Code injection in database en return pagina.
- Misleiding, door IP nummer van request te maskeren in een button veld en een simpel hidden ip-veld. Dit laatste zorgt ervoor dat kwaadwillenden om de tuin worden geleid.
Niet gebruikte truuk is gebruikmaken van SessionId(). Dit kan ook nog samen met de $_SESSION array voor sessie gebaseerde opslag. Cookies zijn ook leuk trouwens.
WB
[
Voor 38% gewijzigd door
Wim-Bart op 22-12-2005 01:39
]
Beheerders, Consultants, Servicedesk medewerkers. We zoeken het allemaal. Stuur mij een PM voor meer info of kijk hier De mooiste ICT'er van Nederland.