MySQL 사용자 이름과 암호를 디 컴파일로부터 보호하려면 어떻게해야합니까?
Java .class
파일은 상당히 쉽게 디 컴파일 될 수 있습니다. 코드에서 로그인 데이터를 사용해야하는 경우 데이터베이스를 어떻게 보호 할 수 있습니까?
암호를 코드에 하드 코딩하지 마십시오. 이것은 최근에 가장 위험한 프로그래밍 실수 25 가지 에서 제기되었습니다 .
비밀 계정과 암호를 소프트웨어에 하드 코딩하는 것은 숙련 된 리버스 엔지니어에게 매우 편리합니다. 암호가 모든 소프트웨어에서 동일하면 암호가 불가피하게 알려질 때 모든 고객이 취약 해집니다. 그리고 하드 코딩되어 있기 때문에 고치는 것은 엄청난 고통입니다.
암호를 포함한 구성 정보를 응용 프로그램이 시작될 때 읽는 별도의 파일에 저장해야합니다. 이것이 디 컴파일의 결과로 암호가 유출되는 것을 방지하는 유일한 방법입니다 (시작하기 위해 절대로 바이너리로 컴파일하지 마십시오).
이 일반적인 실수에 대한 자세한 내용은 CWE-259 기사를 참조하십시오 . 이 기사에는 문제에 대한보다 철저한 정의, 예 및 기타 많은 정보가 포함되어 있습니다.
Java에서이를 수행하는 가장 쉬운 방법 중 하나는 Preferences 클래스를 사용하는 것입니다. 모든 종류의 프로그램 설정을 저장하도록 설계되었으며 일부에는 사용자 이름과 암호가 포함될 수 있습니다.
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
위의 코드 setCredentials
에서 사용자 이름과 암호를 묻는 대화 상자를 표시 한 후 메서드를 호출 할 수 있습니다. 데이터베이스에 연결해야하는 경우 getUsername
및 getPassword
메서드를 사용 하여 저장된 값을 검색 할 수 있습니다 . 로그인 자격 증명은 바이너리에 하드 코딩되지 않으므로 디 컴파일로 인해 보안 위험이 발생하지 않습니다.
중요 참고 : 기본 설정 파일은 일반 텍스트 XML 파일입니다. 권한이없는 사용자가 원시 파일 (UNIX 권한, Windows 권한 등)을 보지 못하도록 적절한 조치를 취해야합니다. Linux에서는 적어도 이것은 문제가되지 않습니다.을 호출 Preferences.userNodeForPackage
하면 현재 사용자의 홈 디렉토리에 XML 파일이 생성되므로 다른 사용자가 읽을 수 없습니다. Windows에서는 상황이 다를 수 있습니다.
더 중요한 참고 사항 : 이 답변에 대한 의견과이 상황에 대한 올바른 아키텍처가 무엇인지에 대한 다른 의견에서 많은 논의가있었습니다. 원래 질문은 응용 프로그램이 사용되는 컨텍스트를 실제로 언급하지 않으므로 제가 생각할 수있는 두 가지 상황에 대해 이야기하겠습니다. 첫 번째는 프로그램을 사용하는 사람이 이미 데이터베이스 자격 증명을 알고 있고이를 알 권한이있는 경우입니다. 두 번째는 개발자 인 귀하가 프로그램을 사용하는 사람으로부터 데이터베이스 자격 증명을 비밀로 유지하려는 경우입니다.
첫 번째 경우 : 사용자는 데이터베이스 로그인 자격 증명을 알 수있는 권한이 있습니다.
이 경우 위에서 언급 한 솔루션이 작동합니다. Java Preference
클래스는 사용자 이름과 암호를 일반 텍스트로 저장하지만 기본 설정 파일은 권한이있는 사용자 만 읽을 수 있습니다. 사용자는 기본 설정 XML 파일을 열고 로그인 자격 증명을 읽을 수 있지만 사용자가 시작할 자격 증명을 알고 있었기 때문에 보안 위험이 없습니다.
두 번째 사례 : 사용자로부터 로그인 자격 증명을 숨기려고
이것은 더 복잡한 경우입니다. 사용자는 로그인 자격 증명을 몰라도 데이터베이스에 액세스해야합니다. 이 경우 응용 프로그램을 실행하는 사용자는 데이터베이스에 직접 액세스 할 수 있으므로 프로그램이 로그인 자격 증명을 미리 알아야합니다. 위에서 언급 한 솔루션은이 경우에 적합하지 않습니다. 데이터베이스 로그인 자격 증명을 기본 설정 파일에 저장할 수 있지만 사용자는 소유자가되므로 해당 파일을 읽을 수 있습니다. 사실,이 경우를 안전하게 사용하는 좋은 방법은 없습니다.
올바른 사례 : 다중 계층 아키텍처 사용
The correct way to do it is to have a middle layer, in between your database server and your client application, that authenticates individual users and allows a limited set of operations to be performed. Each user would have their own login credentials, but not for the database server. The credentials would allow access to the middle layer (the business logic tier) and would be different for each user.
Every user would have their own username and password, which could be stored locally in a preferences file without any security risk. This is called a three-tier architecture (the tiers being your database server, business logic server, and client application). It is more complex, but it really is the most secure way to do this sort of thing.
The basic order of operations is:
- Client authenticates with business logic tier using the user's personal username/password. The username and password are known to the user and are not related to the database login credentials in any way.
- If authentication succeeds, the client makes a request to the business logic tier asking for some information from the database. For example, an inventory of products. Note that the client's request is not a SQL query; it is a remote procedure call such as
getInventoryList
. - The business logic tier connects to the database and retrieves the requested information. The business logic tier is in charge of forming a secure SQL query based on the user's request. Any parameters to the SQL query should be sanitized to prevent SQL injection attacks.
- The business logic tier sends the inventory list back to the client application.
- The client displays the inventory list to the user.
Note that in the entire process, the client application never connects directly to the database. The business logic tier receives a request from an authenticated user, processes the client's request for an inventory list, and only then executes a SQL query.
Put the password into a file that the application will read. NEVER embed passwords in a source file. Period.
Ruby has a little-known module called DBI::DBRC for such usage. I have no doubt that Java has an equivalent. Anyway, it is not difficult to write one.
Are you writing a web application? If so, use JNDI to configure it externally to the application. An overview is available here:
JNDI provides a uniform way for an application to find and access remote services over the network. The remote service may be any enterprise service, including a messaging service or an application-specific service, but, of course, a JDBC application is interested mainly in a database service. Once a DataSource object is created and registered with a JNDI naming service, an application can use the JNDI API to access that DataSource object, which can then be used to connect to the data source it represents.
No matter what you do, the sensitive information will be stored in some file somewhere. Your goal is to make it as difficult to get as possible. How much of this you can achieve depends on your project, needs and thickness of your company's wallet.
The best way is not to store any passwords anywhere. This is achieved by using hash functions to generate and store password hashes:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
Hash algorithms are one way functions. They turn any amount of data into a fixed-length "fingerprint" that cannot be reversed. They also have the property that if the input changes by even a tiny bit, the resulting hash is completely different (see the example above). This is great for protecting passwords, because we want to store passwords in a form that protects them even if the password file itself is compromised, but at the same time, we need to be able to verify that a user's password is correct.
Unrelated note: In the old days of the internet, when you click 'forgot my password' link, websites would email you your plain text password. They were probably storing those in a database somewhere. When hackers gained access to their database, they would gain access to all the passwords. Since many users would use the same password in multiple websites, this was a huge security problem. Luckily, nowadays this is not the common practice.
Now comes the question: what's the best way to store passwords? I would consider this (authentication and user management service stormpath's) solution a pretty damn ideal one:
- Your user enters the credentials, and this is validated against the password hash
- Password hashes are generated and stored, not passwords
- Hashes are performed multiple times
- Hashes are generated using a randomly generated salt
- Hashes are encrypted with a private key
- Private key is stored at a physically different place than hashes
- Private keys are on a time-based fashion updated
- Encrypted hashes are divided into chunks
- These chunks are stored in physically separate locations
Obviously you're not the google or a bank, so this is an overkill solution for you. But then comes the question: How much security your project requires, how much time and money you have?
For many applications, although not recommended, storing hard-coded password in the code might be a good enough solution. However, by easily adding couple of extra steps of security from the above list, you can make your application much more secure.
For example, let's assume step 1 is not be an acceptable solution for your project. You don't want users to enter password every time, or you don't even want/need users to know the password. Still you have sensitive information somewhere and you want to protect this. You have a simple application, there is no server to store your files or this is too much hassle for your project. Your application runs on environments where it is not possible to have files securely stored. This is one of the worst case, but still with some additional security measure you can have much safer solution. For example, you can store the sensitive information in a file, and you can encrypt the file. You can have the encryption private key hard coded in the code. You can obfuscate the code, so you make it a bit more difficult for someone to crack it. There are many libraries exists for this purpose, see this link. (I want to warn you one more time that this is not 100% secure. A smart hacker with right knowledge and tools can hack this. But based on your requirements and needs, this might be a good enough solution for you).
This question shows how to store passwords and other data in an encrypted file: Java 256-bit AES Password-Based Encryption
MD5 is a hash algorithm, not an encryption algorithm, in short u cant get back wat u hashed, u can only compare. It should ideally be used when storing the user authentication information and not db username and password. db username and pwd should be encrypted and kept in a config file, to do the least.
'developer tip' 카테고리의 다른 글
DataFrame의 문자열이지만 dtype은 객체입니다. (0) | 2020.09.25 |
---|---|
R에서 %> % 함수는 무엇을 의미합니까? (0) | 2020.09.25 |
모듈러스 연산자 대신 비트 단위 (0) | 2020.09.25 |
CMake에서 문자열을 여러 줄로 분할하는 방법은 무엇입니까? (0) | 2020.09.25 |
Google Play에서 언어를 변경하려면 어떻게하나요? (0) | 2020.09.25 |