Created
July 6, 2016 09:56
-
-
Save Ksnk/cea7c5dea4491952ea9de358d025bd75 to your computer and use it in GitHub Desktop.
NTLM page authorization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// this user allow to pass | |
$config=array( | |
'domain'=>'WEB-server', // Вставлять в окно ввода : WEB-server\Юзер Пароль | |
'user'=> 'Юзер', // name of user | |
'password' => 'Пароль', // password of registered user | |
'forceNTLM' => false , // обязательно ли требовать авторизацию? | |
); | |
session_start(); | |
ob_start(); | |
$ntlm=new NTLM_service($config); | |
header('Content-type: text/html; charset=utf-8'); | |
if(false===$ntlm->checkAuth()){ | |
$ntlm->sendHeaders(); | |
ob_end_flush(); | |
exit; | |
} | |
if($_SERVER['REQUEST_METHOD']=='POST'){ | |
if(isset($_POST['logout']) && $ntlm->checkAuth()){ | |
$ntlm->sendHeaders(true); | |
exit; | |
} | |
if(isset($_POST['login']) && !$ntlm->checkAuth()){ | |
$ntlm->sendHeaders(true); | |
exit; | |
} | |
} | |
if(!function_exists('hash_hmac')){ | |
echo 'hash_hmac function not found. So you can\'t use NTLM here. :(<br>'; | |
} | |
if(!$ntlm->checkAuth()){ | |
// выводим незащищенный контент | |
?> | |
Unprotected page<br> | |
<form method="POST" action=""> | |
<input type="submit" name="login" value="login"> | |
</form> | |
<?php | |
} else {// выводим защищенный контент | |
?> | |
Hello <?=$ntlm->config['user']?>(<?=$ntlm->config['workstation']?>) | |
<form method="POST" action=""> | |
<input type="submit" name="logout" value="logout"> | |
</form> | |
<?php | |
} | |
/** | |
* Отладочная функция - дамп бинарной строки со строковым дополнением | |
* @param $str | |
* @param string $label | |
* @return string | |
*/ | |
function hex_dump($str,$label='') | |
{ | |
return | |
(empty($label)?'':$label.'('.strlen($str).'): '). | |
chunk_split(bin2hex($str),2," "). | |
' | '.iconv('cp1251','utf-8//ignore',preg_replace('#[\x00-\x20,\xff]#', '.', $str)); | |
} | |
class NTLM_service { | |
var $_config; | |
private | |
$retCode=false; | |
const | |
NTLM_401_UNAUTHORIZED = 1, | |
NTLM_NEXT_STEP = 2, | |
NTLM_SUCCESS = 3; | |
/** | |
* get all headers. | |
*/ | |
function header(){ | |
if(function_exists('apache_request_headers')) | |
return apache_request_headers(); | |
$headers = array(); | |
foreach ($_SERVER as $key => $value) { | |
if (substr($key, 0, 5) == "HTTP_") { | |
$key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5))))); | |
$headers[$key] = $value; | |
} else { | |
$headers[$key] = $value; | |
} | |
} | |
return $headers; | |
} | |
/** | |
* start or continue authorisation | |
* @param string $code | |
*/ | |
function sendHeaders($code=''){ | |
if(!empty($code)) $code=self::NTLM_401_UNAUTHORIZED; | |
else $code=$this->retCode; | |
switch($code){ | |
case self::NTLM_401_UNAUTHORIZED: | |
header('HTTP/1.1 401 Unauthorized'); // требуем от клиента авторизации | |
header('WWW-Authenticate: NTLM'); // тип требуемой авторизации - NTLM | |
break; | |
case self::NTLM_NEXT_STEP: | |
header('HTTP/1.1 401 Unauthorized'); | |
header('WWW-Authenticate: NTLM ' . base64_encode($this->Type2())); // отправляем сообщение type-2 | |
break; | |
} | |
} | |
function __construct($config){ | |
if(isset($_SESSION['ntlm']) && is_array($_SESSION['ntlm'])){ | |
$config=array_merge($config,$_SESSION['ntlm']); | |
}; | |
$this->config=$config; | |
} | |
function store(){ | |
$_SESSION['ntlm']=$this->config; | |
} | |
function random8(){ | |
$result=''; | |
for($i=0;$i<8;$i++) $result.=chr(rand(0,255)); | |
return $result; | |
} | |
function Type2(){ | |
$this->config['server_challenge']=$this->random8(); | |
$this->store(); | |
return "NTLMSSP\x00" . // протокол // 0- | |
"\x02" /* номер этапа */ . "\x00\x00\x00\x00\x00\x00\x00" . //8- | |
"\x28\x00" /* общая длина сообщения */ . "\x00\x00" . //16 | |
"\x01\x82" /* признак */ . "\x00\x00" . // 20 | |
$this->config['server_challenge'] . // 24-8 -challenge | |
"\x00\x00\x00\x00\x00\x00\x00\x00"; | |
} | |
function checkAuth(){ | |
if(empty($this->retCode)){ | |
$headers=$this->header(); | |
$this->retCode=self::NTLM_401_UNAUTHORIZED; | |
if (isset($headers['Authorization']) && substr($headers['Authorization'], 0, 5) == 'NTLM ') { | |
// проверяем, что это NTLM-аутентификация | |
$chain = base64_decode(substr($headers['Authorization'], 5)); // получаем декодированное значение | |
switch (ord($chain{8})) { | |
case 1: | |
if (ord($chain{13}) == 0x82 || ord($chain{13}) == 0xB2) { // проверяем признак NTLM 0x82 по смещению 13 в сообщении type-1: | |
$this->retCode=self::NTLM_NEXT_STEP; | |
} | |
break; | |
case 3: | |
$respond=array('LM_resp'=>false, 'NT_resp'=>false, 'domain'=>true, 'user'=>true, 'workstaion'=>true); | |
$k=0; | |
$offset=0; $length=0; | |
foreach ($respond as $v => $vv) { | |
extract(unpack('vlength/voffset', substr($chain, $k * 8 + 14, 4))); | |
$respond[$v] = substr($chain, $offset, $length); | |
if($vv) | |
$respond[$v]=iconv('UTF-16LE','UTF-8',$respond[$v]); | |
$k++; | |
} | |
$blob=substr($respond['NT_resp'],16); | |
//echo 'domain:'. $respond['domain']."<br>\n"; | |
//echo 'user:'. $respond['user']."<br>\n"; | |
//echo 'workstaion:'. $respond['workstaion']."<br>\n"; | |
//echo hex_dump($respond['NT_resp'],'NT_resp')."<br>\n"; | |
$start_hash=hash_hmac('md5',$this->config['server_challenge'].$blob, | |
hash_hmac('md5',iconv('UTF-8', 'UTF-16LE',mb_strtoupper($this->config['user'],'UTF-8').$this->config['domain']), | |
hash('md4',iconv('UTF-8', 'UTF-16LE',$this->config['password']),true), | |
true), | |
true); | |
//echo hex_dump($start_hash,'hash')."<br>\n"; | |
$this->config['workstation']=$respond['workstaion']; | |
if($start_hash==substr($respond['NT_resp'],0,16)){ | |
$this->retCode=self::NTLM_SUCCESS; | |
} | |
break; | |
} | |
} | |
} | |
return | |
$this->retCode==self::NTLM_401_UNAUTHORIZED?0: | |
($this->retCode==self::NTLM_NEXT_STEP?false:true); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment