자바 보안 코딩 가이드 : 입력 주입 주입

소개

인젝션 문제는 보안에서 매우 흔한 문제인데, 오늘은 자바에서 SQL 인젝션과 XML 인젝션을 방지하는 방법에 대해 논의하겠습니다.

SQL 주입

SQL 주입이란 무엇입니까?

SQL 인젝션은 사용자가 특정 매개 변수를 입력하는 것을 의미하며, 결국 SQL 실행이 프로그래머의 원래 의도에서 벗어나게되어 권한이 없거나 다른 유형의 오류가 발생합니다.

즉, 사용자의 입력으로 인해 SQL의 의미가 바뀌 었습니다.

가장 일반적으로 사용되는 로그인 SQL 문을 사용하여 다음 SQL 문을 작성할 수 있습니다.

select * from user where username='<username>' and password='<password>'

사용자 이름과 비밀번호를 전달해야합니다.

이 SQL 문을 삽입하는 방법은 무엇입니까?

사용자의 사용자 이름 입력이 다음과 같을 때 매우 간단합니다.

somebody' or '1'='1

그러면 전체 SQL 문이 다음과 같이됩니다.

select * from user where username='somebody' or '1'='1' and password='<password>'

누군가가 유효한 사용자이면 언어가 실행되거나 전혀 실행되지 않으므로 암호를 확인하지 않고 사용자 정보가 반환됩니다.

마찬가지로 악의적 인 공격자는 동일한 결과를 얻기 위해 암호에 다음 내용을 입력 할 수 있습니다.

' or '1'='1

전체 SQL은 다음과 같이 구문 분석됩니다.

select * from user where username='somebody' and password='' or '1'='1'

이 문은 모든 사용자 정보를 반환하므로 존재하는 사용자 이름을 모르더라도 SQL 문으로 판단 할 수 있습니다.

이것이 SQL 주입입니다.

자바의 SQL 주입

Java에서 가장 일반적으로 사용되는 것은 JDBC를 통해 데이터베이스를 운영하는 것이며 JDBC를 사용하여 연결을 생성 한 후 SQL 문을 실행할 수 있습니다.

Java에서 JDBC SQL 주입을 사용하는 예를 살펴 보겠습니다.

먼저 일반 JDBC 연결을 만듭니다.

    public Connection getConnection() throws ClassNotFoundException, SQLException {
    
    
        Connection con = null;
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("数据库驱动加载成功");
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql?characterEncoding=UTF-8", "root", "");
            System.out.println("数据库连接成功");
          return con;
    }

그런 다음 SQL 문을 직접 어셈블하고 다음을 호출합니다.

public void jdbcWithInjection(String username,char[] password) throws SQLException, ClassNotFoundException {
    
    
        Connection connection = getConnection();
        if (connection == null) {
    
    
            // Handle error
        }
        try {
    
    
            String pwd = encodePassword(password);

            String sqlString = "SELECT * FROM user WHERE username = '"
                    + username +
                    "' AND password = '" + pwd + "'";
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sqlString);

            if (!rs.next()) {
    
    
                throw new SecurityException(
                        "User name or password incorrect"
                );
            }
        } finally {
    
    
            try {
    
    
                connection.close();
            } catch (SQLException x) {
    
    
            }
        }
    }

위의 예에서는 사용자 이름 만 삽입되고 비밀번호는 삽입되지 않습니다. encodePassword 메소드를 사용하여 비밀번호를 변환했기 때문입니다.

public String encodePassword(char[] password){
    
    
        return Base64.getEncoder().encodeToString(new String(password).getBytes());
    }

PreparedStatement 사용

SQL 주입을 방지하기 위해 일반적으로 PreparedStatement를 사용하는 것이 좋습니다. java.sql.PreparedStatement는 SQL 주입을 방지하기 위해 입력 매개 변수를 이스케이프 할 수 있습니다.

PreparedStatement는 올바르게 사용해야하며, 잘못 사용하면 SQL 주입이 발생합니다.

잘못된 사용의 예를 살펴 보겠습니다.

String sqlString = "SELECT * FROM user WHERE username = '"
                    + username +
                    "' AND password = '" + pwd + "'";
            PreparedStatement stmt = connection.prepareStatement(sqlString);
            ResultSet rs = stmt.executeQuery();

위의 코드에서 우리는 여전히 SQL을 직접 어셈블했고, 결국에는 prepareStatement를 사용했지만 효과를 얻지 못했습니다.

올바른 사용법의 예는 다음과 같습니다.

String sqlString =
                    "select * from user where username=? and password=?";
            PreparedStatement stmt = connection.prepareStatement(sqlString);
            stmt.setString(1, username);
            stmt.setString(2, pwd);
            ResultSet rs = stmt.executeQuery();

이스케이프 될 수 있도록 사용자 입력을 PreparedStatement에 대한 매개 변수로 설정해야합니다.

XML에 SQL 삽입

XML (Extensible Markup Language)은 데이터를 저장, 구조화 및 전송할 수 있도록 설계되었습니다. 플랫폼 독립성, 유연성 및 상대적 단순성으로 인해 XML은 많은 응용 프로그램에서 사용되었습니다. 그러나 XML의 다양성으로 인해 XML 주입을 포함한 다양한 공격에 취약합니다.

그렇다면 XML 주입이란 무엇입니까? 예를 들어 보겠습니다.

<item>
  <name>Iphone20</name>
  <price>5000.0</price>
  <quantity>1</quantity>
</item>

위의 예에서는 XML을 사용하여 iphone20의 가격과 수량을 정의했습니다. iphone20은 5000 위안입니다.

위의 XML에서 수량이 사용자가 입력 한 데이터이면 사용자는 다음과 같이 입력 할 수 있습니다.

1</quantity><price>20.0</price><quantity>1

최종 XML 파일은 다음과 같습니다.

<item>
  <name>Iphone20</name>
  <price>5000.0</price>
  <quantity>1</quantity>
  <price>20.0</price><quantity>1</quantity>
</item>

일반적으로 XML 구문 분석 과정에서 중복 태그를 발견하면 다음 태그가 이전 태그를 덮어 씁니다.

결과적으로 iphone20의 현재 가격은 20 위안으로 매우 비용 효율적입니다.

XML 주입 자바 코드

Java 코드에서 XML 주입이 어떻게 구현되는지 살펴 보겠습니다.

    public String createXMLInjection(String quantity){
    
    
        String xmlString = "<item>\n<name>Iphone20</name>\n"
                + "<price>5000.0</price>\n" + "<quantity>" + quantity
                + "</quantity></item>";
        return xmlString;
    }

사용자가 입력 한 수량을 XML 스 플라이 싱으로 직접 사용하는 것을 볼 수 있는데, 이는 분명히 문제가됩니다.

그것을 해결하는 방법? 두 가지 방법이 있습니다.

  • 첫 번째 방법

첫 번째 방법은 사용자가 입력 한 수량을 확인하는 것입니다.

    public String createXML(String quantity){
    
    
        int count = Integer.parseUnsignedInt(quantity);
        String xmlString = "<item>\n<name>Iphone20</name>\n"
                + "<price>5000.0</price>\n" + "<quantity>" + count
                + "</quantity></item>";
        return xmlString;
    }

위의 코드에서는 사용자의 불법 입력을 피하기 위해 수량을 Integer로 변환했습니다.

  • 두 번째 방법

두 번째 방법은 XML 스키마를 사용하여 생성 된 XML의 형식을 확인하는 것입니다.

이 XML 스키마를 정의하는 방법을 살펴 보겠습니다.


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="item">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="price" type="xs:decimal"/>
      <xs:element name="quantity" type="xs:nonNegativeInteger"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
</xs:schema>

위에서 XML 요소의 시퀀스를 정의했습니다. 사용자가 정의되지 않은 형식으로 다른 XML을 입력하면 오류가보고됩니다.

해당 자바 코드를 작성하는 방법을 살펴 보겠습니다.

StreamSource ss = new StreamSource(new File("schema.xsd"));
            Schema schema = sf.newSchema(ss);
            SAXParserFactory spf = SAXParserFactory.newInstance();
            spf.setSchema(schema);
            SAXParser saxParser = spf.newSAXParser();
            XMLReader reader = saxParser.getXMLReader();
            reader.setContentHandler(defHandler);
            reader.parse(xmlStream);

위의 XML 확인 코드를 나열했습니다. 전체 코드는 기사 끝에있는 코드 링크를 참조 할 수 있습니다. 여기에 하나씩 게시하지 않겠습니다.

이 기사의 코드 :

java-base-9-to-20 / tree / master / security 알아보기

이 기사는 http://www.flydean.com/java-security-code-line-injection/ 에 포함되었습니다 .

가장 인기있는 해석, 가장 심오한 건조 제품, 가장 간결한 튜토리얼 및 모르는 많은 팁이 여러분이 발견하기를 기다리고 있습니다!

내 공식 계정에 관심을 기울이는 것을 환영합니다 : "그것들을 프로그래밍"하고, 기술을 알고, 더 잘 알고 있습니다!

추천

출처blog.csdn.net/superfjj/article/details/109021091