일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- vuetify
- AI
- leetcode
- nginx
- Clone
- machine learning
- var
- scss
- C++
- Python
- VUE
- loop
- property
- git
- 앙상블
- dotenv
- generic
- docker
- webpack
- security
- condition
- C#
- type
- BOJ
- bash
- vue.js
- 보안
- npm
- TypeScript
- JavaScript
- Today
- Total
ice rabbit programming
[보안] 인젝션 본문
일전에 한 대기업 인턴에 다닐 때, 개인 과제로 웹 전반을 제작하였었다. 프론트엔드와 백엔드 모두를 개발하다보니 의문점이 들어 당시 멘토였던 차장님께 질문을 했었다.
"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. 입력 값에 필터링 정책 사용
-> 동적 쿼리 사용 시, 필터링 해야하는 특수문자 및 문자열에 주의한다.
-> 입력값에 대한 크기나 유형에 제한을 두어, 부적절한 입력값이 삽입되는 것을 방지해야 한다.
'Development > Secutiry' 카테고리의 다른 글
[보안] 접근제어 (0) | 2021.12.19 |
---|---|
[보안] 계정 및 인증 관리 (0) | 2021.10.05 |
[보안] 쿠키 및 세션 관리 (0) | 2021.03.24 |
[보안] 파일 업로드/다운로드 취약점 (0) | 2021.01.17 |
[보안] XSS(사이트 간 스크립팅) (0) | 2020.05.01 |