Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * PHP Soap Digest Authentication
- *
- * This script simulates the implementation of Digest
- * authentication present in the php5 soap module to
- * demonstate the flaw which prevents authorisation
- * against Microsoft SQL Server
- *
- */
- //point this script at a SOAP service on MSSQL Server
- $user='username';
- $pass='password';
- $host="1.2.3.4";
- $uri="/ept/cv?wsdl";
- //demonstrate fix
- $fix_buggy_behaviour=true;
- //make initial request
- $headers=getHttpResponseHeaders($host, $uri);
- //ensure resource requires authentication
- if ($headers['_statuscode']!=401)
- die("$host does not require authorization");
- if (!isset($headers['WWW-Authenticate']))
- die("No WWW-Authenticate header");
- //parse the WWW-Authenticate header
- $auth=array();
- list($type,$params)=explode(' ', $headers['WWW-Authenticate']);
- $params=explode(',',$params);
- foreach($params as $param)
- {
- list($name,$value)=explode('=',$param);
- $value=preg_replace('/^"/', '', $value);
- $value=preg_replace('/"$/', '', $value);
- $auth[$name]=$value;
- }
- //check the header is worth testing further
- if ($type!='Digest')
- die('Host is not configured for Digest authentication');
- if ($auth['algorithm']!='MD5-sess')
- die('Bug only occurs with server requesting MD5-sess algorithm');
- //define our client side values
- $nc="00000001";
- $cnonce=substr(md5(rand()),0,8);
- //calc HA1
- $ha1=md5($user.':'.$auth['realm'].':'.$pass);
- //refine HA1 for MD5-sess
- if ($auth['algorithm']=='MD5-sess')
- $ha1=md5($ha1.':'.$auth['nonce'].':'.$cnonce);
- //calc HA2
- $ha2=md5('GET:'.$uri);
- //build response hash
- $rhash=md5($ha1.':'.$auth['nonce'].':'.$nc.':'.$cnonce.':'.$auth['qop'].':'.$ha2);
- //assemble what we want in our response
- $response=array();
- $response['username']=$user;
- $response['realm']=$auth['realm'];
- $response['nonce']=$auth['nonce'];
- $response['uri']=$uri;
- $response['cnonce']=$cnonce;
- $response['nc']=$nc;
- $response['qop']=$auth['qop'];
- $response['response']=$rhash;
- if ($fix_buggy_behaviour)
- {
- //the PHP soap module does not include this header
- //when the md5-sess algorithm has been applied
- $response['algorithm']=$auth['algorithm'];
- }
- //construct the header line
- $authorization="Digest";
- $sep="";
- foreach($response as $name=>$value)
- {
- $authorization.=$sep." {$name}=\"".$value."\"";
- $sep=",";
- }
- //make the request again
- $headers=getHttpResponseHeaders($host, $uri, array('Authorization'=>$authorization));
- if ($headers['_statuscode']==200)
- {
- echo "Request succeeded - digest authentication worked<br>";
- }
- else
- {
- echo "Request failed - digest authentication broken<br>";
- var_dump($headers);
- }
- exit;
- /**
- * Makes HTTP request with optional headers and returns
- * array of response headers
- */
- function getHttpResponseHeaders($host, $uri='/', $headers=array())
- {
- $fp = fsockopen($host, 80, $errno, $errstr, 30);
- if (!$fp) {
- die("$errstr ($errno)");
- } else {
- $http="GET $uri HTTP/1.1\r\n";
- foreach($headers as $name=>$value){
- $http.="$name:$value\r\n";
- }
- $http.="Host:$host\r\n";
- $http.="Connection: Close:$host\r\n";
- $http.="\r\n";
- fwrite($fp, $http);
- $lines=0;
- while (!feof($fp)) {
- $lines++;
- $header=trim(fgets($fp, 8192));
- if (empty($header))
- break;
- if ($lines>1)
- {
- list($name,$value)=explode(':',$header);
- $headers[$name]=trim($value);
- }
- else
- {
- list($protocol, $status, $msg)=explode(' ',$header,3);
- $headers['_protocol']=$protocol;
- $headers['_statuscode']=$status;
- $headers['_statusmsgmsg']=$msg;
- }
- }
- fclose($fp);
- }
- return $headers;
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement