>백엔드 개발 >PHP 튜토리얼 >응용 프로그램이 PHP 응용 프로그램의 잘못된 병렬 구성 보안을 시작할 수 없습니다 - 위반할 수 없는 4가지 보안 규칙

응용 프로그램이 PHP 응용 프로그램의 잘못된 병렬 구성 보안을 시작할 수 없습니다 - 위반할 수 없는 4가지 보안 규칙

WBOY
WBOY원래의
2016-07-29 08:35:191506검색

보안이 중요하다는 것은 누구나 알고 있지만, 마지막 순간까지 보안을 추가하지 않는 것이 업계 추세입니다. 웹 애플리케이션을 완벽하게 보호하는 것은 불가능하기 때문에 굳이 귀찮게 할 이유가 있을까요? 잘못된. 몇 가지 간단한 단계만 수행하면 PHP 웹 애플리케이션의 보안을 크게 향상시킬 수 있습니다.
시작하기 전에
이 튜토리얼에서는 PHP 웹 애플리케이션에 보안을 추가하는 방법을 알아봅니다. 이 튜토리얼에서는 사용자가 PHP 웹 애플리케이션 작성 경험이 1년 이상 있다고 가정하므로 PHP 언어(규칙 또는 구문)에 대한 기본 지식은 여기서 다루지 않습니다. 목표는 귀하가 구축하는 웹 애플리케이션을 보호하는 방법에 대한 아이디어를 제공하는 것입니다.
목적
이 튜토리얼에서는 SQL 주입, GET 및 POST 변수 조작, 버퍼 오버플로 공격, 사이트 간 스크립팅 공격, 브라우저 내 데이터 조작, 원격 양식 제출 등 가장 일반적인 보안 위협으로부터 보호하는 방법을 설명합니다. .
전제 조건
이 튜토리얼은 프로그래밍 경험이 1년 이상인 PHP 개발자를 위해 작성되었습니다. PHP의 구문과 규칙을 이해해야 합니다. 여기서는 설명하지 않습니다. Ruby, Python 및 Perl과 같은 다른 언어를 사용한 경험이 있는 개발자도 이 튜토리얼의 이점을 누릴 수 있습니다. 여기서 논의된 많은 규칙은 다른 언어 및 환경에도 적용되기 때문입니다.
시스템 요구사항
PHP V4 또는 V5 및 MySQL을 실행하는 환경이 필요합니다. Linux, OS X 또는 Microsoft Windows를 사용할 수 있습니다. Windows를 사용하는 경우 WAMPServer 바이너리를 다운로드하고 컴퓨터에 Apache, MySQL 및 PHP를 설치하십시오.
보안에 대한 간략한 소개
웹 애플리케이션에서 가장 중요한 부분은 무엇인가요? 이 질문에 대한 대답은 누가 대답하느냐에 따라 달라질 수 있습니다. 비즈니스 사람들에게는 안정성과 확장성이 필요합니다. IT 지원 팀에는 강력하고 유지 관리가 가능한 코드가 필요합니다. 최종 사용자는 작업 수행 시 아름다운 사용자 인터페이스와 높은 성능을 요구합니다. 그러나 대답이 "보안"이라면 이것이 웹 애플리케이션에 중요하다는 데 모두가 동의할 것입니다.
그러나 대부분의 논의는 여기서 그칩니다. 보안은 프로젝트 체크리스트에 있지만 프로젝트가 전달될 때까지 해결되지 않는 경우가 많습니다. 이 접근 방식을 사용하는 웹 애플리케이션 프로젝트의 수는 엄청납니다. 개발자들은 웹 애플리케이션을 대중에게 공개하기 위해 마지막에 보안 기능을 추가하면서 몇 달 동안 작업했습니다.
보안 기능이 추가되기 전에 코드를 검사하고, 단위 테스트하고, 더 큰 프레임워크에 통합했기 때문에 결과가 엉망이거나 재작업이 필요한 경우가 많습니다. 보안을 추가한 후 주요 구성 요소의 작동이 중지될 수 있습니다. 보안 통합은 원활하지만 안전하지 않은 프로세스에 추가 부담이나 단계를 추가합니다.
이 튜토리얼은 보안을 PHP 웹 애플리케이션에 통합하는 훌륭한 방법을 제공합니다. 몇 가지 일반적인 보안 주제를 논의한 다음 주요 보안 취약점과 이를 연결하는 방법을 자세히 살펴봅니다. 이 튜토리얼을 마치면 보안에 대해 더 잘 이해하게 될 것입니다.
주제:
SQL 주입 공격
GET 문자열 조작
버퍼 오버플로 공격
교차 사이트 스크립팅 공격(XSS)
브라우저 내 데이터 조작
원격 양식 제출
웹 보안 101
보안 구현의 세부 사항을 논의하기 전에 높은 수준의 관점에서 웹 애플리케이션 보안을 논의하는 것이 가장 좋습니다. 이 섹션에서는 어떤 종류의 웹 애플리케이션을 생성하든 염두에 두어야 할 몇 가지 기본 보안 철학을 소개합니다. 이러한 아이디어 중 일부는 Chris Shiflett(PHP 보안에 관한 책이 귀중한 보고임), 일부는 Simson Garfinkel(참고자료 참조), 일부는 수년간 축적된 지식에서 나왔습니다.
규칙 1: 외부 데이터나 입력을 절대 신뢰하지 마세요.
웹 애플리케이션 보안에 대해 가장 먼저 깨달아야 할 것은 외부 데이터를 신뢰해서는 안 된다는 것입니다. 외부 데이터에는 프로그래머가 PHP 코드에 직접 입력하지 않은 모든 데이터가 포함됩니다. 다른 소스(예: GET 변수, 양식 POST, 데이터베이스, 구성 파일, 세션 변수 또는 쿠키)의 모든 데이터는 보안을 보장하기 위한 조치를 취할 때까지 신뢰할 수 없습니다.
예를 들어 다음 데이터 요소는 PHP에서 설정되므로 안전하다고 간주할 수 있습니다.
목록 1. 안전하고 완벽한 코드
$myUsername = 'tmyer'
$arrayUsers = array('tmyer', 'tom', 'tommy'); >define("GREETING", 'hello there' . $myUsername)
?> 그러나 다음 데이터 요소에는 결함이 있습니다.
목록 2. 안전하지 않고 결함이 있는 코드
$myUsername = $_POST['username'] //tainted!
$arrayUsers = array($myUsername, ' tom', 'tommy'); //tainted!
define("GREETING", 'hello 거기' . $myUsername); //tainted!
?> ? POST 형식에서 직접 제공되기 때문입니다. 사용자는 파일을 정리하거나 이전에 업로드한 파일을 실행하기 위한 악성 명령을 포함하여 이 입력 필드에 임의의 문자열을 입력할 수 있습니다. "A-Z 문자만 허용하는 클라이언트측(JavaScript) 양식 유효성 검사 스크립트를 사용하면 이러한 위험을 피할 수 없나요?"라고 물을 수 있습니다. 예, 이는 항상 유익한 단계이지만 나중에 살펴보겠지만 누구나 어떤 양식이든 컴퓨터에 다운로드하여 수정하고 필요한 것을 다시 제출할 수 있습니다.
해결책은 간단합니다. 삭제 코드는 $_POST['username'] 에서 실행되어야 합니다. 이렇게 하지 않으면 $myUsername을 사용할 때마다(예: 배열 또는 상수에서) 이러한 개체를 오염시킬 수 있습니다.
사용자 입력을 삭제하는 간단한 방법은 정규식을 사용하여 처리하는 것입니다. 이 예에서는 문자만 허용됩니다. 문자열을 특정 문자 수로 제한하거나 모든 문자를 소문자로 요구하는 것도 좋은 생각일 수 있습니다.
목록 3. 사용자 입력을 안전하게 만들기
$myUsername = cleanInput($_POST['username']) //clean!
$arrayUsers = array($myUsername , ' tom', 'tommy'); //clean!
define("GREETING", '안녕하세요' . $myUsername) //clean!
function cleanInput($input){
$ clean = strtolower($input);
$clean = preg_replace("/[^a-z]/", "", $clean)
$clean = substr($clean,0,12) > return $clean;
}
?>
규칙 2: 보안 구현을 어렵게 만드는 PHP 설정을 비활성화합니다.
이제 사용자 입력을 신뢰할 수 없다는 것을 알았습니다. 기계를 신뢰하지 않습니다. PHP를 구성하는 방법. 예를 들어, Register_globals가 비활성화되어 있는지 확인하십시오. Register_globals가 활성화된 경우 $variable을 사용하여 동일한 이름의 GET 또는 POST 문자열을 바꾸는 것과 같은 부주의한 작업을 수행할 수 있습니다. 이 설정을 비활성화하면 PHP는 올바른 네임스페이스에서 올바른 변수를 참조하도록 강제합니다. POST 형식의 변수를 사용하려면 $_POST['variable']을 인용해야 합니다. 이렇게 하면 이 특정 변수를 쿠키, 세션 또는 GET 변수로 잘못 해석하지 않습니다.
두 번째로 확인해야 할 설정은 오류 보고 수준입니다. 개발 중에는 가능한 한 많은 오류 보고서를 얻고 싶지만, 프로젝트를 전달할 때는 오류가 화면에 표시되지 않고 로그 파일에 기록되기를 원합니다. 왜? 악의적인 해커가 오류 보고 정보(예: SQL 오류)를 사용하여 애플리케이션이 수행하는 작업을 추측할 수 있기 때문입니다. 이러한 종류의 정찰은 해커가 애플리케이션을 침해하는 데 도움이 될 수 있습니다. 이 취약점을 해결하려면 php.ini 파일을 편집하여 error_log 항목에 적합한 대상을 제공하고 display_errors를 Off로 설정하십시오.
규칙 3: 이해하지 못하면 보호할 수 없습니다
어떤 개발자는 이상한 구문을 사용하거나 문장을 매우 촘촘하게 구성하여 짧지만 모호한 코드를 만듭니다. 이 접근 방식은 효율적일 수 있지만 코드가 수행하는 작업을 이해하지 못하면 코드를 보호하는 방법을 결정할 수 없습니다.
예를 들어, 다음 두 가지 코드 중 어떤 코드가 마음에 드시나요?
목록 4. 코드를 보호하기 쉽게 만드세요
//난독화된 코드
$input = (isset($_POST['username']) ? $_POST['username' ] :'');
//난독화되지 않은 코드
$input = '';
if (isset($_POST['username'])){
$input = $_POST['username ' ];
$input = '';
}
?>
두 번째 명확한 코드 조각에서는 $input에 결함이 있음을 쉽게 알 수 있습니다. 안전하게 폐기하기 전에 청소해야 합니다.
규칙 4: "심층 방어"는 새로운 마법 무기입니다.
이 튜토리얼에서는 예제를 사용하여 온라인 양식을 보호하는 동시에 양식을 처리하는 PHP 코드에서 필요한 조치를 취하는 방법을 설명합니다. 마찬가지로, PHP 정규식을 사용하여 GET 변수가 완전히 숫자인지 확인하는 경우에도 SQL 쿼리가 이스케이프된 사용자 입력을 사용하도록 조치를 취할 수 있습니다.
심층 방어는 단순히 좋은 생각이 아니라 심각한 문제에 빠지지 않도록 보장합니다.
이제 기본 규칙에 대해 논의했으니 첫 번째 위협인 SQL 주입 공격을 살펴보겠습니다.
SQL 주입 공격 방지
SQL 주입 공격에서는 사용자가 양식이나 GET 쿼리 문자열을 조작하여 데이터베이스 쿼리에 정보를 추가합니다. 예를 들어 간단한 로그인 데이터베이스가 있다고 가정합니다. 이 데이터베이스의 각 레코드에는 사용자 이름 필드와 비밀번호 필드가 있습니다. 사용자가 로그인할 수 있도록 로그인 양식을 작성하십시오.
목록 5. 간단한 로그인 양식


로그인



<입력 유형 = 'text' name='user' id='user'/>


<입력 유형='제출' 값='로그인'/ > ;




이 양식은 사용자가 입력한 사용자 이름과 비밀번호를 승인합니다. verify.php라는 파일입니다. 이 파일에서 PHP는 다음과 같이 로그인 양식의 데이터를 처리합니다.
목록 6. 안전하지 않은 PHP 양식 처리 코드
$okay =
$username = $_POST[ 'user'];
$pw = $_POST['pw'];
$sql = "사용자 이름='".$username."' 및 비밀번호='인 사용자로부터 count(*)를 선택합니다. ".$pw."' 제한 1";
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data- >ctr = = 1){
                                                                 $_SESSION['loginokay'] =
header("index.php")
}el; se{
헤더("login.php")
}
?>
이 코드는 괜찮아 보이죠? 전 세계적으로 수백(수천은 아니더라도) PHP/MySQL 사이트가 이와 같은 코드를 사용합니다. 무슨 문제가 있나요? 글쎄요, "사용자 입력을 신뢰할 수 없습니다"를 기억하세요.사용자의 어떤 정보도 여기서 이스케이프되지 않으므로 애플리케이션이 취약해집니다. 특히 모든 유형의 SQL 주입 공격이 발생할 수 있습니다.
예를 들어, 사용자가 사용자 이름으로 foo를 입력하고 비밀번호로 ' 또는 '1'='1을 입력하면 실제로 다음 문자열이 PHP로 전달되고 MySQL로 쿼리가 전달됩니다.
$sql = "사용자 이름='foo' 및 비밀번호='' 또는 '1'='1' 제한 1인 사용자로부터 count(*)를 선택합니다."
이것은 쿼리는 항상 1의 개수를 반환하므로 PHP는 액세스를 허용합니다. 해커는 비밀번호 문자열 끝에 일부 악성 SQL을 삽입하여 합법적인 사용자를 가장할 수 있습니다.
이 문제에 대한 해결책은 PHP에 내장된 mysql_real_escape_string() 함수를 사용자 입력 주위의 래퍼로 사용하는 것입니다. 이 함수는 문자열의 문자를 이스케이프하여 문자열에서 아포스트로피와 같은 특수 문자를 전달하는 것을 불가능하게 하고 MySQL이 특수 문자에 대해 작동할 수 있도록 합니다. Listing 7은 이스케이프된 코드를 보여준다.
목록 7. 보안 PHP 양식 처리 코드
$okay = 0
$username = $_POST['user']
$pw = $_POST[ ' pw'];
$sql = "사용자 이름='".mysql_real_escape_string($username)."' 및 비밀번호='"인 사용자의 ctr로 개수(*)를 선택합니다."' 제한 1 ";
$result = mysql_query($sql);
while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
/ /
$okay = 1
}
}
if ($okay){
$_SESSION['loginokay'] = true; header("index.php");
}else{
header("login.php");
}
?> mysql_real_escape_string()을 사용자 입력용 래퍼로 사용 , 사용자 입력 시 악의적인 SQL 삽입을 방지할 수 있습니다. 사용자가 SQL 주입을 통해 잘못된 비밀번호를 전달하려고 하면 다음 쿼리가 데이터베이스에 전달됩니다.
select count(*) as ctr from users where username='foo' and Password='' or '1' ='1 ' 제한 1"
데이터베이스에 해당 비밀번호와 일치하는 항목이 없습니다. 간단한 한 단계만으로 웹 애플리케이션에 큰 구멍이 생겼습니다. 여기서 교훈은 항상 SQL Escape 사용자 입력을 사용해야 한다는 것입니다.
그러나 차단해야 할 몇 가지 보안 허점이 있습니다.
GET 변수의 사용자 조작 방지
이전 섹션에서는 사용자가 잘못된 비밀번호로 로그인하는 것을 방지했습니다. 당신은 현명했습니다. SQL 문에 대한 모든 사용자 입력이 이스케이프되었는지 확인하기 위해 배운 기술을 적용했어야 했습니다.
하지만 이제 사용자는 유효한 비밀번호로 안전하게 로그인할 수 있다는 의미는 아닙니다. 규칙에 따라 플레이하세요. 예를 들어, 애플리케이션을 통해 사용자는 template.php?pid=33 또는 template.php?pid=321을 가리키는 특별한 콘텐츠를 볼 수 있습니다. URL에서 물음표 뒤의 부분을 쿼리 문자열이라고 합니다. 쿼리 문자열이 URL에 직접 배치되기 때문에 PHP에서는 Register_globals가 비활성화된 경우 이 문자열에 액세스할 수 있습니다. $_GET['pid']를 사용하여 template.php 페이지에서 목록 8과 유사한 작업을 수행할 수 있습니다. 예제 template.php
$pid = $_GET['pid'];
//가상 클래스 Page
$obj = new Page의 객체를 생성합니다.
$content = $obj->fetchPage($pid)
//이제 페이지를 표시하는 PHP 무리
?>
여기에 문제가 있나요? 우선 브라우저의 GET 변수 pid가 안전하다는 암묵적인 믿음이 있습니다. 대부분의 사용자는 그렇지 않을 것입니다. 의미론적 공격을 구성하는 것이 현명하지만 브라우저의 URL 위치 필드에서 pid=33을 발견하면 문제가 발생할 수 있습니다.다른 숫자를 입력하면 괜찮을 것입니다. 그러나 SQL 명령이나 파일 이름(예: /etc/passwd) 또는 3,000자 길이의 값과 같은 다른 장난을 입력하면 어떻게 될까요? ?
이 경우 기본 규칙을 기억하고 사용자 입력을 신뢰하지 마세요. 애플리케이션 개발자는 template.php에서 허용하는 개인 식별자(PID)가 숫자여야 한다는 것을 알고 있으므로 아래와 같이 PHP의 is_numeric() 함수를 사용하여 숫자가 아닌 PID가 허용되지 않도록 할 수 있습니다.
목록 9. is_numeric 사용 ( ) GET 변수를 제한
$pid = $_GET['pid']
if (is_numeric($pid)){
//a 객체를 생성합니다. 가상 클래스 Page
$obj = new Page;
$content = $obj->fetchPage($pid)
//이제 페이지를 표시하는 PHP가 생겼습니다
} else {
//is_numeric() 테스트를 통과하지 못했습니다. 다른 작업을 수행하세요!
}
?> 이 방법은 효과적인 것 같지만 다음 입력은 is_numeric 검사를 쉽게 통과할 수 있습니다. for ():
100(유효)
100.1(소수점 자리가 없어야 함)
0123.45e6(과학적 표기법 - 좋지 않음)
0xff33669f(16진수 - 위험! 위험! )
그래서 , 보안에 민감한 PHP 개발자는 무엇을 해야 합니까? 수년간의 경험에 따르면 정규식을 사용하여 아래와 같이 전체 GET 변수가 숫자로 구성되도록 하는 것이 가장 좋습니다.
목록 10. 정규식을 사용하여 GET 변수 제한
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid)){
/ /로그아웃하거나 홈 페이지로 다시 보내는 등의 적절한 조치를 취하세요
}
}else{
//$pid를 비우므로 홈 페이지로 다시 보내기
}
//이제
//악의적인 사용자 입력으로부터 적당히 보호되는 가상 클래스 페이지의 개체를 만듭니다.
$obj = new Page;$content = $obj->fetchPage( $ pid)
//이제
?> 페이지를 표시하는 PHP 배치가 생겼습니다.
strlen()을 사용하여 변수의 길이가 아닌지 확인하면 됩니다. -zero; 그렇다면 모든 숫자로 구성된 정규 표현식을 사용하여 데이터 요소가 유효한지 확인하세요. PID에 문자, 슬래시, 마침표 또는 16진수와 유사한 모든 것이 포함되어 있으면 이 루틴은 이를 캡처하고 페이지에서 사용자 활동을 차단합니다. Page 클래스의 이면을 살펴보면 보안을 중시하는 PHP 개발자가 사용자 입력 $pid 를 이스케이프하여 아래와 같이 fetchPage() 메서드를 보호하고 있음을 알 수 있습니다.
목록 11. 오른쪽 fetchPage( )
class Page{
function fetchPage($pid){
$sql = "pid가 있는 페이지에서 pid,title,desc,kw,content,status를 선택하는 방법 ='".mysql_real_escape_string($pid)."'";
}
}
?>
"PID가 숫자임을 확인했는데 왜 여전히 탈출?" fetchPage() 메서드가 얼마나 다양한 컨텍스트와 상황에서 사용될지 모르기 때문입니다. 이 메소드가 호출되는 모든 곳에서 보호가 제공되어야 하며 메소드에서 탈출하는 것은 심층 방어의 의미를 구현합니다.
사용자가 버퍼 오버플로 공격을 시도하기 위해 최대 1000자 등 매우 긴 값을 입력하려고 하면 어떻게 되나요? 다음 섹션에서는 이에 대해 더 자세히 설명하지만 지금은 입력 PID의 길이가 올바른지 확인하기 위해 또 다른 검사를 추가할 수 있습니다. 데이터베이스의 pid 필드의 최대 길이가 5자리라는 것을 알고 있으므로 다음 확인을 추가할 수 있습니다.
목록 12. 정규식 및 길이 검사를 사용하여 GET 변수 제한
$pid = $_GET['pid']
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid) && strlen($pid) > 5){
//로그아웃하거나 다시 보내는 등 적절한 작업을 수행합니다. home page
}
} else {
//$pid가 비어 있으므로 홈 페이지로 다시 보냅니다.
}
//가상 클래스 Page의 개체를 만듭니다. 이제
//악한 사용자 입력으로부터 더욱 보호됩니다.
$obj = new Page
$content = $obj->fetchPage($pid)
//이제 페이지를 표시하는 PHP 묶음
?>
요즘에는 누구도 5,000자리 값을 데이터베이스 애플리케이션에 넣을 수 없습니다. 적어도 GET 문자열이 포함된 곳에서는 말이죠. 해커가 귀하의 응용 프로그램에 침입하려는 시도에 좌절감을 느끼고 이를 갈고 있다고 상상해 보십시오! 그리고 오류 보고 기능이 꺼져 있기 때문에 해커가 정찰을 수행하기가 더 어렵습니다.
버퍼 오버플로 공격
버퍼 오버플로 공격은 PHP 애플리케이션(또는 더 정확하게는 Apache 또는 기본 운영 체제)에서 메모리 할당 버퍼 오버플로를 시도합니다. PHP와 같은 고급 언어로 웹 애플리케이션을 작성하더라도 여전히 C(Apache의 경우)를 호출하게 된다는 점을 기억하세요. 대부분의 저수준 언어와 마찬가지로 C에는 메모리 할당에 대한 엄격한 규칙이 있습니다.
버퍼 오버플로 공격은 대량의 데이터를 버퍼로 전송하여 데이터 중 일부가 인접한 메모리 버퍼로 오버플로되도록 하여 버퍼를 파괴하거나 로직을 다시 작성하게 합니다. 이로 인해 서비스 거부가 발생하거나 데이터가 손상되거나 원격 서버에서 악성 코드가 실행될 수 있습니다.
버퍼 오버플로 공격을 방지하는 유일한 방법은 모든 사용자 입력 길이를 확인하는 것입니다. 예를 들어 사용자 이름이 필요한 양식 요소가 있는 경우 이 필드에 값이 40인 maxlength 속성을 추가하고 백엔드에서 substr()을 사용하여 확인합니다. 목록 13에는 양식과 PHP 코드의 간단한 예가 나와 있습니다.
목록 13. 사용자 입력 길이 확인
if ($_POST['submit'] == "go"){
$name = substr($_POST[' 이름 '],0,40);
}
?>



; /form>
maxlength 속성을 제공할 뿐만 아니라 백엔드에서 substr() 검사도 수행하는 이유는 무엇입니까? 심층 방어는 항상 좋기 때문입니다. 브라우저는 사용자가 PHP 또는 MySQL이 안전하게 처리할 수 없는 매우 긴 문자열을 입력하는 것을 방지하는 반면(누군가가 최대 1,000자 길이의 이름을 입력하려고 한다고 상상해 보십시오), 백엔드 PHP는 누구도 원격으로 또는 브라우저에서 양식 데이터를 조작하지 않는지 확인합니다.
보시다시피 이 접근 방식은 이전 섹션에서 strlen()을 사용하여 GET 변수 pid의 길이를 확인하는 것과 유사합니다.이 예에서는 5자리보다 긴 입력 값은 무시되지만 아래와 같이 값을 적절한 길이로 쉽게 잘라낼 수 있습니다.
목록 14. 입력 GET 변수의 길이 변경
$pid = $_GET['pid'];
if (strlen($pid)){
if (!ereg("^[0-9] $",$pid )){
//숫자가 아닌 $pid인 경우 홈 페이지로 다시 보냅니다.
}
}else{
//$pid가 비어 있으므로 홈 페이지로 다시 보냅니다.
}
//숫자형 pid가 있는데 너무 길 수 있으니 확인해 보겠습니다.
if (strlen($pid)>5){
$pid = substr($pid,0, 5);
}
//가상 클래스 Page의 객체를 생성합니다. 이는 이제
//악한 사용자 입력으로부터 더욱 보호됩니다.
$obj = new Page; $ content = $ obj->fetchPage($pid); //이제 페이지를 표시하는 PHP 배치가 생겼습니다
?>
버퍼 오버플로 공격은 긴 숫자 문자열로 제한되지 않습니다. 또는 편지. 긴 16진수 문자열(종종 xA3 또는 xFF처럼 보임)도 볼 수 있습니다. 버퍼 오버플로 공격의 목표는 특정 버퍼를 플러딩하고 악성 코드나 명령을 다음 버퍼에 배치하여 데이터를 손상시키거나 악성 코드를 실행하는 것입니다. 16진수 버퍼 오버플로를 처리하는 가장 간단한 방법은 입력이 특정 길이를 초과하지 않도록 하는 것입니다.
데이터베이스에 더 긴 항목을 허용하는 양식 텍스트 영역을 처리하는 경우 클라이언트 측에서 데이터 길이를 쉽게 제한할 수 있는 방법이 없습니다. 데이터가 PHP에 도착하면 정규식을 사용하여 16진수와 유사한 문자열을 지울 수 있습니다.
목록 15. 16진수 문자열 방지
if ($_POST['submit'] == "go"){
$name = substr($_POST[ 'name'] ,0,40);
//모든 잠재적인 16진수 문자를 제거합니다.
$name = cleanHex($name)
//계속 처리합니다....
}
function cleanHex( $input){
$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input); clean;
}
?>



이 일련의 작업이 다소 엄격하다는 것을 알 수 있습니다. 결국 16진수 문자열은 외국어로 문자를 인쇄하는 등 합법적인 용도로 사용됩니다. 16진수 정규식을 배포하는 방법은 귀하에게 달려 있습니다. 더 나은 전략은 한 줄에 16진수 문자열이 너무 많거나 문자열이 특정 문자 수(예: 128 또는 255)를 초과하는 경우에만 16진수 문자열을 제거하는 것입니다.
교차 사이트 스크립팅 공격
교차 사이트 스크립팅(XSS) 공격에서는 악의적인 사용자가 양식에(또는 다른 사용자 입력 방법을 통해) 정보를 입력하여 악성 클라이언트 측 태그를 삽입하는 경우가 많습니다. 프로세스 또는 데이터베이스에 있습니다. 예를 들어, 방문자가 자신의 이름, 이메일 주소, 간단한 메시지를 남길 수 있는 간단한 방명록 프로그램이 사이트에 있다고 가정해 보겠습니다. 악의적인 사용자는 이 기회를 이용하여 다른 사용자에게 부적절한 이미지나 사용자를 다른 사이트로 리디렉션하거나 쿠키 정보를 훔치는 JavaScript 등 간단한 메시지가 아닌 다른 내용을 삽입할 수 있습니다.
다행히도 PHP는 HTML 태그로 둘러싸인 모든 콘텐츠를 제거할 수 있는 Strip_tags() 함수를 제공합니다. Strip_tags() 함수를 사용하면 또는 와 같은 허용된 태그 목록을 제공할 수도 있습니다.
목록 16은 이전 예제를 기반으로 구축된 예제를 보여줍니다.
목록 16. 사용자 입력에서 HTML 태그 지우기
if ($_POST['submit'] == "go"){
//strip_tags
$name = Strip_tags($_POST['name']);
$name = substr($name,0,40);
//모든 잠재적인 16진수 문자를 제거합니다.
$name = cleanHex($name) ;
//계속 처리....
}
function cleanHex($input){
$clean = preg_replace("![][xX]([A-Fa-f0-9 ] {1,3})!", "",$input);
return $clean;
}
?>





보안 관점에서 공용 사용자 입력을 위해 Strip_tags()를 사용하는 것이 필요합니다. 양식이 보호된 영역(예: 콘텐츠 관리 시스템)에 있고 사용자가 작업(예: 웹사이트용 HTML 콘텐츠 생성)을 올바르게 수행할 것이라고 신뢰하는 경우, Strip_tags() 사용은 불필요할 수 있으며 생산성에 영향을 미칠 수 있습니다.
질문 하나 더: 게시물에 대한 댓글이나 게스트 등록 항목과 같은 사용자 입력을 받아들이고 이 입력을 다른 사용자에게 표시해야 하는 경우 PHP의 htmlspecialchars() 함수에 응답을 넣어야 합니다. 이 함수는 앰퍼샌드, < 및 > 기호를 HTML 엔터티로 변환합니다. 예를 들어 앰퍼샌드(&)는 &가 됩니다. 이 경우 악성 콘텐츠가 프런트엔드의 Strip_tags() 처리를 벗어나더라도 백엔드에서는 htmlspecialchars()에 의해 처리됩니다.
브라우저 내 데이터 조작
사용자가 페이지의 헤더 요소와 양식 요소를 조작할 수 있는 일종의 브라우저 플러그인이 있습니다. Mozilla 플러그인인 Tamper Data를 사용하면 숨겨진 텍스트 필드가 많은 간단한 양식을 쉽게 조작하여 PHP 및 MySQL에 명령을 보낼 수 있습니다.
사용자가 양식에서 제출을 클릭하기 전에 데이터 변조를 시작할 수 있습니다. 양식을 제출하면 양식 데이터 필드 목록이 표시됩니다. 데이터 변조를 사용하면 브라우저가 양식 제출을 완료하기 전에 사용자가 이 데이터를 변조할 수 있습니다.
앞서 만든 예시로 돌아가 보겠습니다. 문자열 길이가 확인되고 HTML 태그가 정리되었으며 16진수 문자가 제거되었습니다. 그러나 아래와 같이 일부 숨겨진 텍스트 필드가 추가되었습니다.
목록 17. 숨겨진 변수
if ($_POST['submit'] == "go"){
//strip_tags
$name = Strip_tags($_POST['name']);
$name = substr($name,0,40)
//모든 잠재적인 16진수 문자를 제거합니다.
$name = cleanHex($name);
//계속 처리....
}
function cleanHex($input){
$clean = preg_replace("![][xX] ([A-Fa-f0-9]{1,3})!", "",$input);
return $clean;
}
?>

>







숨겨진 변수 중 하나는 테이블 이름인 사용자를 노출합니다. create 값이 있는 작업 필드도 표시됩니다. 기본적인 SQL 경험이 있는 사람이라면 누구나 이러한 명령이 미들웨어의 SQL 엔진을 제어한다는 것을 알 수 있습니다. 큰 혼란을 일으키고 싶은 사람은 테이블 이름을 변경하거나 삭제와 같은 다른 옵션을 제공하면 됩니다.
그림 1은 변조 데이터가 제공할 수 있는 피해 범위를 보여줍니다. Tamper Data를 사용하면 사용자는 양식 데이터 요소뿐만 아니라 HTTP 헤더 및 쿠키에도 액세스할 수 있습니다.
그림 1. 데이터 변조 창
이 도구를 방어하는 가장 쉬운 방법은 모든 사용자가 데이터 변조(또는 유사한 도구)를 사용할 수 있다고 가정하는 것입니다. 시스템이 양식을 처리하는 데 필요한 최소한의 정보만 제공하고 양식을 일부 전용 로직에 제출합니다. 예를 들어 등록 양식은 등록 로직에만 제출되어야 합니다.
공통 양식 처리 기능을 구축했고 많은 페이지에서 이 공통 로직을 사용한다면 어떻게 될까요? 흐름을 제어하기 위해 숨겨진 변수를 사용한다면 어떨까요? 예를 들어, 쓸 데이터베이스 테이블이나 사용할 파일 저장소를 숨겨진 양식 변수로 지정할 수 있습니다. 4가지 옵션이 있습니다:
아무것도 변경하지 말고 시스템에 악의적인 사용자가 없기를 기도하세요.
숨겨진 양식 변수 사용을 방지하기 위해 보다 안전한 전용 양식 처리 기능을 사용하도록 기능을 다시 작성합니다.
md5() 또는 기타 암호화 메커니즘을 사용하여 숨겨진 양식 변수에 있는 테이블 이름이나 기타 민감한 정보를 암호화합니다. PHP 측에서 암호를 해독하는 것을 잊지 마세요.
약어나 별명을 사용하여 값의 의미를 모호하게 만든 다음 이러한 값을 PHP 양식 처리 함수에서 변환합니다. 예를 들어 사용자 테이블을 참조하려는 경우 u 또는 임의의 문자열(예: u8y90x0jkL)을 사용하여 참조할 수 있습니다.
후자의 두 가지 옵션은 완벽하지는 않지만 사용자가 미들웨어 로직이나 데이터 모델을 쉽게 추측하도록 하는 것보다 훨씬 낫습니다.
이제 어떤 질문이 남았나요? 원격 양식 제출.
원격 양식 제출
웹의 장점은 정보와 서비스를 공유할 수 있다는 것입니다. 단점은 어떤 사람들은 양심의 가책도 없이 일을 하기 때문에 정보와 서비스를 공유한다는 것입니다.
양식을 예로 들어보겠습니다. 누구나 웹 사이트를 방문하고 브라우저에서 파일 > 다른 이름으로 저장을 사용하여 양식의 로컬 복사본을 만들 수 있습니다. 그런 다음 그는 완전한 URL(formHandler.php가 아니라 양식이 이 사이트에 있으므로 http://www.yoursite.com/formHandler.php)을 가리키도록 작업 매개변수를 수정하고 원하는 작업을 수행할 수 있습니다. 수정 사항이 있는 경우 제출을 클릭하면 서버는 법적 통신 흐름으로 이 양식 데이터를 수신하게 됩니다.
먼저 $_SERVER['HTTP_REFERER']를 확인하여 요청이 자신의 서버에서 오는지 확인하는 것이 좋습니다. 이 방법은 대부분의 악의적인 사용자를 차단할 수 있지만 가장 정교한 해커는 차단할 수 없습니다. 이 사람들은 양식의 원격 복사본이 서버에서 제출된 것처럼 보이도록 헤더의 참조 정보를 조작할 만큼 똑똑합니다.
원격 양식 제출을 처리하는 더 좋은 방법은 고유한 문자열이나 타임스탬프를 기반으로 토큰을 생성하고 이 토큰을 세션 변수와 양식에 넣는 것입니다. 양식을 제출한 후 두 토큰이 일치하는지 확인하세요. 일치하지 않으면 누군가가 양식의 원격 복사본에서 데이터를 보내려고 하는 것입니다.
임의 토큰을 생성하려면 아래와 같이 PHP에 내장된 md5(), uniqid() 및 rand() 함수를 사용할 수 있습니다.
목록 18. 원격 양식 제출 방지
session_start()
if ($_POST['submit'] == "go"){
//토큰 확인
if ($_POST['token'] == $_SESSION [' 토큰']){
//strip_tags
$name = Strip_tags($_POST['name'])
$name = substr($name,0,40)
/ /모든 잠재적인 16진수 문자를 제거합니다.
$name = cleanHex($name);
//처리를 계속합니다....
}else{
//모든 원격 양식 게시 시도를 중지합니다!
}
}
$token = md5(uniqid(rand(), true))
$_SESSION['token']= $token;
function cleanHex($input)
$clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input)
return $clean; >}
?>
="name">이름




PHP에서는 세션 데이터를 서버 간에 마이그레이션할 수 없기 때문에 이 기술이 작동합니다.누군가 귀하의 PHP 소스 코드를 획득하여 자신의 서버로 이동하고 귀하의 서버에 정보를 제출하더라도 귀하의 서버는 모두 비어 있거나 잘못된 형식의 세션 토큰과 원래 제공된 양식 토큰만 받게 됩니다. 일치하지 않으며 원격 양식 제출이 실패합니다.
결론
이 튜토리얼에서는 많은 문제를 논의했습니다.
SQL 삽입 문제를 방지하려면 mysql_real_escape_string()을 사용하세요.
정규 표현식과 strlen()을 사용하여 GET 데이터가 변조되지 않았는지 확인하세요.
정규 표현식과 strlen()을 사용하여 사용자가 제출한 데이터가 메모리 버퍼를 오버플로하지 않도록 하세요.
strip_tags() 및 htmlspecialchars()를 사용하여 사용자가 잠재적으로 유해한 HTML 태그를 제출하지 못하도록 방지하세요.
데이터 조작과 같은 도구로 시스템이 침해되는 것을 방지하세요.
사용자가 원격으로 서버에 양식을 제출하는 것을 방지하려면 고유한 토큰을 사용하세요.
이 튜토리얼에서는 파일 삽입, HTTP 헤더 스푸핑 및 기타 취약점과 같은 고급 주제를 다루지 않습니다. 그러나 학습한 내용은 즉시 충분한 보안을 추가하여 현재 프로젝트를 더욱 안전하게 만드는 데 도움이 될 수 있습니다.
참고자료
학습
Zend.com에서 유용한 PHP 101 튜토리얼을 찾아보세요.
Chris Shiflett의 필수 PHP 보안 사본을 받으세요. 그가 제공하는 소개는 이 튜토리얼보다 훨씬 더 심층적입니다.
Simson Garfinkel의 웹 보안, 개인 정보 보호 및 상거래 사본을 받아보세요.
PHP 보안 컨소시엄에 대해 자세히 알아보세요.
'PHP 보안 실수 7가지'를 읽어보세요.
developerWorks의 "권장 PHP 읽기 목록"을 확인하세요.
developerWorks 기사 "PHP 감사, 1부: Register_globals 이해"를 읽어보세요.
PHP 보안 HOWTO 웹캐스트를 확인하세요.
PHP에 대해 자세히 알아보려면 IBM DeveloperWorks의 PHP 프로젝트 참조를 방문하세요.
developerWorks 기술 이벤트와 웹캐스트를 계속 지켜봐 주시기 바랍니다.
전 세계 IBM 오픈 소스 개발자를 위한 예정된 컨퍼런스, 내부 미리보기, 웹캐스트 및 기타 이벤트에 대해 알아보세요.
오픈 소스 기술을 사용하여 개발하고 이를 IBM 제품에서 사용하는 데 도움이 되는 풍부한 방법 정보, 도구, 프로젝트 업데이트가 포함되어 있는 DeveloperWorks의 오픈 소스 영역을 방문하세요.
소프트웨어 개발자 간의 흥미로운 인터뷰와 토론을 들으려면 개발자Works 팟캐스트를 꼭 확인하세요.
제품 및 기술 얻기
Windows 사용자는 WAMPServer를 다운로드할 수 있습니다.
PHP로 다음 개발 프로젝트를 구축해 보세요.
다운로드 또는 DVD로 제공되는 IBM 평가판 소프트웨어를 사용하여 다음 오픈 소스 개발 프로젝트를 개선하세요.
토론
developerWorks 블로그에 참여하여 개발자Works 커뮤니티에 참여하세요.
저자 소개
Thomas Myer는 정보 아키텍처, 웹 애플리케이션 개발 및 XML 컨설팅을 전문으로 하는 텍사스 주 오스틴에 위치한 웹 컨설팅 회사인 Triple Dog Dare Media의 창립자이자 주요 인물입니다. 그는 No Nonsense XML Web Development with PHP(SitePoint 출판)의 저자입니다.

위에서는 시작할 수 없고 병렬 구성이 잘못된 응용 프로그램을 소개합니다. PHP 응용 프로그램의 보안 - 시작할 수 없고 병렬 구성이 잘못된 응용 프로그램을 포함하여 위반할 수 없는 네 가지 보안 규칙입니다. PHP 튜토리얼에 관심이 있는 분들은 이 도움말을 통해 배울 수 있습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.