코드 보기에서 연결용 포함 파일 바로 뒤인 두 번째 줄로 이동하여 다음과 같이 코드 시작 부분에 GetSQLValueString() 함수를 추가합니다:
<?php if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") { $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue); switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } } ?>
문제
일부 데이터베이스는 단일 쿼리에서 여러 개의 SQL 문장을 전송할 수 있습니다. 따라서 쿼리 문자열에서 동적으로 생성된 데이터베이스 쿼리로 매개 변수를 전달할 때 잠재적인 보안 위험이 있습니다. 해커는 기존 매개 변수에 악성 SQL 문을 추가하여 동적 쿼리에서 URL 또는 양식 변수를 수정하려고 시도할 수 있습니다. 이것을 SQL 삽입 공격이라고 합니다. SQL 삽입 공격 위험을 줄이려면 Dreamweaver에서 생성한 서버 동작 코드의 일부를 수정해야 합니다. SQL 삽입에 대한 자세한 배경 정보는 이 위키디피아 문서를 참조하십시오. (참조. 201713)
참고: 이 기술 노트에서 설명하는 문제는 Dreamweaver 8.0.2 업데이터에서 수정되었습니다.
이 기술 노트는 Dreamweaver의 PHP 서버 동작을 다룹니다. ColdFusion, ASP VBScript, ASP JavaScript, JSP 서버 동작에 대한 별도의 기술 노트가 있습니다. ASP.NET 서버 동작은 영향을 받지 않습니다.
해결 방법
쿼리 문자열을 매개 변수에 전달할 때 예측된 정보만 전달되어야 합니다. Adobe는 SQL 주입 공격의 위험을 줄이는 Dreamweaver 8.0.2 업데이트를 만들었습니다.이러한 수정 사항은 향후 Dreamweaver의 모든 릴리스에 통합될 예정입니다. Dreamweaver 8을 업데이트한 후에는 서버 동작을 사용하는 페이지에 서버 동작을 다시 적용하고 해당 페이지를 서버에 다시 배포해야 합니다.
이 기술 노트의 나머지 부분에서는 PHP 서버 모델로 SQL 주입 공격을 방지하기 위해 Dreamweaver MX 2004 코드를 수동으로 편집하는 방법을 설명합니다. 이러한 공격에 취약한 서버 동작이 수정 사항과 함께 아래에 나열되어 있습니다:
필터가 있는 레코드세트
필터링되지 않은 레코드 집합은 수정할 필요가 없지만 필터링된 레코드 집합은 수정해야 합니다. 아래 예에서 "rs_byDate"라는 이름의 Dreamweaver MX 2004 레코드 세트는 URL 매개 변수에서 전달된 날짜 값으로 필터링됩니다. 아래 강조 표시된 코드가 변경해야 하는 부분입니다:
<?php $colname_rs_byDate = "1"; if (isset($_GET['relDate'])) { $colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET['relDate'] : addslashes($_GET['relDate']); } mysql_select_db($database_dreamqa2, $dreamqa2); $query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $colname_rs_byDate); $rs_byDate = mysql_query($query_rs_byDate, $dreamqa2) or die(mysql_error()); $row_rs_byDate = mysql_fetch_assoc($rs_byDate); $totalRows_rs_byDate = mysql_num_rows($rs_byDate); ?>
레코드 세트를 SQL 주입 공격으로부터 보호하려면 페이지 상단 근처에 맞춤형 GetSQLValueString() 함수를 만들어야 합니다. 이 함수는 쿼리 매개 변수의 데이터 유형을 확인합니다. 함수를 만든 후에는 GetSQLValueString() 함수를 사용하도록 레코드 세트 코드를 업데이트합니다.
수정된 코드:
$colname_rs_byDate = $_GET['relDate'];
위에서 만든 GetSQLValueString() 함수를 사용하여 SQL 문자열을 만들도록 레코드세트 코드를 업데이트합니다.$query_rs_byDate 변수의 값을 업데이트합니다:
원본 코드:
$query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $colname_rs_byDate);
수정된 보안 코드:
$query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = %s", GetSQLValueString($colname_rs_byDate, "date"));
레코드 삽입, 업데이트 및 삭제 서버 동작과 레코드 삽입 양식 마법사
레코드 삽입, 업데이트 및 삭제 서버 동작과 레코드 삽입 양식 마법사는 이미 GetSQLValueString() 함수를 사용하므로 SQL 인젝션을 방지하기 위해 수정해야 합니다.GetSQLValueString() 함수에서만 변경하면 됩니다.
다음은 원본 코드입니다.변경할 줄이 노란색으로 강조표시됩니다:
if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue; switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } }
$theValue 변수의 정의를 업데이트합니다:
원래 코드:
$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;
수정된 보안 코드:
$theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);
사용자 로그인 서버 비헤이비어
사용자 로그인 서버 동작을 수정하는 단계는 다음과 같습니다:
로그인 SQL 쿼리를 구성하는 코드를 수정하십시오.
원래 코드:
$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username='%s' AND password='%s'", get_magic_quotes_gpc() ? $loginUsername : addslashes($loginUsername), get_magic_quotes_gpc() ? $password : addslashes($password));
수정된 보안 코드:
$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username=%s AND password=%s", GetSQLValueString($loginUsername, "text"), GetSQLValueString($password, "text"));
새 사용자 확인 서버 비헤이비어
새 사용자 확인 서버 비헤이비어는 먼저 레코드 삽입 서버 동작을 페이지에 추가해야 합니다. GetSQLValuesString() 함수는 레코드 삽입 서버 동작에 포함되어 있습니다. 해야 할 일은 GetSQLValuesString()를 업데이트하여 SQL 인젝션을 더 잘 처리하고, 매개변수가 전달될 때 이 함수를 사용하도록 새 사용자 확인 서버 동작을 업데이트하는 것뿐입니다.
매개변수를 전달할 때 GetSQLValuesString()를 사용하여 로그인 SQL 쿼리를 구성하도록 코드를 수정하십시오. 페이지 상단에서 // *** Redirect if username exists.
로 시작하는 섹션에 있는 코드를 찾으십시오.
원래 코드:
$LoginRS__query = "SELECT username FROM login WHERE username='" . $loginUsername . "'"
수정된 보안 코드:
$LoginRS__query = sprintf("SELECT username FROM login WHERE username=%s", GetSQLValueString($loginUsername, "text"));
마스터 세부 정보 페이지 세트
마스터 세부 정보 페이지 세트 애플리케이션의 경우 변경 사항은 주로 Dreamweaver가 상세 페이지에 대해 생성한 레코드 집합에 있습니다. 마스터 페이지에 필터링된 레코드 집합이 없는 경우 마스터 페이지를 변경할 필요가 없습니다. 필터링된 레코드 집합이 있는 경우 필터가 있는 레코드 집합을 참조하여 레코드 집합 코드를 업데이트하십시오.
Dreamweaver는 상세 페이지에서 필터링된 레코드 집합을 생성하므로, 해당 레코드 집합 코드는 매개변수를 전달하는 GetSQLValueString() 함수와 SQL 문자열을 구성하는 sprintf()를 사용하도록 업데이트해야 합니다.
GetSQLValuesString() 함수를 사용하여 변수 선언 코드를 업데이트하고 SQL 쿼리를 구성하십시오.
원래 코드:
$recordID = $_GET['recordID']; $query_DetailRS1 = "SELECT * FROM albums WHERE ID = $recordID";
수정된 보안 코드:
$colname_DetailRS1 = "-1"; if (isset($_GET['recordID'])) { $colname_DetailRS1 = (get_magic_quotes_gpc()) ? $_GET['recordID'] : addslashes($_GET['recordID']); } $query_DetailRS1 = sprintf("SELECT * FROM albums WHERE ID = %s", GetSQLValueString($colname_DetailRS1, "int"));
레코드 업데이트 폼 마법사
추가 정보
SQL 인젝션 공격에 대한 자세한 내용은 다음 문서를 참조하십시오: SQL 인젝션에 대한 위키피디아 문서.
Adobe 보안 공지: APSB 06-07 Dreamweaver 서버 동작 SQL 인젝션 취약점.