forked from gnuboard/g4dtd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.php
502 lines (419 loc) · 20.7 KB
/
common.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
<?php
/*******************************************************************************
** 공통 변수, 상수, 코드
*******************************************************************************/
error_reporting(E_ALL ^ E_NOTICE);
// 보안설정이나 프레임이 달라도 쿠키가 통하도록 설정
header('P3P: CP="ALL CURa ADMa DEVa TAIa OUR BUS IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC OTC"');
if(!isset($set_time_limit)) $set_time_limit = 0;
@set_time_limit($set_time_limit);
// 짧은 환경변수를 지원하지 않는다면
if(isset($HTTP_POST_VARS) && !isset($_POST)) {
$_POST = &$HTTP_POST_VARS;
$_GET = &$HTTP_GET_VARS;
$_SERVER = &$HTTP_SERVER_VARS;
$_COOKIE = &$HTTP_COOKIE_VARS;
$_ENV = &$HTTP_ENV_VARS;
$_FILES = &$HTTP_POST_FILES;
if(!isset($_SESSION)) $_SESSION = &$HTTP_SESSION_VARS;
}
//
// phpBB2 참고
// php.ini 의 magic_quotes_gpc 값이 FALSE 인 경우 addslashes() 적용
// SQL Injection 등으로 부터 보호
//
if(!get_magic_quotes_gpc()) {
if(is_array($_GET)) {
while(list($k, $v) = each($_GET)) {
if(is_array($_GET[$k])) {
while(list($k2, $v2) = each($_GET[$k])) {
$_GET[$k][$k2] = addslashes($v2);
}
@reset($_GET[$k]);
} else {
$_GET[$k] = addslashes($v);
}
}
@reset($_GET);
}
if(is_array($_POST)) {
while(list($k, $v) = each($_POST)) {
if(is_array($_POST[$k])) {
while(list($k2, $v2) = each($_POST[$k])) {
$_POST[$k][$k2] = addslashes($v2);
}
@reset($_POST[$k]);
} else {
$_POST[$k] = addslashes($v);
}
}
@reset($_POST);
}
if(is_array($_COOKIE)) {
while(list($k, $v) = each($_COOKIE)) {
if(is_array($_COOKIE[$k])) {
while(list($k2, $v2) = each($_COOKIE[$k])) {
$_COOKIE[$k][$k2] = addslashes($v2);
}
@reset($_COOKIE[$k]);
} else {
$_COOKIE[$k] = addslashes($v);
}
}
@reset($_COOKIE);
}
}
if ($_GET['g4_path'] || $_POST['g4_path'] || $_COOKIE['g4_path']) {
unset($_GET['g4_path']);
unset($_POST['g4_path']);
unset($_COOKIE['g4_path']);
unset($g4_path);
}
//======================================================================================================================
// XSS(Cross Site Scripting) 공격에 의한 데이터 검증 및 차단
//----------------------------------------------------------------------------------------------------------------------
function xss_clean($data) {
// If its empty there is no point cleaning it :\
if(empty($data)) return $data;
// Recursive loop for arrays
if(is_array($data)) {
foreach($data as $key => $value) {
$data[$key] = xss_clean($value);
}
return $data;
}
// http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php
// +----------------------------------------------------------------------+
// | Copyright (c) 2001-2006 Bitflux GmbH |
// +----------------------------------------------------------------------+
// | Licensed under the Apache License, Version 2.0 (the "License"); |
// | you may not use this file except in compliance with the License. |
// | You may obtain a copy of the License at |
// | http://www.apache.org/licenses/LICENSE-2.0 |
// | Unless required by applicable law or agreed to in writing, software |
// | distributed under the License is distributed on an "AS IS" BASIS, |
// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
// | implied. See the License for the specific language governing |
// | permissions and limitations under the License. |
// +----------------------------------------------------------------------+
// | Author: Christian Stocker <[email protected]> |
// +----------------------------------------------------------------------+
// Fix &entity\n;
$data = str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $data);
$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/', '$1;', $data);
$data = preg_replace('/(&#x*[0-9A-F]+);*/i', '$1;', $data);
if(function_exists("html_entity_decode")) {
$data = html_entity_decode($data);
} else {
$trans_tbl = get_html_translation_table(HTML_ENTITIES);
$trans_tbl = array_flip($trans_tbl);
$data = strtr($data, $trans_tbl);
}
// Remove any attribute starting with "on" or xmlns
$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#i', '$1>', $data);
// Remove javascript: and vbscript: protocols
$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#i', '$1=$2nojavascript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#i', '$1=$2novbscript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#', '$1=$2nomozbinding...', $data);
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#i', '$1>', $data);
// Remove namespaced elements (we do not need them)
$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
do {
// Remove really unwanted tags
$old_data = $data;
$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
} while ($old_data !== $data);
return $data;
}
$_GET = xss_clean($_GET);
//======================================================================================================================
//======================================================================================================================
// extract($_GET); 명령으로 인해 page.php?_POST[var1]=data1와 같은 코드가 _POST 변수로 사용되는 것을 막음
// 081029 : letsgolee 님께서 도움 주셨습니다.
//----------------------------------------------------------------------------------------------------------------------
$ext_arr = array ('PHP_SELF', '_ENV', '_GET', '_POST', '_FILES', '_SERVER', '_COOKIE', '_SESSION', '_REQUEST',
'HTTP_ENV_VARS', 'HTTP_GET_VARS', 'HTTP_POST_VARS', 'HTTP_POST_FILES', 'HTTP_SERVER_VARS',
'HTTP_COOKIE_VARS', 'HTTP_SESSION_VARS', 'GLOBALS');
$ext_cnt = count($ext_arr);
for($i = 0; $i < $ext_cnt; $i++) {
// GET 으로 선언된 전역변수가 있다면 unset() 시킴
if (isset($_GET[$ext_arr[$i]])) unset($_GET[$ext_arr[$i]]);
}
//======================================================================================================================
// PHP 4.1.0 부터 지원됨
// php.ini 의 register_globals=off 일 경우
@extract($_GET);
@extract($_POST);
@extract($_SERVER);
// 완두콩님이 알려주신 보안관련 오류 수정
// $member 에 값을 직접 넘길 수 있음
$config = array();
$member = array();
$board = array();
$group = array();
$g4 = array();
// index.php 가 있는곳의 상대경로
// php 인젝션 ( 임의로 변수조작으로 인한 리모트공격) 취약점에 대비한 코드
// prosper 님께서 알려주셨습니다.
if(!$g4_path || preg_match("/:\/\//", $g4_path)) {
die("<meta http-equiv='content-type' content='text/html; charset=$g4[charset]'><script type='text/javascript'> alert('잘못된 방법으로 변수가 정의되었습니다.'); </script>");
}
//if (!$g4_path) $g4_path = ".";
$g4['path'] = $g4_path;
// 경로의 오류를 없애기 위해 $g4_path 변수는 해제
unset($g4_path);
include_once($g4['path'].'/lib/constant.php'); // 상수 정의
include_once($g4['path'].'/config.php'); // 설정 파일
include_once($g4['path'].'/lib/common.lib.php'); // 공통 라이브러리
// config.php 가 있는곳의 웹경로
if(!$g4['url']) {
$g4['url'] = 'http://' . $_SERVER['HTTP_HOST'];
$dir = dirname($_SERVER["PHP_SELF"]);
if(!file_exists('config.php')) $dir = dirname($dir);
$cnt = substr_count($g4['path'], "..");
for($i = 2; $i <= $cnt; $i++) {
$dir = dirname($dir);
}
$g4['url'] .= $dir;
}
// \ 를 / 롤 변경
$g4['url'] = strtr($g4['url'], "\\", "/");
// url 의 끝에 있는 / 를 삭제한다.
$g4['url'] = preg_replace("/\/$/", "", $g4['url']);
// _COMMON_SIMPLE_ 상수가 정의되어있지 않으면 디비와 세션을 모두 사용
if(!defined('_COMMON_SIMPLE_')) {
//==============================================================================
// 공통
//==============================================================================
$dirname = dirname(__FILE__).'/';
$dbconfig_file = 'data/dbconfig.php';
if(file_exists($g4['path'].'/'.$dbconfig_file)) {
//if (is_dir("$g4[path]/install")) die("<meta http-equiv='content-type' content='text/html; charset=$g4[charset]'><script type='text/javascript'> alert('install 디렉토리를 삭제하여야 정상 실행됩니다.'); </script>");
include_once($g4['path'].'/'.$dbconfig_file);
$connect_db = sql_connect($mysql_host, $mysql_user, $mysql_password);
$select_db = sql_select_db($mysql_db, $connect_db);
if(!$select_db) {
die("<meta http-equiv='content-type' content='text/html; charset=$g4[charset]'><script type='text/javascript'> alert('DB 접속 오류'); </script>");
}
} else {
echo "<meta http-equiv='content-type' content='text/html; charset=$g4[charset]'>";
echo <<<HEREDOC
<script type="text/javascript">
alert("DB 설정 파일이 존재하지 않습니다.\\n\\n프로그램 설치 후 실행하시기 바랍니다.");
location.href = "./install/";
</script>
HEREDOC;
exit;
}
unset($my); // DB 설정값을 클리어 해줍니다.
//print_r2($GLOBALS);
//-------------------------------------------
// SESSION 설정
//-------------------------------------------
ini_set('session.use_trans_sid', 0); // PHPSESSID를 자동으로 넘기지 않음
ini_set('url_rewriter.tags', ''); // 링크에 PHPSESSID가 따라다니는것을 무력화함 (해뜰녘님께서 알려주셨습니다.)
session_save_path($g4['session_path']);
if(isset($SESSION_CACHE_LIMITER)) {
@session_cache_limiter($SESSION_CACHE_LIMITER);
} else {
@session_cache_limiter('no-cache, must-revalidate');
}
//==============================================================================
// 공용 변수
//==============================================================================
// 기본환경설정
// 기본적으로 사용하는 필드만 얻은 후 상황에 따라 필드를 추가로 얻음
if(!defined('_NO_CONFIG_')) {
$config = sql_fetch(" select * from $g4[config_table] ");
}
ini_set('session.cache_expire', 180); // 세션 캐쉬 보관시간 (분)
ini_set('session.gc_maxlifetime', 10800); // session data의 garbage collection 존재 기간을 지정 (초)
ini_set('session.gc_probability', 1); // session.gc_probability는 session.gc_divisor와 연계하여 gc(쓰레기 수거) 루틴의 시작 확률을 관리합니다. 기본값은 1입니다. 자세한 내용은 session.gc_divisor를 참고하십시오.
ini_set('session.gc_divisor', 100); // session.gc_divisor는 session.gc_probability와 결합하여 각 세션 초기화 시에 gc(쓰레기 수거) 프로세스를 시작할 확률을 정의합니다. 확률은 gc_probability/gc_divisor를 사용하여 계산합니다. 즉, 1/100은 각 요청시에 GC 프로세스를 시작할 확률이 1%입니다. session.gc_divisor의 기본값은 100입니다.
session_set_cookie_params(0, '/');
ini_set('session.cookie_domain', $g4['cookie_domain']);
@session_start();
/*
// 081022 : CSRF 방지를 위해 코드를 작성했으나 효과가 없어 주석처리 함
if (strpos($_SERVER[PHP_SELF], $g4['admin']) === false)
set_session("ss_admin", false);
*/
// 4.00.03 : [보안관련] PHPSESSID 가 틀리면 로그아웃한다.
if($_REQUEST['PHPSESSID'] && $_REQUEST['PHPSESSID'] != session_id()) {
goto_url("{$g4['bbs_path']}/logout.php");
}
// QUERY_STRING
$qstr = "";
if (isset($sca)) {
$sca = mysql_real_escape_string($sca);
$qstr .= '&sca=' . urlencode($sca);
}
if (isset($sfl)) {
$sfl = mysql_real_escape_string($sfl);
$qstr .= '&sfl=' . urlencode($sfl); // search field (검색 필드)
}
if (isset($stx)) { // search text (검색어)
$stx = mysql_real_escape_string($stx);
$qstr .= '&stx=' . urlencode($stx);
}
if (isset($sst)) {
$sst = mysql_real_escape_string($sst);
$qstr .= '&sst=' . urlencode($sst); // search sort (검색 정렬 필드)
}
if(isset($sod)) { // search order (검색 오름, 내림차순)
$sod = preg_match("/^(asc|desc)$/i", $sod) ? $sod : "";
$qstr .= '&sod=' . urlencode($sod);
}
if(isset($sop)) { // search operator (검색 or, and 오퍼레이터)
$sop = preg_match("/^(or|and)$/i", $sop) ? $sop : "";
$qstr .= '&sop=' . urlencode($sop);
}
if(isset($spt)) { // search part (검색 파트[구간])
$spt = (int)$spt;
$qstr .= '&spt=' . urlencode($spt);
}
if(isset($page)) { // 리스트 페이지
$page = (int)$page;
$qstr .= '&page=' . urlencode($page);
}
if($wr_id) {
$wr_id = (int)$wr_id;
}
if($bo_table) {
$bo_table = preg_match("/^[a-zA-Z0-9_]+$/", $bo_table) ? $bo_table : "";
}
// URL ENCODING
if(isset($url)) {
$urlencode = urlencode($url);
} else {
// 2008.01.25 Cross Site Scripting 때문에 수정
//$urlencode = $_SERVER['REQUEST_URI'];
$urlencode = urlencode($_SERVER['REQUEST_URI']);
}
//===================================
// 자동로그인 부분에서 첫로그인에 포인트 부여하던것을 로그인중일때로 변경하면서 코드도 대폭 수정하였습니다.
if($_SESSION['ss_mb_id']) {
// 로그인중이라면
$member = get_member($_SESSION['ss_mb_id']);
// 오늘 처음 로그인 이라면
if(substr($member['mb_today_login'], 0, 10) != $g4['time_ymd']) {
// 첫 로그인 포인트 지급
insert_point($member['mb_id'], $config['cf_login_point'], "{$g4['time_ymd']} 첫로그인", "@login", $member['mb_id'], $g4['time_ymd']);
// 오늘의 로그인이 될 수도 있으며 마지막 로그인일 수도 있음
// 해당 회원의 접근일시와 IP 를 저장
$sql = " update {$g4['member_table']} set mb_today_login = '{$g4['time_ymdhis']}', mb_login_ip = '{$_SERVER['REMOTE_ADDR']}' where mb_id = '{$member['mb_id']}' ";
sql_query($sql);
}
} else {
// 자동로그인 ---------------------------------------
// 회원아이디가 쿠키에 저장되어 있다면 (3.27)
if($tmp_mb_id = get_cookie('ck_mb_id')) {
$tmp_mb_id = substr(preg_replace("/[^a-zA-Z0-9_]*/", "", $tmp_mb_id), 0, 20);
// 최고관리자는 자동로그인 금지
if($tmp_mb_id != $config['cf_admin']) {
$sql = " select mb_password, mb_intercept_date, mb_leave_date, mb_email_certify
from {$g4['member_table']} where mb_id = '$tmp_mb_id' ";
$row = sql_fetch($sql);
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . $row['mb_password']);
// 쿠키에 저장된 키와 같다면
$tmp_key = get_cookie("ck_auto");
if($tmp_key == $key && $tmp_key) {
// 차단, 탈퇴가 아니고 메일인증이 사용이면서 인증을 받았다면
if($row['mb_intercept_date'] == "" && $row['mb_leave_date'] == "" && (!$config['cf_use_email_certify'] || preg_match('/[1-9]/', $row['mb_email_certify']))) {
// 세션에 회원아이디를 저장하여 로그인으로 간주
set_session('ss_mb_id', $tmp_mb_id);
// 페이지를 재실행
echo '<script type="text/javascript"> window.location.reload(); </script>';
exit;
}
}
// $row 배열변수 해제
unset($row);
}
}
// 자동로그인 end ---------------------------------------
}
// 첫방문 쿠키
// 1년간 저장
if(!get_cookie("ck_first_call")) set_cookie('ck_first_call', $g4['server_time'], 86400 * 365);
if(!get_cookie('ck_first_referer')) set_cookie('ck_first_referer', $_SERVER['HTTP_REFERER'], 86400 * 365);
// 회원이 아니라면 권한을 방문객 권한으로 함
if(!($member['mb_id'])) {
$member['mb_level'] = 1;
} else {
$member['mb_dir'] = substr($member['mb_id'], 0, 2);
}
//$member['mb_level_title'] = $g4['member_level'][$member['mb_level']]; // 권한명
$write_table = "";
if(isset($bo_table)) {
$board = sql_fetch(" select * from {$g4['board_table']} where bo_table = '$bo_table' ");
if($board['bo_table']) {
$gr_id = $board['gr_id'];
$write_table = $g4['write_prefix'] . $bo_table; // 게시판 테이블 전체이름
//$comment_table = $g4['write_prefix'] . $bo_table . $g4['comment_suffix']; // 코멘트 테이블 전체이름
if($wr_id) {
$write = sql_fetch(" select * from $write_table where wr_id = '$wr_id' ");
}
}
}
if(isset($gr_id)) {
$group = sql_fetch(" select * from {$g4['group_table']} where gr_id = '$gr_id' ");
}
// 회원, 비회원 구분
$is_member = $is_guest = false;
if($member['mb_id']) {
$is_member = true;
} else {
$is_guest = true;
}
$is_admin = is_admin($member['mb_id']);
if($is_admin != 'super') {
// 접근가능 IP
$cf_possible_ip = trim($config['cf_possible_ip']);
if($cf_possible_ip) {
$is_possible_ip = false;
$pattern = explode("\n", $cf_possible_ip);
for($i = 0; $i < count($pattern); $i++) {
$pattern[$i] = trim($pattern[$i]);
if(empty($pattern[$i])) continue;
//$pat = "/({$pattern[$i]})/";
$pattern[$i] = str_replace(".", "\.", $pattern[$i]);
$pat = "/^{$pattern[$i]}/";
$is_possible_ip = preg_match($pat, $_SERVER['REMOTE_ADDR']);
if($is_possible_ip) break;
}
if(!$is_possible_ip) die ('접근이 가능하지 않습니다.');
}
// 접근차단 IP
$is_intercept_ip = false;
$pattern = explode("\n", trim($config['cf_intercept_ip']));
for($i = 0; $i < count($pattern); $i++) {
$pattern[$i] = trim($pattern[$i]);
if(empty($pattern[$i])) continue;
$pattern[$i] = str_replace(".", "\.", $pattern[$i]);
$pat = "/^{$pattern[$i]}/";
$is_intercept_ip = preg_match($pat, $_SERVER['REMOTE_ADDR']);
if($is_intercept_ip) die ('접근 불가합니다.');
}
}
// 방문자수의 접속을 남김
include_once($g4['bbs_path'].'/visit_insert.inc.php');
}
// 스킨경로
$board_skin_path = '';
if(isset($board['bo_skin'])) {
// 게시판 스킨 경로
$board_skin_path = "{$g4['path']}/skin/board/{$board['bo_skin']}";
}
// common.php 파일을 수정할 필요가 없도록 확장합니다.
$tmp = dir($g4['path'].'/extend');
while($entry = $tmp->read()) {
// php 파일만 include 함
if(preg_match("/(\.php)$/i", $entry)) {
include_once($g4['path']."/extend/$entry");
}
}
?>