입력 및 출력
- 10분
현재 애플리케이션의 가장 일반적인 보안 약점은 외부 원본, 특히 사용자 입력에서 받은 데이터를 올바르게 처리하지 못하는 것입니다. 입력이 사용되기 전에 유효성이 검사되었는지 확인하려면 항상 모든 입력을 자세히 살펴봐야 합니다. 가능한 공격에 대해 사용자 입력을 분석하지 못하면 데이터가 손실 또는 노출되거나, 권한이 상승하거나, 심지어 다른 사용자의 컴퓨터에서 악성 코드가 실행될 수 있습니다.
이런 상황의 비극은 이 시나리오가 해결하기 쉬운 문제라는 것입니다. 이 단원에서는 데이터를 받을 때, 화면에 표시될 때, 나중에 사용할 수 있도록 저장될 때 데이터를 처리하는 방법을 설명합니다.
입력의 유효성을 검사해야 하는 이유는 무엇일까요?
사용자가 웹 사이트에서 계정을 만들 수 있도록 인터페이스를 빌드하고 있다고 가정해 보겠습니다. 프로필 데이터에는 사이트를 방문하는 모든 사람에게 표시할 이름, 메일 및 애칭이 포함됩니다. 신규 사용자가 프로필을 만들고 몇 가지 SQL 명령이 포함된 애칭을 입력하면 어떻게 될까요? 예를 들어 악의적인 사용자가 다음과 같이 입력하는 경우는 어떻게 해야 합니다.
Eve'); DROP TABLE Users;--
아무 생각 없이 이 값을 데이터베이스에 삽입하면 절대 실행하면 안 되는 명령을 실행하도록 SQL 문이 변경될 수 있습니다. 이 예제는 사용자 입력을 제대로 처리하지 않을 때 발생할 수 있는 여러 유형의 악용 중 하나인 SQL 삽입 공격이라고 합니다. 이 상황을 해결하려면 어떻게 해야 할까요? 이 단원에서는 입력의 유효성을 검사하는 시기, 출력을 인코딩하는 방법 및 매개 변수가 있는 쿼리를 만드는 방법을 설명합니다(위의 악용을 해결). 이러한 세 가지 기술은 애플리케이션에 입력되는 악의적인 입력을 방어하는 주요 방어 기술입니다.
언제 입력의 유효성을 검사해야 할까요?
대답은 항상입니다. 애플리케이션에 대한 모든 입력의 유효성을 검사해야 합니다. 여기에는 URL의 매개 변수, 사용자의 입력, 데이터베이스의 데이터, API의 데이터 및 사용자가 잠재적으로 조작할 수 있다는 명확한 내용이 포함됩니다. 나쁜 입력을 구체적으로 찾아야 하는 차단 목록을 사용하지 말고, 항상 “알려진 좋은” 입력만 허용하는 허용 목록 방식을 사용하세요. 목록 전체를 위험한 입력이라고 생각하기는 불가능하기 때문입니다. 방어벽을 회피할 수 없도록 이 작업을 클라이언트 쪽이 아닌 서버에서 수행하세요(또는 서버에서도 하고 클라이언트 쪽에서도 하세요). 모든 데이터를 신뢰할 수 없는 데이터로 처리하면 대부분의 일반적인 웹앱 취약성으로부터 자신을 보호할 수 있습니다.
ASP.NET 사용하는 경우 프레임워크는 클라이언트와 서버 쪽 모두에서 입력의 유효성을 검사하는 데 큰 지원을 제공합니다.
다른 웹 프레임워크를 사용하는 경우 OWASP 입력 유효성 검사 치트시트에서 사용할 수 있는 입력 유효성 검사를 수행하는 몇 가지 훌륭한 기술이 있습니다.
항상 매개 변수가 있는 쿼리 사용
SQL 데이터베이스는 일반적으로 데이터를 저장하는 데 사용됩니다. 예를 들어 애플리케이션은 데이터베이스에 사용자 프로필 정보를 저장할 수 있습니다. 원시 사용자 입력을 사용하여 코드에서 인라인 SQL이나 다른 데이터베이스 쿼리를 만들어 데이터베이스에 직접 전송해서는 안 됩니다. 이전에 살펴본 대로 이러한 행동은 재앙을 부릅니다.
예를 들어 다음 인라인 SQL 예제와 같은 코드를 만들지 마세요 .
string userName = Request.QueryString["username"]; // receive input from the user BEWARE!
...
string query = "SELECT * FROM [dbo].[users] WHERE userName = '" + userName + "'";
여기서는 텍스트 문자열을 함께 연결하여 쿼리를 만들고, 사용자의 입력을 가져와서 사용자를 조회하는 동적 SQL 쿼리를 생성합니다. 다시 말하지만, 악의적인 사용자가 이 작업을 수행하고 있다는 것을 깨달았거나 다른 입력 스타일을 시도 하여 취약성이 있는지 확인하면 큰 재해가 발생할 수 있습니다. 대신 다음과 같이 매개 변수가 있는 SQL 문이나 저장 프로시저를 사용합니다.
-- Lookup a user
CREATE PROCEDURE sp_findUser
(
@UserName varchar(50)
)
SELECT * FROM [dbo].[users] WHERE userName = @UserName
이 방법을 사용하면 코드에서 안전하게 프로시저를 호출하여 userName
문자열을 전달할 수 있으며 SQL 문의 일부로 처리될까 봐 걱정하지 않아도 됩니다.
항상 출력을 인코딩
시각적으로 또는 문서로 제공하는 모든 출력을 항상 인코딩하고 이스케이프해야 합니다. 그러면 삭제 패스에서 무언가가 누락되었거나 악의적으로 사용 가능한 무언가를 코드에서 실수로 생성한 경우에 데이터를 보호할 수 있습니다. 이 디자인 원칙은 모든 항목이 출력 으로 표시되고 실수로 실행되어야 하는 것으로 해석되지 않도록 합니다. 이는 XSS( 사이트 간 스크립팅 )라고 하는 또 다른 일반적인 공격 기술입니다.
XSS 방지는 일반적인 애플리케이션 요구 사항이므로 이 보안 기술은 ASP.NET 작업을 수행하는 또 다른 영역입니다. 기본적으로 모든 출력이 이미 인코딩되어 있습니다. 다른 웹 프레임워크를 사용하는 경우 OWASP XSS 방지 치트시트를 사용하여 웹 사이트에서 출력 인코딩 옵션을 확인할 수 있습니다.
요약
입력 삭제 및 유효성 검사는 입력의 유효성을 보장하고 안전하게 사용 및 저장하기 위한 필수 요구 사항입니다. 대부분의 최신 웹 프레임워크는 이 작업 중 일부를 자동화할 수 있는 기능을 기본 제공합니다. 원하는 프레임워크의 설명서를 확인하고 제공된 기능을 확인할 수 있습니다. 웹 애플리케이션은 이런 일이 발생하는 가장 일반적인 장소이지만 다른 유형의 애플리케이션도 마찬가지로 취약할 수 있습니다. 새 애플리케이션이 데스크톱 앱이기 때문에 안전하다고는 생각하지 마세요. 다른 사용자가 앱을 사용하여 데이터를 손상하거나 회사의 평판을 손상하는 일이 없도록 계속해서 사용자 입력을 적절하게 처리해야 합니다.