2011년 1월 10일 월요일

sulinux 2.0 + APM + Zend + eaccelerator + nginx + mrtg

# 아래 작업에 대한 책임은 전적으로 본인에게 있습니다.

# nginx 는 정적서비스용입니다.

# mrtg 는 테스트가 필요합니다.

# Zend 는 php 5.2 버젼에 적용됩니다. 5.3는 아직 지원되지 않습니다.

# eaccelerator 에 대한 부분은 본인 필요에 따라 설치바랍니다.

# 기타 라이브러리는 본인이 설치해야 합니다.

 

 

#sulinux 2.0 설치후 작업
#sulinux 2.0 + APM + Zend + eaccelerator + nginx + mrtg

#시간 맞춤
rdate -s time.bora.net && /sbin/clock -w
ntpdate -b -s time.kriss.re.kr && /sbin/clock -w

crontab -e
*/30 * * * * rdate -s time.bora.net && /sbin/clock -w
*/30 * * * * ntpdate -b -s time.kriss.re.kr && /sbin/clock -w
/etc/init.d/crond restart

#yum 전체 업데이트
yum update -y

#한글 처리 UTF-8 -> EUC-KR
vi /etc/sysconfig/i18n
LANG="ko_KR.EUC-KR"
SUPPORTED="ko_KR.UTF-8:ko_KR:ko"
SYSFONT="latarcyrheb-sun16"

#APM 설치 Apache_2.2.16 + PHP_5.2.14 + MySQL_5.1.51
/root/bin/apmtools

#젠드설치
wget http://downloads.zend.com/optimizer/3.3.3/ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz
tar xvfz ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz
cd ZendOptimizer-3.3.3-linux-glibc23-i386
./install.sh
cd ..
rm -Rf ZendOptimizer-3.3.3-linux-glibc23-i386*

#eaccelerator 설치
wget http://bart.eaccelerator.net/source/0.9.6/eaccelerator-0.9.6-rc1.tar.bz2
tar xvfj eaccelerator-0.9.6-rc1.tar.bz2
cd eaccelerator-0.9.6-rc1
export PHP_PREFIX="/usr/local/php/"
$PHP_PREFIX/bin/phpize
./configure --enable-eaccelerator=shared --with-php-config=$PHP_PREFIX/bin/php-config
make
make install

#아래는 확인해둘것 extension_dir= 에 입력
Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/

mkdir /tmp/eaccelerator
chmod 0777 /tmp/eaccelerator
chown nobody:nobody /tmp/eaccelerator

vi /usr/local/php/lib/php.ini
#[Zend] ;반드시 Zend 전에 입력
extension_dir=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/
extension="eaccelerator.so"
eaccelerator.shm_size="32"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"
eaccelerator.allowed_admin_path="/usr/local/apache/htdocs"

/etc/init.d/httpd restart

#모듈 설치 확인
php -v
PHP 5.2.2 (cli) (built: Mar 29 2010 18:45:51)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
with eAccelerator v0.9.6-rc1, Copyright (c) 2004-2007 eAccelerator, by eAccelerator
with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies
with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies

#관리자 페이지 설정
vi control.php
$auth = true;
$user = "admin";
$pw = "tnghkrl";

cp control.php /usr/local/apache/htdocs/control.php

#설치파일 삭제
cd ..
rm -Rf eaccelerator-0.9.6-rc1*

#아파치 재실행
/etc/init.d/httpd restart

#nginx 설치
wget http://nginx.org/download/nginx-0.8.54.tar.gz
tar xvzf nginx-0.8.54.tar.gz
cd nginx-0.8.54
./configure --pid-path=/usr/local/nginx/logs/nginx.pid --sbin-path=/usr/local/sbin/nginx --with-md5=/usr/lib --with-sha1=/usr/lib --with-http_ssl_module --with-http_dav_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module
make
make install

vi /etc/rc.d/init.d/nginx

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /usr/local/nginx/conf/nginx.conf
# pidfile: /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"


lockfile=/var/lock/subsys/nginx

start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
echo -n $"Starting $prog: "
$nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}

stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}

restart() {
configtest || return $?
stop
start
}

reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}

force_reload() {
restart
}

configtest() {
$nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
status $prog
}

rh_status_q() {
rh_status >/dev/null 2>&1
}

case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac

chmod 750 /etc/rc.d/init.d/nginx

vi /usr/local/nginx/conf/nginx.conf

#CPU코어 갯수 * CPU 갯수
worker_processes  1;

#max_clients = worker_processes * worker_connections
events {
    worker_connections  1024;
}

# keepalive 설정
http {
    ...

    keepalive_timeout  5 5;
    keepalive_requests 5;

    ...

#서비스 포터 설정
    server {

        ...

        listen 5135;
 server_name localhost;

        location / {

            root    /usr/local/apache/htdocs;

            index    index.html index.htm, index.php;

            expires 24h;    

        }

        ...

    }
}

#이미지 서비스용 포트
setup -> 방화벽 설정 -> 사용자설정 -> 그외의 포트 -> 5135:tcp

/etc/init.d/iptables restart

cd ..
rm -Rf nginx-0.8.54*

#cacti 설치
wget http://www.cacti.net/downloads/cacti-0.8.7g.tar.gz
tar xvzf cacti-0.8.7g.tar.gz
cd cacti-0.8.7g

 


#mrtg
yum install net-snmp

vi /etc/snmp/snmpd.conf
com2sec network 192.168.163.135 public

group   notConfigGroup v2c           notConfigUser
group   rwgroup         v1      local
group   rwgroup         v2c     local
group   rwgroup         v1      network
group   rwgroup         v2c     network

view    all             included        .1      80
view    systemview      included        system
view    mib2            included        .iso.org.dod.internet.mgmt.mib-2 fc

access  rwgroup ""      any     noauth  exact   all     all     all
access  rogroup ""      any     noauth  exact   systemview      none    none

/etc/init.d/snmpd restart

wget http://oss.oetiker.ch/mrtg/pub/mrtg-2.17.0.tar.gz
tar xvzf mrtg-2.17.0.tar.gz
cd mrtg-2.17.0
./configure --prefix=/usr/local/mrtg/
make && make install

vi /root/mrtg.sh
#!/bin/sh
/usr/bin/cfgmaker --global 'WorkDir: /usr/local/apache/htdocs/' --global 'Language: korean' --global 'Options[_]: bits,growright' -output /usr/local/apache/htdocs/mrtg.cfg public@192.168.163.135
/usr/bin/indexmaker --title "mrtg.kantukan.co.kr" --output /usr/local/apache/htdocs/index.htm /usr/local/apache/htdocs/mrtg.cfg
/usr/bin/mrtg /usr/local/apache/htdocs/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok
chmod 700 mrtg.sh

*/5 * * * * su - root -c '/home/mrtg/public_html/mrtg.sh' >& mrtg.log

2010년 7월 14일 수요일

sulinux 1.5 + curl 7.21.0 + openssl

스마트폰 결제모듈 설치 관련 데이콤 xpay 크로스 플랫폼용

curl 설치

 

sulinux 1.5

 

yum update openssl

yum update openssl-devel

 

http://curl.haxx.se/ 에서 다운 혹은

 

wget http://curl.haxx.se/download/curl-7.21.0.tar.gz

tar xvzf curl-7.21.0.tar.gz

cd curl-7.21.0

./configure --without-libidn --with-openssl=/usr/bin/openssl -prefix=/usr/local/curl

(sulinux에는 libidn 이 없음.)

make

make install

 

php 재설치

 

기존 php가 5.2.2 였으나 5.2.1  로 다시 설치

/root/bin/apm/apm_phpupdate

--with-curl=/usr/local/curl --wth-ssl

 

옵션 추가

 

phpinfo 에서 curl 버젼과 configure command 확인

2010년 6월 23일 수요일

이미지 슬라이더 nivo-slider

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> nivo-slider </TITLE>
</HEAD>
<link rel="stylesheet" href="./css/nivo-slider.css" type="text/css" media="screen" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="./js/jquery.nivo.slider.js" type="text/javascript"></script>
<SCRIPT LANGUAGE="JavaScript">
<!--
$(window).load(function() {
 $('#slider').nivoSlider({
  effect:'sliceDownRight', //Specify sets like: "sliceDownRight","sliceDownLeft","sliceUpRight","sliceUpLeft","sliceUpDown","sliceUpDownLeft","fold","fade"
  slices:15,
  animSpeed:500,
  pauseTime:3000,
  startSlide:0, //Set starting Slide (0 index)
  directionNav:true, //Next & Prev
  directionNavHide:false, //Only show on hover
  controlNav:false, //1,2,3...
  controlNavThumbs:false, //Use thumbnails for Control Nav
  controlNavThumbsFromRel:false, //Use image rel for thumbs
  controlNavThumbsSearch: '.jpg', //Replace this with...
  controlNavThumbsReplace: '_thumb.jpg', //...this in thumb Image src
  keyboardNav:false, //Use left & right arrows
  pauseOnHover:true, //Stop animation while hovering
  manualAdvance:false, //Force manual transitions
  captionOpacity:0.8, //Universal caption opacity
  beforeChange: function(){},
  afterChange: function(){},
  slideshowEnd: function(){} //Triggers after all slides have been shown
 });
});

//-->
</SCRIPT>
<BODY>
<div id="slider" style='width:743px'>
 <img src="01.jpg" alt="" />
 <img src="02.jpg" alt="" />
 <img src="03.jpg" alt="" />
 <img src="04.jpg" alt="" />
</div>
</BODY>
</HTML>

2010년 4월 2일 금요일

Zend 한번에 설치하기

apm 설치후 Zend 설치

 

#!/bin/bash
################################################################
# 제작환경 : SULinux 1.5 + ZendOptimizer-3.0.1         #
# 제작일 : 2009.03.25                         #
# 제작자 : 이창민                       #
# 이메일 : lcm790203@naver.com            #
# 주.) 개인적 사용의 목적으로 만들었습니다.                    #
# 필요하신분만 사용하시고 이용상의 오류는 책임질수 없습니다.   #
################################################################

wget http://downloads.zend.com/optimizer/3.3.3/ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz
tar xvfz ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz
cd ZendOptimizer-3.3.3-linux-glibc23-i386
./install.sh
cd ..
rm -Rf ZendOptimizer-3.3.3-linux-glibc23-i386*

 

위의 파일을 그대로 스크립트로 만들어도 되고 복사해서 작업하셔도 됩니다.

전 스크립트로 만들어서 사용합니다.

eaccelerator 설치

Zend 설치후 설치

 

# wget http://bart.eaccelerator.net/source/0.9.6/eaccelerator-0.9.6-rc1.tar.bz2
# tar xvfj eaccelerator-0.9.6-rc1.tar.bz2
# cd eaccelerator-0.9.6-rc1
# export PHP_PREFIX="/usr/local/php/"
# $PHP_PREFIX/bin/phpize
# ./configure --enable-eaccelerator=shared --with-php-config=$PHP_PREFIX/bin/php-config
# make
# make install

아래는 확인해둘것
Installing shared extensions:     /usr/local/php_5.2.2/lib/php/extensions/no-debug-non-zts-20060613/

# mkdir /tmp/eaccelerator
# chmod 0777 /tmp/eaccelerator
# chown nobody:nobody /tmp/eaccelerator

# vi /usr/local/php/lib/php.ini
[Zend] ;반드시 Zend 전에 입력
extension_dir=/usr/local/php_5.2.2/lib/php/extensions/no-debug-non-zts-20060613/
extension="eaccelerator.so"
eaccelerator.shm_size="32"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"
eaccelerator.allowed_admin_path="/home/kantukan/public_html/ybbs/shop/"

# /etc/init.d/httpd restart

모듈 설치 확인
# php -v
PHP 5.2.2 (cli) (built: Mar 29 2010 18:45:51)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
    with eAccelerator v0.9.6-rc1, Copyright (c) 2004-2007 eAccelerator, by eAccelerator
    with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies
    with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies

관리자 페이지 설정
# vi control.php
$user = "admin";
$pw = "tnghkrl";

# cp control.php /home/kantukan/public_html/ybbs/shop/control.php

웹페이지에서 확인

설치파일 삭제
# cd /
# rm -Rf /root/eaccelerator-0.9.6-rc1*

아파치 재실행
# /etc/init.d/httpd restart

2010년 1월 26일 화요일

테이블그리드 CSS로 효과내기

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<style>
.container {
 width: 100%;
 height: 300px;
 overflow: auto;
}

.HeaderFreezing {
 background-color: #e7e7e7;
 position:relative ;
 top: expression(this.offsetParent.scrollTop);
 z-index: 10;
}

.FooterFreezing {
 background-color: #e7e7e7;
 position: relative;
 bottom: expression((this.offsetParent.offsetWidth != this.offsetParent.clientWidth) ? (this.offsetParent.scrollHeight - (this.offsetParent.scrollTop + this.offsetParent.offsetHeight)) : 0);
 z-index: 20;
}

.td_class {
 background-color: #f9f9f9;
 text-align: center;
 padding: 5px;
}
</style>
 </HEAD>

<BODY>
<div class="container">
<table width=100% border=0 cellpadding=0 cellspacing=1 bgcolor="#E7E7E7">
 <tr class="HeaderFreezing">
  <td class="td_class">고정상단</td>
  <td class="td_class">고정상단</td>
  <td class="td_class">고정상단</td>
  <td class="td_class">고정상단</td>
  <td class="td_class">고정상단</td>
  <td class="td_class">고정상단</td>
 </tr>
 <? for($q=0;$q<100;$q++) { ?>
 <tr bgcolor="#ffffff">
  <td align=center><?=$q?></td>
  <td>내용</td>
  <td>내용</td>
  <td>내용</td>
  <td>내용</td>
  <td>내용</td>
 </tr>
 <? } ?>
 <tr class="FooterFreezing">
  <td class="td_class">하단고정</td>
  <td class="td_class">하단고정</td>
  <td class="td_class">하단고정</td>
  <td class="td_class">하단고정</td>
  <td class="td_class">하단고정</td>
  <td class="td_class">하단고정</td>
 </tr>
</table>
</div>
</BODY>
</HTML>

2009년 9월 11일 금요일

md5(), crypt(), password() 등의 문제점 및 로그인 암호화 보안

로그인에 관련된 보안얘기를 하려고 합니다.

password(); // mysql.
md5(); // php.
crypt(); // php.

뭐, 암호화에 관련된 함수들이 여러 가지 있겠지만 위 3가지 함수는 범용적으로 많이들 쓰고 있고
안정성이 검증된 함수들이죠.. 그리고 모두 복호화가 안되거나, 어려운 해쉬함수들입니다.

흔히 password() 로 암호화시킨 비밀번호... 원래의 값을 절대 알 수 없다고들 표현합니다......

절대 알 수 없다 ?
절대 알 수 없다 ?
절대 알 수 없다 ?

id = 'abcd'
pw = '4ed0bdda4ee8f6a5'

위 pw 원래의 값을 과연 절대 알 수 없을까요 ? 정말 그럴까요 ?


password() 뿐 아니라, md5(), crypt() 등 해쉬함수들이 있는데요....
지금부터 제가 생각하고 있는 바를 차근차근 얘기해 나가려고 합니다....

그다지 어려운얘기 아니고요,

누구나 알 수 있는 쉬운 얘기들뿐입니다..

( 제가 워낙 쉬운 것만 좋아해서 쉬운 것밖에는 모릅니다 ^^ )


--------------------------------------------------------------------------------------


가령,

사용자가 비밀번호를 '3204' 라고 입력한 것을  md5() 로 해쉬시키면

' 640258597cbc50037072712f964cf5d8 ' 라는 값이 나오게 되지요...

md5() 는 디코딩을 지원하지 않는 단방향성 해쉬함수이기에 위 문자열을 보고 원래 값 '3204'를
추출 할 수는 없을 것입니다.

나머지 password(), crypt() 들도 마찬가지죠.. 상당히 어려운 알고리즘을 통해 해쉬된 문자열이
나오면서 원래의 값을 알아낼 수는 없게 됩니다.

특히 crypt() 는 두 번째에 주어지는 salt 값에 따라  똑같은 패스워드를 해쉬해도 결과는
매번 틀리게 됩니다...

가령,

$password = '20930';
$savepw = crypt( $password, md5( time() ) );
이런식으로 하면

실행 할 때마다 94JrlBxXigCZU , 30K4887zrFHBw , 등의 틀린 결과를 나오게 합니다.

모두 대단한 함수들입죠 ~~


------------------------- 그런데, 취약점은 항상 있는 법 --------------------------------

아이디 해킹을 하기위한 몇 가지 조건들이 있기 마련이죠..
그중, 해킹에 의해 DB가 노출되었다고 칩니다......

DB 비번관리를 잘못하던지, 디렉토리파싱을 당하던지 여러 이유로 DB가 노출되었다고 치구요..

DB 내용에는 사용자 계정 정보가

id = 'abcd'
pw = '640258597cbc50037072712f964cf5d8'

위처럼 되있다고 치구요.....


비밀번호가 암호화 되어있으니, 과연 안전할까요 ?

그런데 위 문자열 패턴을 보면, md5 로 해쉬된 것을 쉽게 알 수 있습니다.
지금부터 md5() 함수를 이용해서 원래의 비번을 찾아보도록 하겠습니다.

<?
for( $pw = 0; $pw < 99999; $pw ++ ) {
       if( '640258597cbc50037072712f964cf5d8' == md5( $pw ) ) {
              echo "find ok : $pw ";
              break;
       }
}
// 출력 -> find ok : 3204
?>

간단하게 찾았습니다.



그러면, crypt() 는 안전 할까요 ??

아닙니다.. crypt() 역시 똑 같습니다..

노출된 DB 에.
id = 'abcd'
pw = '12FP8QJo.OCVg';

위 문자열 패턴을 보면, crypt() 로 해쉬된 것을 알 수 있습니다.
이것도 원래의 비번을 찾아보도록 하겠습니다.
<?
for( $i = 0; $i < 99999; $i ++ ) {
       if( '12FP8QJo.OCVg' == crypt( $i, '12FP8QJo.OCVg' ) ) {
              echo " find ok : $i ";
              break;
       }
}
// 출력 -> find ok : 20930
?>

이번에도 결과가 나와 버립니다.


하지만 실제 암호는 숫자만 쓰는 것이 아니고, 문자열을 섞어서 입력하겠지요?
그렇다고 못 찾는 건 아닙니다.
.....
.....
$pw = $chk.chr($i);
if( '640258597cbc50037072712f964cf5d8' == md5( $pw ) ) {
.....
.....
}
$i ++;
if( $i > 126 ) $chk = ( ord( $chk ) + 1 );
.....
.....

저런 식으로 숫자 대신 문자를 자동으로 대입하게 해서 돌아가게 만들면 된다는 것이죠....

수행시간이 오래 걸린 것입니다만,,
문자 하나당 유효값이 93 자 인가? 그러니, 비밀번호가 4글자만 되도
loop 를 93 * 93 * 93 * 93 = 74,805,201 번을 돌아야 할 것입니다...

문제는 요즘 컴퓨터 성능이 워낙 좋아져서, loop 도는 시간이 그리 오래 걸리지도 않고,
또, 단위별로 끊어서 몇 단계 나누어서 병렬로 돌리면 결과는 더욱 빨리 나오게 된다는 것이죠.

그리고, 시간이 좀 걸려서 1주일쯤 걸렸다고 칩니다.
그 1주일동안 해커가 컴퓨터 앞에 매달려 있습니까 ? 잠을 못잡니까 ?
계속 지켜봐야 합니까 ?? 아니면 컴퓨터가 망가집니까 ?

그냥 디코드 돌려놓고 지 할일 하다가 결과 나오면 그때 해킹하는 것이죠...



------------------------------------------------------------------------------

결국은 DB 가 노출되거나, 해쉬된 비밀번호의 결과값이 노출되면 게임은 끝이라는 겁니다.

가령, 비밀번호를 암호화시켰다고 해서 비밀번호를 쿠키로 날아다니게 한다던지,
페이지에 폼값으로 날려준다던지 하는 것은 해커에게 비밀번호를 다이렉트로 알려주는 것과
같습니다......

그럼,

비밀번호 안 날라 다니게 하고 DB노출만 막으면 안전할까요 ??


그것도 만만치 않습니다.

크라이언트에서 서버 접속해서 비밀번호 처음에 날려줄 때,,,,
네트웍을 감시당하면 아예, 원 비밀번호가 그대로 노출될 수 있습니다...

그래서 클라이언트에서도 JavaScript 를 이용해서 나름대로 암호화시킨 문자열을
날아다니게 하지요...

네트웍 감시를 당했을 때, 암호화된 비밀번호가 노출되는 것이구요..

하지만,, 이 역시 결과는 마찬가지죠.......

이 경우는 암호를 풀고 자시고도 없이
그냥 암호화된 비번 그 자체를 login 페이지로 날려서 그대로 접속해 버리면 되지요..
이 경우라면 원래의 암호는 알 필요도 없는 것이지요..


-------------------- 그럼 가장 안전한 방법은 무엇인가 ---------------------------------

개발자는 어떤 상황이던 비밀번호 스트링이 네트웍감시를 당하던, DB 가 노출되던 해서
해커에게 알려진다고 간주해야 합니다.

그럼 이러던 저러던 끝이라는 얘기일까요 ?
... 꼭 그렇지만은 않다고 봅니다.

여기서 우리는 보안을 위해 몇 가지 노력해야 할 것이 있습니다.


#-------------- 비밀번호가 어떤 모듈로 해쉬가 됐는지 모르게 하자.

가장 쉬운 방법은,, 암호화함수 1개에 의존하지 않고 여러 함수를 거쳐 2중 3중으로 돌려야 합니다.



#-------------- 외부에 노출이 안되는 서버만의 고유한 토큰키를 만들자.

가령,

사용자가 '1234' 라는 비밀번호를 쳤을 때 DB 저장할 때는 고유의 '키값'을 정해 눌러서 저장합니다.
예) 키값 '1011' + 비밀번호 '1234' = '2245'
저장도 '2245' 로 저장하고 로그인 인증 때도 또 키값을 더해서 인증하는 것이죠...

'키값'은 절대 DB 에 저장하지 않고, 파일로 접근하게 만듭니다.
서버 자체가 해킹당하기 전에는 절대 볼 수 없도록 실행권한과 접근권한도 설정 되야 겠지요..



#-------------- 클라이언트와 주고받는 비밀번호역시 또 다른 유일한 '키값'을 부여해서 주고받습니다...

서버쪽에서 DB 저장할 때와는 조금 틀리죠...
이 '키값'은 접속시마다 틀리게 합니다.

예) 키값 '0012'

클라이언트 '1234' + '0012' = '1246' ---- 송신 ----> 서버 '1246' - '0012' = '1234' 저장.

그런데,
주고 받을때 사용하는 키값은 클라이언트 페이지에 남아 있으면 안됩니다.

가령,

<form name=hashKey type=hidden value='<?=$hashKey?>'>

저렇게 되 있다면,

Temporary Internet Files 디렉토리만 뒤져봐도 키값이 노출되겠지요...

그러니 페이지에 남기지 않고 로그아웃시 메모리에서 사라지게
lifetime 0 짜리 1회용 쿠키나 세션에 담아쓰면 좀 낳을 수 있겠지요...

페이지에서 쿠키값을 검색해서 '키값'을 뽑아내고 메모리 상에서만 연산을 하면 되겠지요..

저렇게나마 해 두면 네트웍 감시를 당해도

id = 'abcd'
pw = '1246'
이라는 해쉬된 값이 나오기 때문에 원래의 비밀번호 '1234' 는
'키값'을 알기 전에는 무용지물이 되겠지요....

그리고  login 페이지로 '1246'을 날려도 소용없게 해야죠...
주고받는 그 때만 생성되는 유니크한 값을 '키값'으로 사용해서
어떨 때는 '1246' 이 '1234' 로 해석되지만,
어떨 때는 '3266' 이 '1234' 로 해석이 되게 하는 등.....
지속적으로 키값이 바뀌게 해야 하는 것이죠.....


보통 setCookie("hashKey", rand( 1000, 9000), 0 ) 식으로 라이프타임을 0 으로 주면
페이지 접속창이 닫힐 때 까지만 한번 정해진 '키값'이 유효한 상태가 되고,
이후 새로운 창이 열리거나 기존 창을 닫으면 사라지게 되지요..

쿠키도 마찬가지로 라이프타임을 0 으로 주면 되구요,.,



------------- 이정도 가지만 해도 ---------------------------------------------------

# DB 가 노출되었을 때 사용자들을 보호할 수 있습니다.

# 네트웍이 감시를 당해도 원래의 아이디를 모를 뿐 아니라
    해쉬된 스트링으로 로그인을 시도해도 키값이 수시로 변하기에 안전할 수 있습니다.



물론 헤커가 세션과, 쿠키까지 파싱하고, 서버디렉토리도 들락날락거린다면 속수무책이 되게지만,
최소한 실력없는 헤커로부터는 안전을 보장받을 수 있게 됩니다.




아참,
mysql 의 password() 함수를 실험 안 해 보았군요....



id = 'abcd'
pw = '4ed0bdda4ee8f6a5'

<?
for( $i = 0; $i < 99999; $i ++ ) {

       $temp = mysql_fetch_array( mysql_query ( "select password('$i')" ) );

       if( '4ed0bdda4ee8f6a5' == $temp[0] ) {
              echo " find ok : $i ";
              break;
       }
}
// 출력 -> find ok : 50267
?>