Examples에서 예시 하나를 복사해온다. (나중에 사용할 API 가이드에 맞춰서 수정할 예정)
Ajax
:: JavaScript의 라이브러리중 하나이며 Asynchronous Javascript And Xml(비동기식 자바스크립트와xml)의 약자.
브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법 (기본적으로HTTP프로토콜은 클라이언트쪽에서Request를 보내고Server쪽에서 Response를 받으면 이어졌던 연결이 끊기게 되어있음)
ⓐ SQL Injection : SQL 문 사용 시 공격자의 입력 값이 정상적인 요청에 영향을 주는 취약점
ⓑ Command Injection : OS Command 사용 시 사용자의 입력 데이터에 의해 실행되는 Command를 변조 할 수 있는 취약점
ⓒ Server Side Template Injection(SSTI) : 템플릿 변환 도중 사용자의 입력 데이터가 템플릿으로 사용돼 발생하는 취약점
ⓓ Path Traversal : URL / File Path를 사용 시 사용자의 입력 데이터에 의해 임의의 경로에 접근하는 취약점
ⓔ Server Side Request Forgery(SSRF) : 공격자가 서버에서 변조된 요청을 보낼 수 있는 취약점
ⓐ-1 SQL Injection
웹 어플리케이션에서 로그인/검색과 같이 사용자의 입력 데이터를 기반으로 DBMS에 저장된 정보를 조회하는 기능 등을 구현하기 위해 SQL 쿼리에 사용자의 입력 데이터를 추가하여 DBMS에 요청하는데, 그 과정에서 사용자의 입력이 SQL 쿼리에 삽입되어 SQL 구문으로 해석되거나 문법적으로 조작하게 되면 개발자가 의도하지 않은 임의의 쿼리가 실행될 수 있다.
즉, SQL 쿼리에 사용자의 입력 값이 삽입돼 사용자가 원하는 쿼리를 실행할 수 있는 취약점이다.
대표적인 예시로, 로그인 시
SELECT * FROM users WHERE uid = '{uid}' and upw='{upw}'; 라는 쿼리가 실행될 때
'를 기준으로 문자열을 구분하고 있다는 점을 집중해서 보자.
만약 사용자가 입력에 ' 문자를 포함해 해당 문자열을 탈출하고 뒷 부분에 새로운 쿼리를 작성하여 전달하면 DBMS는 사용자가 직접 작성한 쿼리를 실행시키는 것이다.
'{uid}' 에 admin을 , '{upw}' 에 1'or'1 을 작성한다면, or 연산을 이용해 참의 조건이 만족되므로 admin의 데이터에 접근이 가능하게 된다.
+ (or연산은A or B와 같은 구조일 경우 A와 B 중 하나라도 참(True)인 경우 결과는 참이된다.)
ⓐ-2 SQL Injection 방어
SQL Injection을 막기 위해 권장하는 방법
:: ORM(Object Relational Mapper의 약자로써 SQL의 쿼리 작성을 돕기위한 라이브러리)과 같이 검증된 SQL 라이브러리 사용
이를 통해 개발자가 직접 쿼리를 작성하는 Raw 쿼리를 사용하지 않아도 기능 구현이 가능하여, SQL Injection으로부터 상대적으로 안전하다.
ORM은 생산성을 위해서도 사용하지만 사용자의 입력 값을 라이브러리 단에서 스스로 escape하고 쿼리에 매핑시키기 때문에 안전하게 SQL 쿼리를 실행한다.
ⓑ-1 Command Injection
:: OS Command는 linux (ls, pwd, ping, zip..), windows (dir, pwd, ping..) 등의 OS에서 사용하는 명령어
:: 이러한 명령어를 실행하기 위해 PHP, NodeJS, Python과 같은 함수들이 존재한다.
OS Command는 내부적으로 셸(Shell)을 이용해 실행하는데, 셸은 사용자 편의성을 위해 한 줄에 여러 명령어를 실행하는 특수 문자가 여럿 존재한다.
따라서 이를 사용할 때 사용자의 입력 값을 검증하지 않고 함수의 인자로 전달한다면?
여러 특수 문자를 이용해 사용자가 원하는 명령어를 함께 실행할 수 있다.
` `
명령어 치환
`` 안에 들어있는 명령어를 실행한 결과로 치환된다.
$( )
명령어 치환
$( ) 안에 들어있는 명령어를 실행한 결과로 치환. 중복 가능
&&
명령어 연속 실행
한 줄에 여러 명령어를 사용하고 싶을 때. 앞 명령어에서 에러가 발생하지 않아야 뒷 명령어 실행 가능
||
명령어 연속 실행
한 줄에 여러 명령어를 사용하고 싶을 때. 앞 명령어에서 에러가 발생해야 뒷 명령어 실행 가능
;
명령어 구분자
한 줄에 여러 명령어를 사용하고 싶을 때. 단순 구분자. 앞 명령어의 에러 유무 상관없이 뒷 명령어도 실행
① $conn = mysqli_connect('localhost','root','1111','mysqls');
// 데이터베이스에 PHP 접속 //함수에 들어가는 인자 : 호스트(데이터베이스의 서버 주소), 사용자 네임, 비밀번호, 데이터베이스(스키마) 이름
② $sql = "INSERT INTO topic (title, description, created) VALUES(
'{$_POST['title']}', '{$_POST['description']}',
NOW()
)
";
// sql 문 작성. html에서 POST 방식으로 작성할 것이기 때문에 $_POST['name'] 방식 사용
③ $result = mysqli_query($conn,$sql); //mysqli_query( ): php가 클라이언트가 되어 데이터베이스 서버에 sql문 실행
//실패 시 false, 성공 시 객체 리턴
// 함수에 들어가는 인자 : (데이터베이스 접속 정보 변수, sql문)
④ if ($result === false){ echo mysqli_error($conn);
// mysqli_error( ) :저장하는 과정에서 어떤 에러가 발생했는지 알려주는 함수
// 그러나 사용자에게 그대로 보여주면 보안 위협이 있으므로 아래와 같이 진행 echo '저장하는 과정에서 문제가 생겼습니다. 관리자에게 문의해주세요'; error_log(mysqli_error($conn)); //error_log( ): 아파치 error log 디렉토리에 에러사항이 기록됨 } else { echo '성공했습니다.'; }