ice rabbit programming

[보안] 인젝션 본문

Development/Secutiry

[보안] 인젝션

판교토끼 2020. 4. 19. 20:49

일전에 한 대기업 인턴에 다닐 때, 개인 과제로 웹 전반을 제작하였었다. 프론트엔드와 백엔드 모두를 개발하다보니 의문점이 들어 당시 멘토였던 차장님께 질문을 했었다.

"Client에서 유효성 검사를 했는데, Server에서도 유효성 검사를 해야 하나요?"

당시 답변은, Client를 통하지 않은 request도 Server로 들어올 수 있으니, 해야 한다는 것이었다. 옳다고 생각하여 두 곳 모두에서 유효성 검사를 진행하기는 했지만, Insomnia나 Postman 등을 통한 request 정도로 생각하고 있었는데, 인젝션에 대해서 알게 되면서 그 때의 답을 완벽히 알게 되었고, 유효성 검사의 중요성을 다시금 알게 되었다.


SQL 인젝션(Injection) : Client의 입력 값을 조작하여(인증우회) DB를 공격한다.
-> 즉, 외부에서 받은 값으로 동적 쿼리를 생성하여 실행한다.

그렇기 때문에 Client에서 일차적으로 걸러야하며, 공격자들이 Client를 통하지 않고도 공격할 수 있으므로 Server에서도 유효성 검사가 필수적인 것이다.

예를 들어, 다음과 같은 코드가 있다고 생각해보자.

router.get("/",function(req,res,next) {
    var sql = "select * from Students where name=?"
    var name = req.name;
    con.query(sql,name,function(err, result, fields){
    	res.send({
        	"status":"success",
        	"result":JSON.stringify(result)
        });
    });
});

GET 방식으로 들어온 request에서 name에 해당하는 학생의 정보를 찾아오는 코드이다. 언뜻 보기에는 문제가 없어 보인다. 그런데 만약 name에 *이 들어오게 되면?

SQL은 select * from Students where name=*로 처리가 될 것이며, 해당 학생의 정보가 아닌 모든 학생의 정보를 반환하게 될 것이다. 이것이 바로 SQL 인젝션 공격이다. 그러므로 입력값에 대한 필터링이 필요한 것이다.

외부 입력값에 대한 프로세스는 다음과 같아야 한다.

외부 Data -> 규범화 및 정규화 -> 입력값 Sanitize -> 검증 -> DB
(* Sanitize : 안전한 값으로 변환, ex. 문자 제거)


인젝션 방법들과 그 취약점 진단법을 알아 보자.

1. Form-Based SQL 인젝션
-> 입력 폼에 SQL을 넣어서 공격한다.
-> 입력 폼에서 유효성 검사를 실시하여 대응한다.

2. Stored Procedure SQL 인젝션
-> 프로시저를 악용한다. 즉, 시스템에 관여가 가능하다.
-> 불필요한 저장 프로시저를 삭제하는 것으로 대응한다.

3. Error Based SQL 인젝션
-> 에러 코드를 이용하여 공격한다.
500 에러 : 특수문자 쿼리처리가 가능 -> SQL 인젝션 공격 가능
400 에러 : 특수문자 쿼리처리 불가 -> 공격 불가

4. UNION SQL 인젝션
-> JOIN을 이용하여 인증을 우회한다.

5. Blind SQL 인젝션
-> 쿼리 결과의 True/False를 통해 공격한다. 무슨 말이냐면, 결과를 뿌려주지 않더라도 만약 쿼리를 불러올 경우에 응답 길이나 시간 등이 다르다는 것을 이용한다. 그래서 첫 글자, 두 번째 글자 등을 노가다로 넣어보면서 true값들을 찾아서 뚫는 방법이다.

6. 명령어 인젝션
-> 외부 입력값이 검증 없이 명령을 실행한다. 즉, 허가되지 않았음에도 쿼리를 날려 허가되지 않은 정보에 접근할 수 있게 된다.
-> select 값 등도 검증이 필요하다(proxy 조작 가능).

 

위 모두를 예방하는 방법은 다음과 같다.

1. 정적 쿼리 구조 사용
-> 구조 변경이 불가능하도록 한다. ORM에서도 정적 쿼리를 쓰는 편이 좋다.

2. 입력 값에 필터링 정책 사용
-> 동적 쿼리 사용 시, 필터링 해야하는 특수문자 및 문자열에 주의한다.
-> 입력값에 대한 크기나 유형에 제한을 두어, 부적절한 입력값이 삽입되는 것을 방지해야 한다.