developer tip

특성 파일에서 비밀번호 보안

copycodes 2020. 11. 25. 08:05
반응형

특성 파일에서 비밀번호 보안


이 질문에 이미 답변이 있습니다.

데이터베이스에 연결하는 Java 애플리케이션이 있습니다.
데이터베이스의 사용자 이름과 암호는 속성 파일에 저장됩니다.
사용자가 암호를 변경할 수있는 옵션을 유지하면서 속성 파일의 일반 텍스트로 암호를 저장하지 않는 일반적인 방법은 무엇입니까?
여기서 주된 동기는 관리자가 속성 파일을 편집하는 동안 누군가가 관리자의 어깨 너머로 비밀번호를 보지 못하도록하는 것입니다. 여기 에서 C #으로 수행하는 방법이 내장되어 있음을
읽었습니다 . 자바를 알기 때문에 기본 제공 솔루션을 찾을 수는 없지만 다른 사람들이 무엇을하는지 듣고 싶습니다.

좋은 선택을 찾지 못한다면 아마도 코드에 보관 될 일정한 암호로 암호화 할 것입니다. 하지만 기분이 나쁘기 때문에 이런 식으로하는 것이 싫습니다.

2012 년 12 월 12 일 편집 마법이없는 것 같습니다. 암호를 코드 또는 이와 유사한 것에 저장해야합니다. 결국 우리는 답변 중 하나에서 언급 한 Jasypt와 매우 유사한 것을 구현했습니다. 그래서 나는 명확한 대답에 가장 가까운 것이기 때문에 Jasypt 대답을 받아들이고 있습니다.


여기에 이미지 설명 입력

Jasypt는 .properties 파일에서 암호화 된 값을로드, 관리 및 투명하게 해독하기위한 org.jasypt.properties.EncryptableProperties 클래스를 제공하여 동일한 파일에서 암호화 된 값과 암호화되지 않은 값을 혼합 할 수 있습니다.

http://www.jasypt.org/encrypting-configuration.html

org.jasypt.properties.EncryptableProperties 개체를 사용하면 애플리케이션이 다음과 같이 .properties 파일을 올바르게 읽고 사용할 수 있습니다.

datasource.driver=com.mysql.jdbc.Driver 
datasource.url=jdbc:mysql://localhost/reportsdb 
datasource.username=reportsUser 
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm) 

데이터베이스 암호는 암호화됩니다 (사실 데이터베이스 구성과 관련이 있든 아니든 다른 속성도 암호화 될 수 있음).

이 값을 어떻게 읽습니까? 이렇게 :

/*
* First, create (or ask some other component for) the adequate encryptor for   
* decrypting the values in our .properties file.   
*/  
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();     
encryptor.setPassword("jasypt"); // could be got from web, env variable...    
/*   
* Create our EncryptableProperties object and load it the usual way.   
*/  
Properties props = new EncryptableProperties(encryptor);  
props.load(new FileInputStream("/path/to/my/configuration.properties"));

/*   
* To get a non-encrypted value, we just get it with getProperty...   
*/  
String datasourceUsername = props.getProperty("datasource.username");

/*   
* ...and to get an encrypted value, we do exactly the same. Decryption will   
* be transparently performed behind the scenes.   
*/ 
String datasourcePassword = props.getProperty("datasource.password");

 // From now on, datasourcePassword equals "reports_passwd"...

가난한 사람의 타협 솔루션은 단순한 다중 서명 접근 방식을 사용하는 것입니다.

예를 들어 DBA는 응용 프로그램 데이터베이스 암호를 50 자의 임의 문자열로 설정합니다. TAKqWskc4ncvKaJTyDcgAHq82X7tX6GfK2fc386bmNw3muknjU

그 또는 그녀는 암호의 절반을 애플리케이션 개발자에게 제공 한 다음 Java 바이너리로 하드 코딩합니다.

private String pass1 = "TAKqWskc4ncvKaJTyDcgAHq82"

The other half of the password is passed as a command line argument. the DBA gives pass2 to the system support or admin person who either enters it a application start time or puts it into the automated application start up script.

java -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU

When the application starts it uses pass1 + pass2 and connects to the database.

This solution has many advantages with out the downfalls mentioned.

You can safely put half the password in a command line arguments as reading it wont help you much unless you are the developer who has the other half of the password.

The DBA can also still change the second half of the password and the developer need not have to re-deploy the application.

The source code can also be semi public as reading it and the password will not give you application access.

You can further improve the situation by adding restrictions on the IP address ranges the database will accept connections from.


What about providing a custom N-Factor authentication mechanism?

Before combining available methods, let's assume we can perform the following:

1) Hard-code inside the Java program

2) Store in a .properties file

3) Ask user to type password from command line

4) Ask user to type password from a form

5) Ask user to load a password-file from command line or a form

6) Provide the password through network

7) many alternatives (eg Draw A Secret, Fingerprint, IP-specific, bla bla bla)

1st option: We could make things more complicated for an attacker by using obfuscation, but this is not considered a good countermeasure. A good coder can easily understand how it works if he/she can access the file. We could even export a per-user binary (or just the obfuscation part or key-part), so an attacker must have access to this user-specific file, not another distro. Again, we should find a way to change passwords, eg by recompiling or using reflection to on-the-fly change class behavior.

2nd option: We can store the password in the .properties file in an encrypted format, so it's not directly visible from an attacker (just like jasypt does). If we need a password manager we'll need a master password too which again should be stored somewhere - inside a .class file, the keystore, kernel, another file or even in memory - all have their pros and cons.
But, now users will just edit the .properties file for password change.

3rd option: type the password when running from command line e.g. java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd.

This doesn't require the password to be stored and will stay in memory. However, history commands and OS logs, may be your worst enemy here. To change passwords on-the-fly, you will need to implement some methods (eg listen for console inputs, RMI, sockets, REST bla bla bla), but the password will always stay in memory.

One can even temporarily decrypt it only when required -> then delete the decrypted, but always keep the encrypted password in memory. Unfortunately, the aforementioned method does not increase security against unauthorized in-memory access, because the person who achieves that, will probably have access to the algorithm, salt and any other secrets being used.

4th option: provide the password from a custom form, rather than the command line. This will circumvent the problem of logging exposure.

5th option: provide a file as a password stored previously on a another medium -> then hard delete file. This will again circumvent the problem of logging exposure, plus no typing is required that could be shoulder-surfing stolen. When a change is required, provide another file, then delete again.

6th option: again to avoid shoulder-surfing, one can implement an RMI method call, to provide the password (through an encrypted channel) from another device, eg via a mobile phone. However, you now need to protect your network channel and access to the other device.

I would choose a combination of the above methods to achieve maximum security so one would have to access the .class files, the property file, logs, network channel, shoulder surfing, man in the middle, other files bla bla bla. This can be easily implemented using a XOR operation between all sub_passwords to produce the actual password.

We can't be protected from unauthorized in-memory access though, this can only be achieved by using some access-restricted hardware (eg smartcards, HSMs, SGX), where everything is computed into them, without anyone, even the legitimate owner being able to access decryption keys or algorithms. Again, one can steal this hardware too, there are reported side-channel attacks that may help attackers in key extraction and in some cases you need to trust another party (eg with SGX you trust Intel). Of course, situation may worsen when secure-enclave cloning (de-assembling) will be possible, but I guess this will take some years to be practical.

Also, one may consider a key sharing solution where the full key is split between different servers. However, upon reconstruction, the full key can be stolen. The only way to mitigate the aforementioned issue is by secure multiparty computation.

We should always keep in mind that whatever the input method, we need to ensure we are not vulnerable from network sniffing (MITM attacks) and/or key-loggers.


Actually, this is a duplicate of Encrypt Password in Configuration Files?.

The best solution I found so far is in this answert: https://stackoverflow.com/a/1133815/1549977

Pros: Password is saved a a char array, not as a string. It's still not good, but better than anything else.

참고 URL : https://stackoverflow.com/questions/10306673/securing-a-password-in-a-properties-file

반응형