Skip to content

Commit

Permalink
회원정보찾기 인증 URL에 들어가는 난수 개선
Browse files Browse the repository at this point in the history
  • Loading branch information
kijin committed Aug 12, 2014
1 parent fdc93c1 commit 241848a
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 14 deletions.
15 changes: 9 additions & 6 deletions bbs/password_lost2.php
Expand Up @@ -28,16 +28,19 @@
else if (is_admin($mb['mb_id']))
alert('관리자 아이디는 접근 불가합니다.');

// 난수 발생
srand(time());
// 임시비밀번호 발급
$change_password = rand(100000, 999999);
$mb_lost_certify = sql_password($change_password);
$mb_datetime = sql_password($mb['mb_datetime']);

$sql = " update {$g5['member_table']} set mb_lost_certify = '$mb_lost_certify' where mb_id = '{$mb['mb_id']}' ";
// 어떠한 회원정보도 포함되지 않은 일회용 난수를 생성하여 인증에 사용
$mb_nonce = bin2hex(pack('V*', rand(), rand(), rand(), rand()));

// 임시비밀번호와 난수를 mb_lost_certify 필드에 저장
$sql = " update {$g5['member_table']} set mb_lost_certify = '$mb_nonce $mb_lost_certify' where mb_id = '{$mb['mb_id']}' ";
sql_query($sql);

$href = G5_BBS_URL.'/password_lost_certify.php?mb_no='.$mb['mb_no'].'&mb_datetime='.$mb_datetime.'&mb_lost_certify='.$mb_lost_certify;
// 인증 링크 생성
$href = G5_BBS_URL.'/password_lost_certify.php?mb_no='.$mb['mb_no'].'&mb_nonce='.$mb_nonce;

$subject = "[".$config['cf_title']."] 요청하신 회원정보 찾기 안내 메일입니다.";

Expand Down Expand Up @@ -69,4 +72,4 @@
mailer($config['cf_admin_email_name'], $config['cf_admin_email'], $mb['mb_email'], $subject, $content, 1);

alert_close($email.' 메일로 회원아이디와 비밀번호를 인증할 수 있는 메일이 발송 되었습니다.\\n\\n메일을 확인하여 주십시오.');
?>
?>
16 changes: 8 additions & 8 deletions bbs/password_lost_certify.php
Expand Up @@ -4,24 +4,24 @@
// 오류시 공히 Error 라고 처리하는 것은 회원정보가 있는지? 비밀번호가 틀린지? 를 알아보려는 해킹에 대비한것

$mb_no = trim($_GET['mb_no']);
$mb_datetime = trim($_GET['mb_datetime']);
$mb_lost_certify = trim($_GET['mb_lost_certify']);
$mb_nonce = trim($_GET['mb_nonce']);

// 회원아이디가 아닌 회원고유번호로 회원정보를 구한다.
$sql = " select mb_id, mb_datetime, mb_lost_certify from {$g5['member_table']} where mb_no = '$mb_no' ";
$sql = " select mb_id, mb_lost_certify from {$g5['member_table']} where mb_no = '$mb_no' ";
$mb = sql_fetch($sql);
if (!trim($mb['mb_lost_certify']))
if (strlen($mb['mb_lost_certify']) < 33)
die("Error");

// 인증 링크는 한번만 처리가 되게 한다.
sql_query(" update {$g5['member_table']} set mb_lost_certify = '' where mb_no = '$mb_no' ");

// 변경될 비밀번호가 넘어와야하고 저장된 변경비밀번호를 md5 로 변환하여 같으면 정상
if ($mb_lost_certify && $mb_datetime === sql_password($mb['mb_datetime']) && $mb_lost_certify === $mb['mb_lost_certify']) {
sql_query(" update {$g5['member_table']} set mb_password = '{$mb['mb_lost_certify']}' where mb_no = '$mb_no' ");
// 인증을 위한 난수가 제대로 넘어온 경우 임시비밀번호를 실제 비밀번호로 바꿔준다.
if ($mb_nonce === substr($mb['mb_lost_certify'], 0, 32)) {
$new_password_hash = substr($mb['mb_lost_certify'], 33);
sql_query(" update {$g5['member_table']} set mb_password = '$new_password_hash' where mb_no = '$mb_no' ");
alert('비밀번호가 변경됐습니다.\\n\\n회원아이디와 변경된 비밀번호로 로그인 하시기 바랍니다.', G5_BBS_URL.'/login.php');
}
else {
die("Error");
}
?>
?>

1 comment on commit 241848a

@kijin
Copy link
Owner Author

@kijin kijin commented on 241848a Aug 12, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

회원정보찾기 인증키에서 임시비번(mb_lost_certify)과 가입일시(mb_datetime)의 해시값(sql_password)을 빼고, 그 대신 랜덤으로 생성된 일회용 난수(nonce)를 사용하여 인증 URL을 통한 개인정보 유출의 가능성을 차단하는 패치입니다.

현재는 임시비밀번호의 해시값과 가입일시의 해시값을 인증키에 그대로 넣고 있어 메일 계정과 브라우저 히스토리를 통해 이런 정보가 유출될 우려가 있습니다. 당장 심각한 취약점은 아니지만, 그누보드는 기본적으로 보안이 약한 MySQL PASSWORD() 함수로 해싱을 하고 있으며, 발급된 임시비밀번호를 변경하지 않는 회원도 많다는 점에서 약간의 위험성이 있다고 할 수 있습니다. 가입일시와 임시비밀번호는 경우의 수가 얼마 되지 않으므로, 해시값이 포함된 URL을 공격자가 손에 넣는다면 불과 몇 분만에 무차별 대입 공격에 성공할 수도 있습니다.

그러나 인증키에 반드시 비번과 가입일시를 사용해야 한다는 법은 없습니다. 정보찾기를 요청한 회원 본인 외에는 클릭하지 못하도록 하는 것이 목적이므로, 타인이 추측하기 어렵고 중복되지 않는 값이라면 어떤 것이든 상관없습니다.

이 패치에서는 rand() 함수를 반복 호출하여 124비트 내외의 무의미한 데이터를 수집한 후, 16진수 32자리의 형태로 정리하여 인증키로 사용하도록 하였습니다. 이렇게 생성한 일회용 난수(mb_nonce) 하나만을 URL에 넣어 전달함으로써 개인정보 유출의 위험도 낮추고 URL의 길이도 다소 줄였습니다.

Please sign in to comment.