From 866f49ec474caf209fa0c07cad5446d9521c3f40 Mon Sep 17 00:00:00 2001 From: thisgun Date: Mon, 22 Oct 2018 17:53:38 +0900 Subject: [PATCH] =?UTF-8?q?pbkdf2=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adm/board_form_update.php | 2 + bbs/login_check.php | 2 +- common.php | 2 +- config.php | 10 +- install/gnuboard5.sql | 62 ++++++----- install/install_db.php | 11 +- lib/common.lib.php | 38 +++++++ lib/pbkdf2.compat.php | 221 ++++++++++++++++++++++++++++++++++++++ lib/uri.lib.php | 27 ++--- 9 files changed, 328 insertions(+), 47 deletions(-) create mode 100644 lib/pbkdf2.compat.php diff --git a/adm/board_form_update.php b/adm/board_form_update.php index 912887760..b3de17f01 100644 --- a/adm/board_form_update.php +++ b/adm/board_form_update.php @@ -186,6 +186,8 @@ if ($w == '') { // 게시판 테이블 생성 $file = file('./sql_write.sql'); + $file = get_db_create_replace($file); + $sql = implode($file, "\n"); $create_table = $g5['write_prefix'] . $bo_table; diff --git a/bbs/login_check.php b/bbs/login_check.php index 3fe856313..ba7c65987 100644 --- a/bbs/login_check.php +++ b/bbs/login_check.php @@ -29,7 +29,7 @@ if(function_exists('social_is_login_check')){ // 가입된 회원이 아니다. 비밀번호가 틀리다. 라는 메세지를 따로 보여주지 않는 이유는 // 회원아이디를 입력해 보고 맞으면 또 비밀번호를 입력해보는 경우를 방지하기 위해서입니다. // 불법사용자의 경우 회원아이디가 틀린지, 비밀번호가 틀린지를 알기까지는 많은 시간이 소요되기 때문입니다. -if (!$is_social_password_check && (!$mb['mb_id'] || !check_password($mb_password, $mb['mb_password'])) ) { +if (!$is_social_password_check && (!$mb['mb_id'] || !login_password_check($mb, $mb_password, $mb['mb_password'])) ) { alert('가입된 회원아이디가 아니거나 비밀번호가 틀립니다.\\n비밀번호는 대소문자를 구분합니다.'); } diff --git a/common.php b/common.php index c3b9d3dcd..df742129b 100644 --- a/common.php +++ b/common.php @@ -145,7 +145,7 @@ if (file_exists($dbconfig_file)) { // mysql connect resource $g5 배열에 저장 - 명랑폐인님 제안 $g5['connect_db'] = $connect_db; - sql_set_charset('utf8', $connect_db); + sql_set_charset(G5_DB_CHARSET, $connect_db); if(defined('G5_MYSQL_SET_MODE') && G5_MYSQL_SET_MODE) sql_query("SET SESSION sql_mode = ''"); if (defined('G5_TIMEZONE')) sql_query(" set time_zone = '".G5_TIMEZONE."'"); } else { diff --git a/config.php b/config.php index 16abee382..61463f1bb 100644 --- a/config.php +++ b/config.php @@ -32,6 +32,12 @@ define('G5_HTTPS_DOMAIN', ''); //디버깅 상수 define('G5_DEBUG', true); +// Set Databse table default engine is Databse default_storage_engine, If you want to use MyISAM or InnoDB, change to MyISAM or InnoDB. +define('G5_DB_ENGINE', ''); + +// Set Databse table default Charset +define('G5_DB_CHARSET', 'utf8mb4'); + /* www.sir.kr 과 sir.kr 도메인은 서로 다른 도메인으로 인식합니다. 쿠키를 공유하려면 .sir.kr 과 같이 입력하세요. 이곳에 입력이 없다면 www 붙은 도메인과 그렇지 않은 도메인은 쿠키를 공유하지 않으므로 로그인이 풀릴 수 있습니다. @@ -175,7 +181,9 @@ define('G5_SMTP_PORT', '25'); // 암호화 함수 지정 // 사이트 운영 중 설정을 변경하면 로그인이 안되는 등의 문제가 발생합니다. -define('G5_STRING_ENCRYPT_FUNCTION', 'sql_password'); +// 5.4 버전 이전에는 sql_password 이 사용됨, 5.4 버전부터 기본이 create_hash 로 변경 +define('G5_STRING_ENCRYPT_FUNCTION', 'create_hash'); +define('G5_MYSQL_PASSWORD_LENGTH', 41); // mysql password length 41, old_password 의 경우에는 16 // SQL 에러를 표시할 것인지 지정 // 에러를 표시하려면 TRUE 로 변경 diff --git a/install/gnuboard5.sql b/install/gnuboard5.sql index d8e65347f..4e1755264 100644 --- a/install/gnuboard5.sql +++ b/install/gnuboard5.sql @@ -186,10 +186,10 @@ CREATE TABLE IF NOT EXISTS `g5_board_new` ( DROP TABLE IF EXISTS `g5_config`; CREATE TABLE IF NOT EXISTS `g5_config` ( `cf_title` varchar(255) NOT NULL DEFAULT '', - `cf_theme` varchar(255) NOT NULL DEFAULT '', - `cf_admin` varchar(255) NOT NULL DEFAULT '', - `cf_admin_email` varchar(255) NOT NULL DEFAULT '', - `cf_admin_email_name` varchar(255) NOT NULL DEFAULT '', + `cf_theme` varchar(100) NOT NULL DEFAULT '', + `cf_admin` varchar(100) NOT NULL DEFAULT '', + `cf_admin_email` varchar(100) NOT NULL DEFAULT '', + `cf_admin_email_name` varchar(100) NOT NULL DEFAULT '', `cf_add_script` text NOT NULL, `cf_use_point` tinyint(4) NOT NULL DEFAULT '0', `cf_point_term` int(11) NOT NULL DEFAULT '0', @@ -198,25 +198,26 @@ CREATE TABLE IF NOT EXISTS `g5_config` ( `cf_login_point` int(11) NOT NULL DEFAULT '0', `cf_cut_name` tinyint(4) NOT NULL DEFAULT '0', `cf_nick_modify` int(11) NOT NULL DEFAULT '0', - `cf_new_skin` varchar(255) NOT NULL DEFAULT '', + `cf_new_skin` varchar(50) NOT NULL DEFAULT '', `cf_new_rows` int(11) NOT NULL DEFAULT '0', - `cf_search_skin` varchar(255) NOT NULL DEFAULT '', - `cf_connect_skin` varchar(255) NOT NULL DEFAULT '', - `cf_faq_skin` varchar(255) NOT NULL DEFAULT '', + `cf_search_skin` varchar(50) NOT NULL DEFAULT '', + `cf_connect_skin` varchar(50) NOT NULL DEFAULT '', + `cf_faq_skin` varchar(50) NOT NULL DEFAULT '', `cf_read_point` int(11) NOT NULL DEFAULT '0', `cf_write_point` int(11) NOT NULL DEFAULT '0', `cf_comment_point` int(11) NOT NULL DEFAULT '0', `cf_download_point` int(11) NOT NULL DEFAULT '0', `cf_write_pages` int(11) NOT NULL DEFAULT '0', `cf_mobile_pages` int(11) NOT NULL DEFAULT '0', - `cf_link_target` varchar(255) NOT NULL DEFAULT '', + `cf_link_target` varchar(50) NOT NULL DEFAULT '', + `cf_bbs_rewrite` tinyint(4) NOT NULL DEFAULT '0', `cf_delay_sec` int(11) NOT NULL DEFAULT '0', `cf_filter` text NOT NULL, `cf_possible_ip` text NOT NULL, `cf_intercept_ip` text NOT NULL, `cf_analytics` text NOT NULL, `cf_add_meta` text NOT NULL, - `cf_member_skin` varchar(255) NOT NULL DEFAULT '', + `cf_member_skin` varchar(50) NOT NULL DEFAULT '', `cf_use_homepage` tinyint(4) NOT NULL DEFAULT '0', `cf_req_homepage` tinyint(4) NOT NULL DEFAULT '0', `cf_use_tel` tinyint(4) NOT NULL DEFAULT '0', @@ -272,44 +273,44 @@ CREATE TABLE IF NOT EXISTS `g5_config` ( `cf_privacy` text NOT NULL, `cf_open_modify` int(11) NOT NULL DEFAULT '0', `cf_memo_send_point` int(11) NOT NULL DEFAULT '0', - `cf_mobile_new_skin` varchar(255) NOT NULL DEFAULT '', - `cf_mobile_search_skin` varchar(255) NOT NULL DEFAULT '', - `cf_mobile_connect_skin` varchar(255) NOT NULL DEFAULT '', - `cf_mobile_faq_skin` varchar(255) NOT NULL DEFAULT '', - `cf_mobile_member_skin` varchar(255) NOT NULL DEFAULT '', + `cf_mobile_new_skin` varchar(50) NOT NULL DEFAULT '', + `cf_mobile_search_skin` varchar(50) NOT NULL DEFAULT '', + `cf_mobile_connect_skin` varchar(50) NOT NULL DEFAULT '', + `cf_mobile_faq_skin` varchar(50) NOT NULL DEFAULT '', + `cf_mobile_member_skin` varchar(50) NOT NULL DEFAULT '', `cf_captcha_mp3` varchar(255) NOT NULL DEFAULT '', - `cf_editor` varchar(255) NOT NULL DEFAULT '', + `cf_editor` varchar(50) NOT NULL DEFAULT '', `cf_cert_use` tinyint(4) NOT NULL DEFAULT '0', `cf_cert_ipin` varchar(255) NOT NULL DEFAULT '', `cf_cert_hp` varchar(255) NOT NULL DEFAULT '', `cf_cert_kcb_cd` varchar(255) NOT NULL DEFAULT '', `cf_cert_kcp_cd` varchar(255) NOT NULL DEFAULT '', - `cf_lg_mid` varchar(255) NOT NULL DEFAULT '', - `cf_lg_mert_key` varchar(255) NOT NULL DEFAULT '', + `cf_lg_mid` varchar(100) NOT NULL DEFAULT '', + `cf_lg_mert_key` varchar(100) NOT NULL DEFAULT '', `cf_cert_limit` int(11) NOT NULL DEFAULT '0', `cf_cert_req` tinyint(4) NOT NULL DEFAULT '0', `cf_sms_use` varchar(255) NOT NULL DEFAULT '', `cf_sms_type` varchar(10) NOT NULL DEFAULT '', `cf_icode_id` varchar(255) NOT NULL DEFAULT '', `cf_icode_pw` varchar(255) NOT NULL DEFAULT '', - `cf_icode_server_ip` varchar(255) NOT NULL DEFAULT '', - `cf_icode_server_port` varchar(255) NOT NULL DEFAULT '', - `cf_googl_shorturl_apikey` varchar(255) NOT NULL DEFAULT '', + `cf_icode_server_ip` varchar(50) NOT NULL DEFAULT '', + `cf_icode_server_port` varchar(50) NOT NULL DEFAULT '', + `cf_googl_shorturl_apikey` varchar(50) NOT NULL DEFAULT '', `cf_social_login_use` tinyint(4) NOT NULL DEFAULT '0', `cf_social_servicelist` varchar(255) NOT NULL DEFAULT '', `cf_payco_clientid` varchar(100) NOT NULL DEFAULT '', `cf_payco_secret` varchar(100) NOT NULL DEFAULT '', - `cf_facebook_appid` varchar(255) NOT NULL, - `cf_facebook_secret` varchar(255) NOT NULL, - `cf_twitter_key` varchar(255) NOT NULL, - `cf_twitter_secret` varchar(255) NOT NULL, + `cf_facebook_appid` varchar(100) NOT NULL, + `cf_facebook_secret` varchar(100) NOT NULL, + `cf_twitter_key` varchar(100) NOT NULL, + `cf_twitter_secret` varchar(100) NOT NULL, `cf_google_clientid` varchar(100) NOT NULL DEFAULT '', `cf_google_secret` varchar(100) NOT NULL DEFAULT '', `cf_naver_clientid` varchar(100) NOT NULL DEFAULT '', `cf_naver_secret` varchar(100) NOT NULL DEFAULT '', `cf_kakao_rest_key` varchar(100) NOT NULL DEFAULT '', `cf_kakao_client_secret` varchar(100) NOT NULL DEFAULT '', - `cf_kakao_js_apikey` varchar(255) NOT NULL, + `cf_kakao_js_apikey` varchar(100) NOT NULL, `cf_captcha` varchar(100) NOT NULL DEFAULT '', `cf_recaptcha_site_key` varchar(100) NOT NULL DEFAULT '', `cf_recaptcha_secret_key` varchar(100) NOT NULL DEFAULT '', @@ -416,7 +417,7 @@ CREATE TABLE IF NOT EXISTS `g5_group_member` ( DROP TABLE IF EXISTS `g5_login`; CREATE TABLE IF NOT EXISTS `g5_login` ( - `lo_ip` varchar(255) NOT NULL default '', + `lo_ip` varchar(100) NOT NULL default '', `mb_id` varchar(20) NOT NULL default '', `lo_datetime` datetime NOT NULL default '0000-00-00 00:00:00', `lo_location` text NOT NULL, @@ -645,11 +646,14 @@ CREATE TABLE IF NOT EXISTS `g5_scrap` ( DROP TABLE IF EXISTS `g5_visit`; CREATE TABLE IF NOT EXISTS `g5_visit` ( `vi_id` int(11) NOT NULL default '0', - `vi_ip` varchar(255) NOT NULL default '', + `vi_ip` varchar(100) NOT NULL default '', `vi_date` date NOT NULL default '0000-00-00', `vi_time` time NOT NULL default '00:00:00', `vi_referer` text NOT NULL, - `vi_agent` varchar(255) NOT NULL default '', + `vi_agent` varchar(200) NOT NULL default '', + `vi_browser` varchar(255) NOT NULL DEFAULT '', + `vi_os` varchar(255) NOT NULL DEFAULT '', + `vi_device` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`vi_id`), UNIQUE KEY `index1` (`vi_ip`,`vi_date`), KEY `index2` (`vi_date`) diff --git a/install/install_db.php b/install/install_db.php index 4f359bd12..93bfcde1c 100644 --- a/install/install_db.php +++ b/install/install_db.php @@ -62,7 +62,7 @@ if (!$select_db) { } $mysql_set_mode = 'false'; -sql_set_charset('utf8', $dblink); +sql_set_charset(G5_DB_CHARSET, $dblink); $result = sql_query(" SELECT @@sql_mode as mode ", true, $dblink); $row = sql_fetch_array($result); if($row['mode']) { @@ -87,7 +87,10 @@ $file = preg_replace('/`g5_([^`]+`)/', '`'.$table_prefix.'$1', $file); $f = explode(';', $file); for ($i=0; $i @@ -181,7 +184,7 @@ sql_query($sql, true, $dblink); // 관리자 회원가입 $sql = " insert into `{$table_prefix}member` set mb_id = '$admin_id', - mb_password = PASSWORD('$admin_pass'), + mb_password = '".get_encrypt_string($admin_pass)."', mb_name = '$admin_name', mb_nick = '$admin_name', mb_email = '$admin_email', @@ -284,6 +287,8 @@ for ($i=0; $i= PBKDF2_COMPAT_ITERATIONS) { + return false; + } else { + return true; + } +} + +// Compares two strings $a and $b in length-constant time. + +function slow_equals($a, $b) +{ + $diff = strlen($a) ^ strlen($b); + for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) { + $diff |= ord($a[$i]) ^ ord($b[$i]); + } + return $diff === 0; +} + +// PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt +// Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt +// This implementation of PBKDF2 was originally created by https://defuse.ca +// With improvements by http://www.variations-of-shadow.com + +function pbkdf2_default($algo, $password, $salt, $count, $key_length) +{ + // Sanity check. + + if ($count <= 0 || $key_length <= 0) { + trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR); + } + + // Check if we should use the fallback function. + + if (!$algo) return pbkdf2_fallback($password, $salt, $count, $key_length); + + // Check if the selected algorithm is available. + + $algo = strtolower($algo); + if (!function_exists('hash_algos') || !in_array($algo, hash_algos())) { + if ($algo === 'sha1') { + return pbkdf2_fallback($password, $salt, $count, $key_length); + } else { + trigger_error('PBKDF2 ERROR: Hash algorithm not supported.', E_USER_ERROR); + } + } + + // Use built-in function if available. + + if (function_exists('hash_pbkdf2')) { + return hash_pbkdf2($algo, $password, $salt, $count, $key_length, true); + } + + // Count the blocks. + + $hash_length = strlen(hash($algo, '', true)); + $block_count = ceil($key_length / $hash_length); + + // Hash it! + + $output = ''; + for ($i = 1; $i <= $block_count; $i++) { + $last = $salt . pack('N', $i); // $i encoded as 4 bytes, big endian. + $last = $xorsum = hash_hmac($algo, $last, $password, true); // first iteration. + for ($j = 1; $j < $count; $j++) { // The other $count - 1 iterations. + $xorsum ^= ($last = hash_hmac($algo, $last, $password, true)); + } + $output .= $xorsum; + } + + // Truncate and return. + + return substr($output, 0, $key_length); +} + +// Fallback function using sha1() and a pure-PHP implementation of HMAC. +// The result is identical to the default function when used with SHA-1. +// But it is approximately 1.6x slower than the hash_hmac() function of PHP 5.1.2+, +// And approximately 2.3x slower than the hash_pbkdf2() function of PHP 5.5+. + +function pbkdf2_fallback($password, $salt, $count, $key_length) +{ + // Count the blocks. + + $hash_length = 20; + $block_count = ceil($key_length / $hash_length); + + // Prepare the HMAC key and padding. + + if (strlen($password) > 64) { + $password = str_pad(sha1($password, true), 64, chr(0)); + } else { + $password = str_pad($password, 64, chr(0)); + } + + $opad = str_repeat(chr(0x5C), 64) ^ $password; + $ipad = str_repeat(chr(0x36), 64) ^ $password; + + // Hash it! + + $output = ''; + for ($i = 1; $i <= $block_count; $i++) { + $last = $salt . pack('N', $i); + $xorsum = $last = pack('H*', sha1($opad . pack('H*', sha1($ipad . $last)))); + for ($j = 1; $j < $count; $j++) { + $last = pack('H*', sha1($opad . pack('H*', sha1($ipad . $last)))); + $xorsum ^= $last; + } + $output .= $xorsum; + } + + // Truncate and return. + + return substr($output, 0, $key_length); +} diff --git a/lib/uri.lib.php b/lib/uri.lib.php index 44de67572..42ac7aa66 100644 --- a/lib/uri.lib.php +++ b/lib/uri.lib.php @@ -257,28 +257,31 @@ function exist_seo_title_recursive($type, $seo_title, $write_table, $sql_id=0){ return exist_seo_title_recursive($type, $seo_title, $write_table, $sql_id); } -function seo_title_update($write_table, $wr_id, $type='bbs'){ +function seo_title_update($db_table, $pk_id, $type='bbs'){ global $g5; + $pk_id = (int) $pk_id; + if( $type === 'bbs' ){ - $sql = "select wr_seo_title FROM {$write_table} WHERE wr_seo_title = '".sql_real_escape_string($seo_title)."' AND wr_id <> '$sql_id' limit 1"; - $row = sql_fetch($sql); - - echo $sql; - - $exists_title = $row['wr_seo_title']; + $write = get_write($db_table, $pk_id, true); + if( ! $write['wr_seo_title'] && $co['wr_subject'] ){ + $wr_seo_title = exist_seo_title_recursive('bbs', generate_seo_title($write['wr_subject']), $db_table, $pk_id); + $sql = " update `{$db_table}` set wr_seo_title = '{$wr_seo_title}' where wr_id = '{$pk_id}' "; + sql_query($sql); + } } else if ( $type === 'content' ){ - $sql = "select co_seo_title FROM {$write_table} WHERE co_seo_title = '".sql_real_escape_string($seo_title)."' AND co_id <> '$sql_id' limit 1"; - $row = sql_fetch($sql); - - $exists_title = $row['co_seo_title']; + $co = get_content_db($pk_id, true); + if( ! $co['co_seo_title'] && $co['co_subject'] ){ + $co_seo_title = exist_seo_title_recursive('content', generate_seo_title($co['co_subject']), $db_table, $pk_id); + $sql = " update `{$db_table}` set co_seo_title = '{$co_seo_title}' where co_id = '{$pk_id}' "; + sql_query($sql); + } } - } function get_nginx_conf_rules($return_string=false){