어떻게 sql 주입 을 효과적으로 방지 하 는 방법

SQL 주입 공격 은 해커 가 데이터 베 이 스 를 공격 하 는 데 자주 사용 되 는 수단 중 하나 로 B/S 모델 응용 개발 이 발전 함 에 따라 이런 모델 로 응용 프로그램 을 작성 하 는 프로그래머 도 점점 많아 지고 있다.그러나 프로그래머 의 수준 과 경험 이 다 르 기 때문에 상당 한 프로그래머 들 이 코드 를 작성 할 때 사용자 가 입력 한 데이터 의 합 법성 을 판단 하지 않 아 프로그램 에 안전 위험 이 존재 합 니 다.사용 자 는 데이터베이스 조회 코드 를 제출 할 수 있 습 니 다.프로그램 이 돌아 온 결과 에 따라 그 가 얻 고 싶 은 데 이 터 를 얻 을 수 있 습 니 다.이것 이 바로 SQL Injection,즉 SQL 주입 입 니 다.
배경
만약 에 한 대학교 에서 인터넷 강의 시스템 을 개발 하여 학생 들 에 게 수업 을 선택 한 후에 공 부 를 완성 하 라 고 요구한다 면 데이터 베이스 에 표course가 있 는데 이 표 는 모든 학생 들 의 수강 신청 정보 와 완성 상황 을 저장 하고 구체 적 인 디자인 은 다음 과 같다.

데 이 터 는 다음 과 같 습 니 다.

이 시스템 은 my sql 을 데이터베이스 로 하고 Jdbc 를 사용 하여 데이터 베 이 스 를 조작 합 니 다.시스템 은 이 학생 의 과정 완성 상황 을 조회 하 는 기능 을 제공 합 니 다.코드 는 다음 과 같 습 니 다.

@RestController
public class Controller {
    
    @Autowired
    SqlInject sqlInject;
    
    @GetMapping("list")
    public List<Course> courseList(@RequestParam("studentId") String studentId){
        List<Course> orders = sqlInject.orderList(studentId);
        return orders;
    }
}

@Service
public class SqlInject {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public List<Course> orderList(String studentId){
        String sql = "select id,course_id,student_id,status from course where student_id = "+ studentId;
        return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
    }
}
2 주입 공격 시범
1.정상 적 인 상황 에서 한 학생 이 선택 한 과정 과 완성 상황 을 조회 하면 입력student_id만 하면 관련 데 이 터 를 찾 을 수 있다.

응답 결과 에 따라 우 리 는 곧 대응 하 는 sql 을 쓸 수 있 습 니 다.다음 과 같 습 니 다.

select id,course_id,student_id,status 
from course 
where student_id = 4
2.만약 에 우리 가 이 표 의 모든 데 이 터 를 얻 으 려 면 위 에 있 는 sql 의 where 조건 이 항상 유지 되 어야 합 니 다.

select id,course_id,student_id,status 
from course 
where student_id = 4 or 1 = 1 
인 터 페 이 스 를 요청 할 때studendId를 4 or 1=1 로 설정 하면 이 sql 의 where 조건 이 일정 합 니 다.sql 도 아래 와 같 습 니 다.

select id,course_id,student_id,status 
from course 
요청 결 과 는 다음 과 같 습 니 다.우 리 는 이 표 의 모든 데 이 터 를 받 았 습 니 다.

3.my sql 버 전 번호 조회,사용union맞 춤 sql

union select 1,1,version(),1

4.데이터베이스 이름 조회

union select 1,1,database(),1

5.mysql 현재 사용자 의 모든 라 이브 러 리 조회

union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1

위의 이 시연 들 을 다 본 후에 너 는 두 려 웠 니?당신 의 모든 데이터 설정 이 완전히 드 러 났 습 니 다.그 밖 에 많은 조작 을 할 수 있 습 니 다.데이터 업데이트,라 이브 러 리 삭제,표 삭제 등 도 할 수 있 습 니 다.
3.sql 주입 을 어떻게 방지 합 니까?
1.코드 층 이 sql 주입 공격 을 방지 하 는 가장 좋 은 방안 은 sql 사전 컴 파일 입 니 다.

public List<Course> orderList(String studentId){
    String sql = "select id,course_id,student_id,status from course where student_id = ?";
    return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}
이렇게 하면 우리 가 들 어 오 는 매개 변수4 or 1 = 1는 하나의student_id로 여 겨 지기 때문에 sql 주입 이 나타 나 지 않 을 것 이다.
2.모든 데이터 의 유형 을 확인 합 니 다.예 를 들 어 숫자,데이터 베 이 스 는 int 형식 으로 저장 해 야 합 니 다.
3.데이터 길 이 를 규정 하면 어느 정도 sql 주입 을 방지 할 수 있 습 니 다.
4.데이터베이스 권한 을 엄 격 히 제한 하여 sql 주입 의 위 해 를 최대한 줄 일 수 있 습 니 다.
5.일부 sql 이상 정보 에 직접 응답 하지 않도록 합 니 다.sql 이상 이 발생 한 후 사용자 정의 이상 으로 응답 합 니 다.
6.필터 파라미터 에 포 함 된 데이터베이스 키워드

@Component
public class SqlInjectionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)servletRequest;
        HttpServletRequest res=(HttpServletRequest)servletResponse;
        //         
        Enumeration params = req.getParameterNames();
        String sql = "";
        while (params.hasMoreElements()) {
            //      
            String name = params.nextElement().toString();
            //        
            String[] value = req.getParameterValues(name);
            for (int i = 0; i < value.length; i++) {
                sql = sql + value[i];
            }
        }
        if (sqlValidate(sql)) {
            throw new IOException("                ");
        } else {
            chain.doFilter(servletRequest,servletResponse);
        }
    }

    /**
     *      
     * @param str
     * @return
     */
    protected static boolean sqlValidate(String str) {
        //       
        str = str.toLowerCase();
        //     sql   ,      
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
        String[] badStrs = badStr.split("\\|");
        for (int i = 0; i < badStrs.length; i++) {
            if (str.indexOf(badStrs[i]) >= 0) {
                return true;
            }
        }
        return false;
    }
}
sql 주입 을 효과적으로 방지 하 는 방법 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 sql 주입 방지 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기