2012-07-10 5 views
5

Ho uno script in cui i processori di pagamento vengono con conferme di pagamento. Per rendere la pagina sicura, in quanto si può accedere alle informazioni di ordine e altre cose legate utente, ho dovuto limitare i accesso di IP (/ 24) come segue:Conosci un semplice script php per lanciare 403, dopo il controllo ip?

$ipAllowed = array(
'192.192.192', 
'172.172.172' 
); 
$ipAllowed = str_replace(".", "\.", implode("|", $ipAllowed)); 

if(!preg_match("/^($ipAllowed)\.[0-9]{1,3}$/", $_SERVER['REMOTE_ADDR'])){ 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.'); 
} 

* gli ip di sono solo un esempio

Prima ho usato:

if(!in_array(@$_SERVER['REMOTE_ADDR'], array('ips here'))); //only works with full ip 

L'in_array era molto più ordinato, allora quello che uso ora, ma ho bisogno di qualcosa che funziona con/24 ips, o anche con entrambe le cose!

Sai qualcosa che funziona meglio/più veloce, è affidabile e molto più ordinato?

@ rap-2-h Come lei ha affermato questa è la versione più ordinato che funziona con piena ip,/24 o addirittura/16

$ipAllowed = array('192.168.1.153' '172.172.172'); 
$allowed = false; 

foreach($ipAllowed as $ip): 
    if(strpos($_SERVER['REMOTE_ADDR'], $ip) === 0) $allowed = true; 
endforeach; 

if (!$allowed) { 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.'); 
} 
+0

Spero che abbiate anche altre misure di sicurezza. L'IP è bello come difesa in profondità, ma eviterei di fare affidamento su di esso come unica misura. – CodesInChaos

+0

sì! dopo, l'intero metodo inizia a calcolare i parametri POST e agisce di conseguenza (anche un hash di tutti i parametri viene inviato con una chiave cifrata). Potrei contare solo su questo, ma voglio essere al sicuro. – amstegraf

+0

"viene anche inviato un hash di tutti i parametri con una chiave di cifratura" Come funziona l'hash con chiave? È qualcosa di buono, come HMAC o qualcosa di rotto come H (k || m)? – CodesInChaos

risposta

11

si può provare qualcosa di simile:

$ipAllowed = array('192.192.192', '172.172.172'); 

$allowed = false; 
foreach($ipAllowed as $ip) { 
    if (strpos($_SERVER['REMOTE_ADDR'], $ip) !== false) { 
     $allowed = true; 
    } 
} 
if (!$allowed) { 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.');  
} 

Quindi è possibile avere solo il frammento IP nell'array $ipAllowed. Non è molto elegante ma dovrebbe funzionare ...

+0

L'uso di strpos è in realtà una soluzione migliore rispetto a hackerare ciecamente l'ultimo ottetto, come ho fatto io. –

+0

questo sembra adatto ma dà anche accesso all'intera classe ip come 172.0.0.0 restituisce anche true o 0. No? – amstegraf

+0

'172.172.172.1' e' 1.172.172.172' saranno consentiti con questo codice. Se vuoi solo '172.172.172.X' puoi sostituire una condizione come questa' if (strpos ($ _ SERVER ['REMOTE_ADDR'], $ ip) === 0) ' –

1

Usare questa funzione per controllare se siete ip è specificato rete:

ad esempio: è 192.168.1.25 in rete 192.168.1.0/24

<?php 

/* 
* ip_in_range.php - Function to determine if an IP is located in a 
*     specific range as specified via several alternative 
*     formats. 
* 
* Network ranges can be specified as: 
* 1. Wildcard format:  1.2.3.* 
* 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
* 3. Start-End IP format: 1.2.3.0-1.2.3.255 
* 
* Return value BOOLEAN : ip_in_range($ip, $range); 
* 
* Copyright 2008: Paul Gregg <[email protected]> 
* 10 January 2008 
* Version: 1.2 
* 
* Source website: http://www.pgregg.com/projects/php/ip_in_range/ 
* Version 1.2 
* 
* This software is Donationware - if you feel you have benefited from 
* the use of this tool then please consider a donation. The value of 
* which is entirely left up to your discretion. 
* http://www.pgregg.com/donate/ 
* 
* Please do not remove this header, or source attibution from this file. 
*/ 


// decbin32 
// In order to simplify working with IP addresses (in binary) and their 
// netmasks, it is easier to ensure that the binary strings are padded 
// with zeros out to 32 characters - IP addresses are 32 bit numbers 
Function decbin32 ($dec) { 
    return str_pad(decbin($dec), 32, '0', STR_PAD_LEFT); 
} 

// ip_in_range 
// This function takes 2 arguments, an IP address and a "range" in several 
// different formats. 
// Network ranges can be specified as: 
// 1. Wildcard format:  1.2.3.* 
// 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
// 3. Start-End IP format: 1.2.3.0-1.2.3.255 
// The function will return true if the supplied IP is within the range. 
// Note little validation is done on the range inputs - it expects you to 
// use one of the above 3 formats. 
Function ip_in_range($ip, $range) { 
    if (strpos($range, '/') !== false) { 
    // $range is in IP/NETMASK format 
    list($range, $netmask) = explode('/', $range, 2); 
    if (strpos($netmask, '.') !== false) { 
     // $netmask is a 255.255.0.0 format 
     $netmask = str_replace('*', '0', $netmask); 
     $netmask_dec = ip2long($netmask); 
     return ((ip2long($ip) & $netmask_dec) == (ip2long($range) & $netmask_dec)); 
    } else { 
     // $netmask is a CIDR size block 
     // fix the range argument 
     $x = explode('.', $range); 
     while(count($x)<4) $x[] = '0'; 
     list($a,$b,$c,$d) = $x; 
     $range = sprintf("%u.%u.%u.%u", empty($a)?'0':$a, empty($b)?'0':$b,empty($c)?'0':$c,empty($d)?'0':$d); 
     $range_dec = ip2long($range); 
     $ip_dec = ip2long($ip); 

     # Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s 
     #$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0')); 

     # Strategy 2 - Use math to create it 
     $wildcard_dec = pow(2, (32-$netmask)) - 1; 
     $netmask_dec = ~ $wildcard_dec; 

     return (($ip_dec & $netmask_dec) == ($range_dec & $netmask_dec)); 
    } 
    } else { 
    // range might be 255.255.*.* or 1.2.3.0-1.2.3.255 
    if (strpos($range, '*') !==false) { // a.b.*.* format 
     // Just convert to A-B format by setting * to 0 for A and 255 for B 
     $lower = str_replace('*', '0', $range); 
     $upper = str_replace('*', '255', $range); 
     $range = "$lower-$upper"; 
    } 

    if (strpos($range, '-')!==false) { // A-B format 
     list($lower, $upper) = explode('-', $range, 2); 
     $lower_dec = (float)sprintf("%u",ip2long($lower)); 
     $upper_dec = (float)sprintf("%u",ip2long($upper)); 
     $ip_dec = (float)sprintf("%u",ip2long($ip)); 
     return (($ip_dec>=$lower_dec) && ($ip_dec<=$upper_dec)); 
    } 

    echo 'Range argument is not in 1.2.3.4/24 or 1.2.3.4/255.255.255.0 format'; 
    return false; 
    } 

} 
?> 
+2

Non dimenticare che ha affermato che sono/24 sottoreti non completi gli indirizzi IP. Penso che probabilmente dovresti eseguire il ciclo di ipAllowed e controllare se l'indirizzo era valido in base a 'strpos'? –

+0

no, perché "192.192.192" non sarà mai il REMOTE_ADDR, poiché gli indirizzi IP contengono quattro ottetti. –

+0

e nota che $ _SERVER ['REMOTE_ADDR'] può essere falso, quindi fai attenzione a questo per sbarazzarti degli attacchi – jondinham

0
<?php 

$ips = array(
    '192.160.0', 
    '172.0.0' 
); 

/** 
* Strip off the last number. 
*/ 
$_SERVER['REMOTE_ADDR'] = '192.160.0.254'; 
$ip = preg_replace('~\.(\d+)$~', '', $_SERVER['REMOTE_ADDR']); 

if(in_array($ip, $ips)) { 
    var_dump('allowed'); 
} 
+0

si! fa quello che dovrebbe, ma quello era esattamente il mio problema che avrebbe dovuto funzionare in modo più intelligente e veloce. Poiché lo strpos è più veloce, pregare e tagliare l'ultima parte, come ho fatto anch'io, non funziona in ogni caso. – amstegraf

Problemi correlati