"PHP Digest 인증 통과"의 두 판 사이의 차이

잔글 (봇: 자동으로 텍스트 교체 (-source +syntaxhighlight))
 
(사용자 2명의 중간 판 21개는 보이지 않습니다)
1번째 줄: 1번째 줄:
;PHP Digest 인증 통과
;PHP로 Digest 인증 통과하여 웹페이지 내용 읽기
==개요==
==개요==
;PHP Digest 인증 터널링
;PHP로 Digest 인증 통과하여 웹페이지 내용 읽기
*[[Digest 인증]]을 무력화한다는 의미는 아님
*[[Digest 인증]]을 무력화한다는 의미는 아님
*아이디/패스워드를 알고 있을 때 인증절차를 자동진행
*아이디/패스워드를 알고 있을 때 인증절차를 자동진행
*보통은 수동으로 인증해야만 볼 수 있는 웹페이지의 내용을 받아올 수 있음
*수동으로 인증해야 볼 수 있는 웹페이지의 내용을 받아올 수 있음


==소스 코드==
==소스 코드 1==
*[[PHP로 Digest 인증 구현]]에서 만든 페이지를 대상으로 한 예제
*[[PHP로 Digest 인증 구현]]에서 만든 페이지를 대상으로 한 예제
<source lang='php'>
<syntaxhighlight lang='php'>
<?php
<?php
function httpPost($url, $postdata, $auth) {
function httpPost($url, $postdata, $auth) {
18번째 줄: 19번째 줄:
if(!isset($auth['type']))$auth['type']='';
if(!isset($auth['type']))$auth['type']='';
  $fp = stream_socket_client("tcp://$host:$port", $err, $errstr, 60, STREAM_CLIENT_CONNECT, stream_context_create());
$fp = stream_socket_client("tcp://$host:$port", $err, $errstr, 60, STREAM_CLIENT_CONNECT, stream_context_create());
  if (!$fp) return NULL; //httpPost error
if (!$fp) return NULL; //httpPost error
  $req = "POST $path HTTP/1.1\r\nHost: $host\r\n";
$req = "POST $path HTTP/1.1\r\nHost: $host\r\n";
  if($auth['type']=='digest' && !empty($auth['username'])) {
if($auth['type']=='digest' && !empty($auth['username'])) {
    $req.='Authorization: Digest ';
$req.='Authorization: Digest ';
    foreach ($auth as $k => $v) {
foreach ($auth as $k => $v) {
      if (empty($k) || empty($v) || $k=='password') continue;
if (empty($k) || empty($v) || $k=='password') continue;
      $req .= $k.'="'.$v.'", ';
$req .= $k.'="'.$v.'", ';
    }
}
    $req.="\r\n";
$req.="\r\n";
  }
}
  $req.="Content-type: text/xml\r\nContent-length: ".strlen($postdata)."\r\nConnection: close\r\n\r\n";
$req.="Content-type: text/xml\r\nContent-length: ".strlen($postdata)."\r\nConnection: close\r\n\r\n";
  fputs($fp, $req);
fputs($fp, $req);
  fputs($fp, $postdata);
fputs($fp, $postdata);
$res = '';
$res = '';
  while(!feof($fp)) { $res .= fgets($fp, 128); }
while(!feof($fp)) { $res .= fgets($fp, 128); }
  fclose($fp);
fclose($fp);


  if( $auth['type']!='nodigest' && !empty($auth['username'])
if( $auth['type']!='nodigest' && !empty($auth['username'])
  && $auth['type']!='digest' && preg_match("/^HTTP\/[0-9\.]* 401 /", $res)
&& $auth['type']!='digest' && preg_match("/^HTTP\/[0-9\.]* 401 /", $res)
  && (1 == preg_match("/WWW-Authenticate: Digest ([^\n\r]*)\r\n/Us", $res, $matches)) ) {
&& (1 == preg_match("/WWW-Authenticate: Digest ([^\n\r]*)\r\n/Us", $res, $matches)) ) {
    foreach (split(",", $matches[1]) as $i) {
foreach (explode(",", $matches[1]) as $i) {
      $ii=split("=",trim($i),2);
$ii=explode("=",trim($i),2);
      if (!empty($ii[1]) && !empty($ii[0])) $auth[$ii[0]]=preg_replace("/^\"/",'', preg_replace("/\"$/",'', $ii[1]));
if (!empty($ii[1]) && !empty($ii[0])) $auth[$ii[0]]=preg_replace("/^\"/",'', preg_replace("/\"$/",'', $ii[1]));
    }
}
    $auth['type'] = 'digest';
$auth['type'] = 'digest';
    $auth['uri'] = "$scheme://$host$path";
$auth['uri'] = "$scheme://$host$path";
    $auth['cnonce'] = sha1(md5(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()')));
$auth['cnonce'] = sha1(md5(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()')));
    $auth['nc'] = 1;
$auth['nc'] = 1;
    $a1 = md5($auth['username'].':'.$auth['realm'].':'.$auth['password']);
$a1 = md5($auth['username'].':'.$auth['realm'].':'.$auth['password']);
    $a2 = md5('POST'.':'.$auth['uri']);
$a2 = md5('POST'.':'.$auth['uri']);
    $auth['response'] = md5($a1.':'.$auth['nonce'].':'.$auth['nc'].':'.$auth['cnonce'].':'.$auth['qop'].':'.$a2);
$auth['response'] = md5($a1.':'.$auth['nonce'].':'.$auth['nc'].':'.$auth['cnonce'].':'.$auth['qop'].':'.$a2);
    return httpPost($url, $postdata, $auth);
return httpPost($url, $postdata, $auth);
  }
}
  if (preg_match("/^HTTP\/[0-9\.]* ([0-9]{3}) ([^\r\n]*)/", $res, $matches) != 1) return NULL; //invalid HTTP reply
if (preg_match("/^HTTP\/[0-9\.]* ([0-9]{3}) ([^\r\n]*)/", $res, $matches) != 1) return NULL; //invalid HTTP reply
  if ($matches[1] != '200') return NULL; // HTTP error
if ($matches[1] != '200') return NULL; // HTTP error
  return preg_replace("/^.*\r\n\r\n/Us",'',$res);
return preg_replace("/^.*\r\n\r\n/Us",'',$res);
}
}


$auth = array('username'=>'jmnote', 'password'=>'P@ssw0rd');
$auth = array('username'=>'jmnote', 'password'=>'P@ssw0rd');
$result = httpPost('http://jmnote.com/php/auth_digest.php', '', $auth);
$result = httpPost('http://zetawiki.com/ex/php/auth_digest.php', '', $auth);
echo "result=[$result]";
echo "result=[$result]";
?>
</syntaxhighlight>
</source>
:→ [[PHP로 구현된 Digest 인증]] 예제인 http://zetawiki.com/ex/php/auth_digest.php 에  jmnote // P@ssw0rd 로 로그인하고 내용을 가져옴
*예제: http://jmnote.com/php/into_digest.php
*예제: http://zetawiki.com/ex/php/into_digest.php
 
==소스 코드 2: curl 활용==
PHP의 curl 모듈 활용
<syntaxhighlight lang='php'>
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://zetawiki.com/ex/php/auth_digest.php");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'jmnote:P@ssw0rd');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$content = curl_exec($ch);
curl_close($ch);
echo $content;
// jmnote 님 반갑습니다.
</syntaxhighlight>
*예제: http://zetawiki.com/ex/php/into_digest2.php


==같이 보기==
==같이 보기==
*[[터널링]]
*[[file_get_contents]]
*[[Digest 인증]]
*[[Digest 인증]]
*[[PHP로 Digest 인증 구현]]
*[[PHP로 Digest 인증 구현]]
*[[curl Digest 인증 통과]]
==참고==
*http://php.net/manual/en/function.stream-socket-client.php
*http://eqcode.com/wiki/Generate_nonce


[[분류: PHP]]
[[분류: PHP]]
[[분류: 인증]]
[[분류: 인증]]
[[분류: 터널링]]

2020년 11월 2일 (월) 02:34 기준 최신판

PHP Digest 인증 통과
PHP로 Digest 인증 통과하여 웹페이지 내용 읽기

1 개요[ | ]

  • Digest 인증을 무력화한다는 의미는 아님
  • 아이디/패스워드를 알고 있을 때 인증절차를 자동진행
  • 수동으로 인증해야 볼 수 있는 웹페이지의 내용을 받아올 수 있음

2 소스 코드 1[ | ]

<?php
function httpPost($url, $postdata, $auth) {
	$arr = parse_url($url);
	if($arr['scheme'] == 'http') { $scheme='http'; $port=80; }
	else if($arr['scheme'] == 'https') { $scheme='https'; $port=443; }
	$host = $arr['host'];
	$path = $arr['path'];
	
	if(!isset($auth['type']))$auth['type']='';
	$fp = stream_socket_client("tcp://$host:$port", $err, $errstr, 60, STREAM_CLIENT_CONNECT, stream_context_create());
	if (!$fp) return NULL; //httpPost error
	$req = "POST $path HTTP/1.1\r\nHost: $host\r\n";
	if($auth['type']=='digest' && !empty($auth['username'])) {
		$req.='Authorization: Digest ';
		foreach ($auth as $k => $v) {
			if (empty($k) || empty($v) || $k=='password') continue;
			$req .= $k.'="'.$v.'", ';
		}
		$req.="\r\n";
	}
	$req.="Content-type: text/xml\r\nContent-length: ".strlen($postdata)."\r\nConnection: close\r\n\r\n";
	fputs($fp, $req);
	fputs($fp, $postdata);
	
	$res = '';
	while(!feof($fp)) { $res .= fgets($fp, 128); }
	fclose($fp);

	if( $auth['type']!='nodigest' && !empty($auth['username'])
	&& $auth['type']!='digest' && preg_match("/^HTTP\/[0-9\.]* 401 /", $res)
	&& (1 == preg_match("/WWW-Authenticate: Digest ([^\n\r]*)\r\n/Us", $res, $matches)) ) {
		foreach (explode(",", $matches[1]) as $i) {
			$ii=explode("=",trim($i),2);
			if (!empty($ii[1]) && !empty($ii[0])) $auth[$ii[0]]=preg_replace("/^\"/",'', preg_replace("/\"$/",'', $ii[1]));
		}
		$auth['type'] = 'digest';
		$auth['uri'] = "$scheme://$host$path";
		$auth['cnonce'] = sha1(md5(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()')));
		$auth['nc'] = 1;
		$a1 = md5($auth['username'].':'.$auth['realm'].':'.$auth['password']);
		$a2 = md5('POST'.':'.$auth['uri']);
		$auth['response'] = md5($a1.':'.$auth['nonce'].':'.$auth['nc'].':'.$auth['cnonce'].':'.$auth['qop'].':'.$a2);
		return httpPost($url, $postdata, $auth);
	}
	if (preg_match("/^HTTP\/[0-9\.]* ([0-9]{3}) ([^\r\n]*)/", $res, $matches) != 1) return NULL; //invalid HTTP reply
	if ($matches[1] != '200') return NULL; // HTTP error
	return preg_replace("/^.*\r\n\r\n/Us",'',$res);
}

$auth = array('username'=>'jmnote', 'password'=>'P@ssw0rd');
$result = httpPost('http://zetawiki.com/ex/php/auth_digest.php', '', $auth);
echo "result=[$result]";
PHP로 구현된 Digest 인증 예제인 http://zetawiki.com/ex/php/auth_digest.php 에 jmnote // P@ssw0rd 로 로그인하고 내용을 가져옴

3 소스 코드 2: curl 활용[ | ]

PHP의 curl 모듈 활용

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://zetawiki.com/ex/php/auth_digest.php");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($ch, CURLOPT_USERPWD, 'jmnote:P@ssw0rd');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$content = curl_exec($ch);
curl_close($ch);
echo $content;
// jmnote 님 반갑습니다.

4 같이 보기[ | ]

5 참고[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}