Advertisement
Guest User

LordElph

a guest
Oct 25th, 2008
1,310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.74 KB | None | 0 0
  1. <?php
  2. /**
  3. * PHP Soap Digest Authentication
  4. *
  5. * This script simulates the implementation of Digest
  6. * authentication present in the php5 soap module to
  7. * demonstate the flaw which prevents authorisation
  8. * against Microsoft SQL Server
  9. *
  10. */
  11.  
  12. //point this script at a SOAP service on MSSQL Server
  13. $user='username';
  14. $pass='password';
  15. $host="1.2.3.4";
  16. $uri="/ept/cv?wsdl";
  17.  
  18. //demonstrate fix
  19. $fix_buggy_behaviour=true;
  20.  
  21. //make initial request
  22. $headers=getHttpResponseHeaders($host, $uri);
  23.  
  24. //ensure resource requires authentication
  25. if ($headers['_statuscode']!=401)
  26.     die("$host does not require authorization");
  27. if (!isset($headers['WWW-Authenticate']))
  28.     die("No WWW-Authenticate header");
  29.    
  30. //parse the WWW-Authenticate header
  31. $auth=array();
  32. list($type,$params)=explode(' ', $headers['WWW-Authenticate']);
  33. $params=explode(',',$params);
  34. foreach($params as $param)
  35. {
  36.     list($name,$value)=explode('=',$param);
  37.    
  38.     $value=preg_replace('/^"/', '', $value);
  39.     $value=preg_replace('/"$/', '', $value);
  40.    
  41.     $auth[$name]=$value;
  42. }
  43.  
  44.  
  45. //check the header is worth testing further
  46. if ($type!='Digest')
  47.     die('Host is not configured for Digest authentication');
  48. if ($auth['algorithm']!='MD5-sess')
  49.     die('Bug only occurs with server requesting MD5-sess algorithm');
  50.  
  51. //define our client side values
  52. $nc="00000001";
  53. $cnonce=substr(md5(rand()),0,8);
  54.  
  55. //calc HA1
  56. $ha1=md5($user.':'.$auth['realm'].':'.$pass);
  57.  
  58. //refine HA1 for MD5-sess
  59. if ($auth['algorithm']=='MD5-sess')
  60.     $ha1=md5($ha1.':'.$auth['nonce'].':'.$cnonce);
  61.  
  62. //calc HA2
  63. $ha2=md5('GET:'.$uri);
  64.  
  65. //build response hash
  66. $rhash=md5($ha1.':'.$auth['nonce'].':'.$nc.':'.$cnonce.':'.$auth['qop'].':'.$ha2);
  67.  
  68. //assemble what we want in our response
  69. $response=array();
  70. $response['username']=$user;
  71. $response['realm']=$auth['realm'];
  72. $response['nonce']=$auth['nonce'];
  73. $response['uri']=$uri;
  74. $response['cnonce']=$cnonce;
  75. $response['nc']=$nc;
  76. $response['qop']=$auth['qop'];
  77. $response['response']=$rhash;
  78.  
  79. if ($fix_buggy_behaviour)
  80. {
  81.     //the PHP soap module does not include this header
  82.     //when the md5-sess algorithm has been applied 
  83.     $response['algorithm']=$auth['algorithm'];
  84. }
  85.  
  86.  
  87. //construct the header line
  88. $authorization="Digest";
  89. $sep="";
  90. foreach($response as $name=>$value)
  91. {
  92.     $authorization.=$sep." {$name}=\"".$value."\"";
  93.     $sep=",";
  94. }
  95.  
  96.  
  97.  
  98. //make the request again
  99. $headers=getHttpResponseHeaders($host, $uri, array('Authorization'=>$authorization));
  100.  
  101. if ($headers['_statuscode']==200)
  102. {
  103.     echo "Request succeeded - digest authentication worked<br>";
  104. }
  105. else
  106. {
  107.     echo "Request failed - digest authentication broken<br>";
  108.     var_dump($headers);
  109.    
  110. }
  111.  
  112. exit;
  113.  
  114.  
  115. /**
  116.  * Makes HTTP request with optional headers and returns
  117.  * array of response headers
  118.  */    
  119. function getHttpResponseHeaders($host, $uri='/', $headers=array())
  120. {
  121.     $fp = fsockopen($host, 80, $errno, $errstr, 30);
  122.     if (!$fp) {
  123.        die("$errstr ($errno)");
  124.     } else {
  125.         $http="GET $uri HTTP/1.1\r\n";
  126.        
  127.         foreach($headers as $name=>$value){
  128.             $http.="$name:$value\r\n";
  129.         }
  130.         $http.="Host:$host\r\n";
  131.         $http.="Connection: Close:$host\r\n";
  132.         $http.="\r\n";
  133.      
  134.         fwrite($fp, $http);
  135.        
  136.         $lines=0;
  137.         while (!feof($fp)) {
  138.             $lines++;
  139.             $header=trim(fgets($fp, 8192));
  140.             if (empty($header))
  141.                 break;
  142.            
  143.             if ($lines>1)
  144.             {
  145.                 list($name,$value)=explode(':',$header);
  146.                 $headers[$name]=trim($value);
  147.             }
  148.             else
  149.             {
  150.                 list($protocol, $status, $msg)=explode(' ',$header,3);
  151.                 $headers['_protocol']=$protocol;
  152.                 $headers['_statuscode']=$status;
  153.                 $headers['_statusmsgmsg']=$msg;
  154.             }
  155.         }
  156.         fclose($fp);
  157.     }
  158.     return $headers;
  159. }
  160.  
  161. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement