자바 보안 인 코딩 안내: 입력 검사

5784 단어
목차
  • 안내
  • 문자열 표준화 후 검증
  • 신뢰 할 수 없 는 문자열 의 포맷 에 주의 하 십시오
  • Runtime. exec () 사용 조심
  • 정규 표현 식 의 일치
  • 간단 한 소개
    자바 프로그램의 안전 을 위해 서 는 모든 외부 사용자 의 입력 이 악의 적 인 공격 의도 가 있 을 수 있다 고 생각 합 니 다. 모든 사용자 의 입력 을 어느 정도 검증 해 야 합 니 다.
    본 고 는 모 두 를 데 리 고 사용자 가 입력 하고 검증 하 는 일부 장면 을 연구 할 것 이다.같이 보 자.
    문자열 표준화 후 검사 하기
    보통 문자열 검 사 를 할 때 특수 문 자 를 걸 러 내 고 걸 러 낸 후에 문자열 검 사 를 해 야 합 니 다.
    자바 에서 문 자 는 유 니 코드 를 기반 으로 인 코딩 된 것 을 알 고 있 습 니 다.그러나 유 니 코드 에 서 는 같은 문자 에 다른 표현 형식 이 있 을 수 있 습 니 다.그래서 우 리 는 문 자 를 표준화 해 야 한다.
    자바 에는 문자 표준화 문 제 를 처리 하 는 전문 적 인 클래스 Normalizer 가 있 습 니 다.
    우 리 는 다음 예 를 보 자.
        public void testNormalizer(){
            System.out.println(Normalizer.normalize("\u00C1", Normalizer.Form.NFKC));
            System.out.println(Normalizer.normalize("\u0041\u0301", Normalizer.Form.NFKC));
        }
    

    출력 결과:
    Á
    Á
    

    둘 의 유 니 코드 는 다 르 지만 최종 적 으로 나타 내 는 문 자 는 같다 는 것 을 알 수 있다.그래서 우 리 는 문자 검증 을 할 때 반드시 normalize 처 리 를 해 야 한다.
    아래 의 예 를 고려 하 다.
        public void falseNormalize(){
            String s = "\uFE64" + "script" + "\uFE65";
            Pattern pattern = Pattern.compile("[<>]"); //         
            Matcher matcher = pattern.matcher(s);
            if (matcher.find()) {
                throw new IllegalStateException();
            }
            s = Normalizer.normalize(s, Normalizer.Form.NFKC);
        }
    

    그 중에서 \ uFE 64 는 입력 한 문자열 에 괄호 가 포함 되 어 있 는 지 여 부 를 판단 하 는 것 을 의미 하지만 유 니 코드 문자 가 직접 들 어 오기 때문에 직접 copile 은 감지 되 지 않 습 니 다.
    우 리 는 코드 에 대해 아래 의 변경 을 진행 해 야 한다.
        public void trueNormalize(){
            String s = "\uFE64" + "script" + "\uFE65";
            s = Normalizer.normalize(s, Normalizer.Form.NFKC);
            Pattern pattern = Pattern.compile("[<>]"); //         
            Matcher matcher = pattern.matcher(s);
            if (matcher.find()) {
                throw new IllegalStateException();
            }
        }
    

    먼저 normalize 작업 을 한 다음 에 문자 검증 을 합 니 다.
    신뢰 할 수 없 는 문자열 의 포맷 에 주의 하 십시오.
    우 리 는 문자열 을 포맷 하기 위해 포맷 을 자주 사용 합 니 다. 포맷 할 때 문자열 에 사용자 가 입력 한 정보 가 들 어 있 으 면 주의해 야 합 니 다.
    아래 의 예 를 보십시오.
        public void wrongFormat(){
            Calendar c = new GregorianCalendar(2020, GregorianCalendar.JULY, 27);
            String input=" %1$tm";
            System.out.format(input + "      ,         %1$terd  ", c);
        }
    

    대충 봐 도 괜 찮 지만, 우리 input 에는 포맷 정보 가 포함 되 어 있 습 니 다. 마지막 출력 결과:
     07      ,         27rd  
    

    변 형 된 것 은 우리 가 시스템 내부 의 정 보 를 얻 었 기 때문에 어떤 상황 에서 시스템 의 내부 논 리 를 폭로 할 수 있다.
    위의 예 에서 우 리 는 input 도 하나의 매개 변수 로 해 야 한다. 다음 과 같다.
        public void rightFormat(){
            Calendar c = new GregorianCalendar(2020, GregorianCalendar.JULY, 27);
            String input=" %1$tm";
            System.out.format("%s      ,         %terd  ",input, c);
        }
    

    출력 결과:
     %1$tm      ,         27rd  
    

    Runtime. exec () 사용 조심
    Runtime. exec () 가 시스템 명령 을 호출 하 는 데 사용 되 는 것 을 알 고 있 습 니 다. 악의 적 인 사용자 가 "rm - rf /" 를 호출 하면 모든 것 이 망 합 니 다.
    따라서 저 희 는 Runtime. exec () 를 호출 할 때 사용자 의 입력 을 조심해 야 합 니 다.
    다음 의 예 를 보십시오.
        public void wrongExec() throws IOException {
            String dir = System.getProperty("dir");
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(new String[] {"sh", "-c", "ls " + dir});
        }
    

    위의 예 에서, 우 리 는 시스템 속성 에서 dir 를 읽 은 다음, 시스템 의 ls 명령 을 실행 하여 dir 의 내용 을 보 았 다.
    만약 악성 사용자 가 dir 에 값 을 부여 한다 면:
    /usr & rm -rf /
    

    그러면 시스템 이 실제로 실행 하 는 명령 은:
    sh -c 'ls /usr & rm -rf /'
    

    악의 적 으로 삭제 된다.
    위의 문 제 를 해결 하 는 데 도 몇 가지 방법 이 있 습 니 다. 첫 번 째 방법 은 입력 에 대해 검 사 를 하 는 것 입 니 다. 예 를 들 어 우 리 는 dir 에 특정한 문자 만 포함 하 는 것 입 니 다.
        public void correctExec1() throws IOException {
            String dir = System.getProperty("dir");
            if (!Pattern.matches("[0-9A-Za-z@.]+", dir)) {
                // Handle error
            }
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(new String[] {"sh", "-c", "ls " + dir});
        }
    

    두 번 째 방법 은 switch 문 구 를 사용 하여 특정한 입력 을 제한 하 는 것 이다.
        public void correctExec2(){
            String dir = System.getProperty("dir");
            switch (dir){
                case "/usr":
                    System.out.println("/usr");
                    break;
                case "/local":
                    System.out.println("/local");
                    break;
                default:
                    break;
            }
        }
    

    또 하 나 는 Runtime. exec () 방법 을 사용 하지 않 고 자바 자체 가 져 오 는 방법 이다.
    정규 표현 식 의 일치
    정규 표현 식 을 구축 하 는 과정 에서 사용자 정의 입력 을 사용 하면 같은 것 도 입력 검 사 를 해 야 합 니 다.
    다음 정규 표현 식 을 고려 합 니 다:
    (.*? +public\[\d+\] +.*.*)
    

    위의 표현 식 은 public [1234] 와 같은 로그 정보 에서 사용자 의 입력 을 검색 하려 는 것 입 니 다.
    그러나 사용 자 는 실제로 아래 의 정 보 를 입력 할 수 있다.
    .*)|(.*
    

    최종 적 으로 정규 표현 식 이 아래 모양 으로 변 합 니 다:
    (.*? +public\[\d+\] +.*.*)|(.*.*)
    

    모든 로그 정보 와 일치 합 니 다.
    해결 방법 도 두 가지 가 있 는데 하 나 는 화이트 리스트 를 사용 하여 사용자 의 입력 을 판단 하 는 것 이다.하 나 는 Pattern. quote () 를 사용 하여 악성 문 자 를 바 꾸 는 것 입 니 다.
    본문 코드:
    learn-java-base-9-to-20/tree/master/security
    본문 은 이미 수록 되 었 다.http://www.flydean.com/java-security-code-line-input/
    가장 통속 적 인 해석, 가장 깊 은 건어물, 가장 간결 한 튜 토리 얼, 당신 이 모 르 는 작은 기술 들 이 당신 을 기다 리 고 있 습 니 다!
    나의 공식 번호 에 관심 을 가 져 주 십시오. "프로그램 그런 일 들", 기술 을 알 고 당신 을 더 잘 알 고 있 습 니 다!

    좋은 웹페이지 즐겨찾기