소프트웨어 보안은 보안 소프트웨어가 아닙니다. 여기서는 인증, 액세스 제어, 기밀성, 암호화, 권한 관리 등의 항목에 대해 설명합니다.
pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
...
webview.setWebViewClient(new WebViewClient() {
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
String username = credentials[0];
String password = credentials[1];
Intent i = new Intent();
i.setAction("SEND_CREDENTIALS");
i.putExtra("username", username);
i.putExtra("password", password);
view.getContext().sendBroadcast(i);
}
});
...
SEND_CREDENTIALS
작업을 통해 인텐트를 수신 대기하도록 등록된 모든 수신자가 메시지를 수신합니다. 이 경우 수정 방법으로 권한을 사용하지 않는 것이 좋지만, 브로드캐스트는 수신자 수를 제한하는 권한으로도 보호되지 않습니다.FileIOPermissions
를 결정합니다.
...
String permissionsXml = GetPermissionsFromXmlFile();
FileIOPermission perm = new FileIOPermission(PermissionState.None);
perm.FromXml(permissionsXml);
perm.Demand();
...
...
CrytoKeyAuditRule auditRule = new CryptoKeyAuditRule(IdRef, (CryptoKeyRights) input, AuditFlags.Success);
...
input
을 제어할 수 있는 경우 어떤 유형의 작업을 로그할 수 있는지 지정할 수 있습니다. 사용자가 이를 CryptoKeyRights.Delete
로 조작할 수 있는 경우 로그되지 않은 상태에서 암호화 키를 읽을 수 있으므로 공격자가 암호화 키를 도용한 사실을 알 수 없습니다.
...
uid = 'scott'.
password = 'tiger'.
WRITE: / 'Default username for FTP connection is: ', uid.
WRITE: / 'Default password for FTP connection is: ', password.
...
pass = getPassword();
...
trace(id+":"+pass+":"+type+":"+tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
...
ResetPasswordResult passRes = System.resetPassword(id1, true);
System.Debug('New password: '+passRes.getPassword());
...
pass = GetPassword();
...
dbmsLog.WriteLine(id+":"+pass+":"+type+":"+tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.get_password()
함수는 저장되는 값 중 사용자가 제공하는 계정 관련 일반 텍스트 암호를 반환합니다.
pass = get_password();
...
fprintf(dbms_log, "%d:%s:%s:%s", id, pass, type, tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 모든 데이터의 안전한 저장소로 보고 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
...
MOVE "scott" TO UID.
MOVE "tiger" TO PASSWORD.
DISPLAY "Default username for database connection is: ", UID.
DISPLAY "Default password for database connection is: ", PASSWORD.
...
Session.pword
변수는 계정 관련 일반 텍스트 암호를 포함합니다.
<cflog file="app_log" application="No" Thread="No"
text="#Session.uname#:#Session.pword#:#type#:#Now()#">
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
var pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.GetPassword()
함수의 반환 값입니다.
pass = GetPassword();
...
if err != nil {
log.Printf('%s: %s %s %s', id, pass, type, tsstamp)
}
Example 1
의 코드는 일반 텍스트 암호를 응용 프로그램 이벤트 로그에 기록합니다. 많은 개발자가 이벤트 로그를 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
pass = getPassword();
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp);
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
...
webview.setWebViewClient(new WebViewClient() {
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm) {
String[] credentials = view.getHttpAuthUsernamePassword(host, realm);
String username = credentials[0];
String password = credentials[1];
Intent i = new Intent();
i.setAction("SEND_CREDENTIALS");
i.putExtra("username", username);
i.putExtra("password", password);
view.getContext().sendBroadcast(i);
}
});
...
SEND_CREDENTIALS
작업을 통해 인텐트를 수신 대기하도록 등록된 모든 수신자가 메시지를 수신합니다. 이 경우 수정 방법으로 권한을 사용하지 않는 것이 좋지만, 브로드캐스트는 수신자 수를 제한하는 권한으로도 보호되지 않습니다.
localStorage.setItem('password', password);
pass = getPassword()
...
dbmsLog.println("$id:$pass:$type:$tstamp")
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
...
webview.webViewClient = object : WebViewClient() {
override fun onReceivedHttpAuthRequest(view: WebView,
handler: HttpAuthHandler, host: String, realm: String
) {
val credentials = view.getHttpAuthUsernamePassword(host, realm)
val username = credentials!![0]
val password = credentials[1]
val i = Intent()
i.action = "SEND_CREDENTIALS"
i.putExtra("username", username)
i.putExtra("password", password)
view.context.sendBroadcast(i)
}
}
...
SEND_CREDENTIALS
작업을 통해 인텐트를 수신 대기하도록 등록된 모든 수신자가 메시지를 수신합니다. 이 경우 수정 방법으로 권한을 사용하지 않는 것이 좋지만, 브로드캐스트는 수신자 수를 제한하는 권한으로도 보호되지 않습니다.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
// Configure the new event with information from the location
CLLocationCoordinate2D coordinate = [location coordinate];
NSString *latitude = [NSString stringWithFormat:@"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:@"%f", coordinate.longitude];
NSLog(@"dLatitude : %@", latitude);
NSLog(@"dLongitude : %@",longitude);
NSString *urlWithParams = [NSString stringWithFormat:TOKEN_URL, latitude, longitude];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlWithParams]];
[request setHTTPMethod:@"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Add password to user defaults
[defaults setObject:@"Super Secret" forKey:@"passwd"];
[defaults synchronize];
getPassword()
함수의 반환 값도 있습니다.
<?php
$pass = getPassword();
trigger_error($id . ":" . $pass . ":" . $type . ":" . $tstamp);
?>
Example 1
의 코드는 일반 텍스트 암호를 응용 프로그램 이벤트 로그에 기록합니다. 많은 개발자가 이벤트 로그를 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.OWA_SEC.get_password()
함수는 사용자가 제공하는 계정 관련 일반 텍스트 비밀번호를 반환하며 이는 HTTP 응답에 인쇄됩니다.
...
HTP.htmlOpen;
HTP.headOpen;
HTP.title (.Account Information.);
HTP.headClose;
HTP.bodyOpen;
HTP.br;
HTP.print('User ID: ' ||
OWA_SEC.get_user_id || '');
HTP.print('User Password: ' ||
OWA_SEC.get_password || '');
HTP.br;
HTP.bodyClose;
HTP.htmlClose;
...
getPassword()
함수의 반환 값도 있습니다.
pass = getPassword();
logger.warning('%s: %s %s %s', id, pass, type, tsstamp)
Example 1
의 코드는 일반 텍스트 암호를 응용 프로그램 이벤트 로그에 기록합니다. 많은 개발자가 이벤트 로그를 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.get_password()
함수는 저장되는 값 중 사용자가 제공하는 계정 관련 일반 텍스트 암호를 반환합니다.
pass = get_password()
...
dbms_logger.warn("#{id}:#{pass}:#{type}:#{tstamp}")
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
val pass = getPassword()
...
dbmsLog.println(id+":"+pass+":"+type+":"+tstamp)
Example 1
의 코드는 일반 텍스트 암호를 파일 시스템에 기록합니다. 많은 개발자가 파일 시스템을 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.
import CoreLocation
...
var locationManager : CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.locationServicesEnabled
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
...
if let location: CLLocation! = locationManager.location {
var coordinate : CLLocationCoordinate2D = location.coordinate
let latitude = NSString(format:@"%f", coordinate.latitude)
let longitude = NSString(format:@"%f", coordinate.longitude)
NSLog("dLatitude : %@", latitude)
NSLog("dLongitude : %@",longitude)
let urlString : String = "http://myserver.com/?lat=\(latitude)&lon=\(longitude)"
let url : NSURL = NSURL(string:urlString)
let request : NSURLRequest = NSURLRequest(URL:url)
var err : NSError?
var response : NSURLResponse?
var data : NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error:&err)
} else {
println("no location...")
}
let defaults : NSUserDefaults = NSUserDefaults.standardUserDefaults()
// Add password to user defaults
defaults.setObject("Super Secret" forKey:"passwd")
defaults.synchronize()
getPassword
함수는 저장되는 값 중 사용자가 제공하는 계정 관련 일반 텍스트 암호를 반환합니다.
pass = getPassword
...
App.EventLog id & ":" & pass & ":" & type & ":" &tstamp, 4
...
Example 1
의 코드는 일반 텍스트 암호를 응용 프로그램 이벤트 로그에 기록합니다. 많은 개발자가 이벤트 로그를 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.AppSearch
코드가 액세스할 수 없도록 해야 합니다.
...
// Document object to index
val doc = Doc(
namespace="user1",
id="noteId",
score=10,
text="This document contains private data"
)
// Adding document object to AppSearch index
val putRequest = PutDocumentsRequest.Builder().addDocuments(doc).build()
SharedPreferences
클래스를 사용하여 물리적 Android 장치에 저장됩니다.password
는 장치에 일반 텍스트 형식으로 저장됩니다.
SharedPreferences userPreferences = this.getSharedPreferences("userPreferences", MODE_WORLD_READABLE);
SharedPreferences.Editor editor = userPreferences.editor();
editor.putString("username", userName);
editor.putString("password", password);
...
editor.language("language", language);
...
SharedPreferences
인스턴스는 응용 프로그램에 대해 비공개적이고 다른 응용 프로그램에서 액세스할 수 없지만 장치에 물리적으로 액세스하면 이러한 파일을 액세스할 수 있습니다. 또한 Example 1
에서 모드를 MODE_WORLD_READABLE
로 설정하면 다른 응용 프로그램에서 기본 설정 파일에 접근할 수 있고, 나아가 사용자 개인 정보를 침해할 수 있습니다.
MIDDLEWARE = (
...
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.gzip.GZipMiddleware',
...
)
...
HKHealthStore healthStore = new HKHealthStore();
HKBloodTypeObject blood = healthStore.GetBloodType(null);
NSLog("%@", blood.BloodType);
var urlWithParams = String.format(TOKEN_URL, block.BloodType);
var responseString = await client.GetStringAsync(urlWithParams);
...
NSLog
함수보다 저수준인 Apple Logging API를 사용하면 개발자는 장치에서 모든 로그를 읽을 수 있는 응용 프로그램을 생성할 수 있습니다(다른 응용 프로그램을 소유하지 않은 경우에도).
...
HKHealthStore healthStore = new HKHealthStore();
HKBloodTypeObject blood = healthStore.GetBloodType(null);
// Add blood type to user defaults
NSUserDefaults.StandardUserDefaults.SetString(blood.BloodType, "bloodType");
...
...
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
HKBloodTypeObject *blood = [healthStore bloodTypeWithError:nil];
NSLog(@"%@", [blood bloodType]);
NSString *urlWithParams = [NSString stringWithFormat:TOKEN_URL, [blood bloodType]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlWithParams]];
[request setHTTPMethod:@"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
...
NSLog
함수보다 저수준인 Apple Logging API를 사용하면 개발자는 장치에서 모든 로그를 읽을 수 있는 응용 프로그램을 만들 수 있습니다(다른 응용 프로그램을 소유하지 않은 경우에도).
...
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
HKBloodTypeObject *blood = [healthStore bloodTypeWithError:nil];
// Add blood type to user defaults
[defaults setObject:[blood bloodType] forKey:@"bloodType"];
[defaults synchronize];
...
...
let healthStore = HKHealthStore()
let blood = try healthStore.bloodType()
print(blood.bloodType)
let urlString : String = "http://myserver.com/?data=\(blood.bloodType)"
let url : NSURL = NSURL(string:urlString)
let request : NSURLRequest = NSURLRequest(URL:url)
var err : NSError?
var response : NSURLResponse?
var data : NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error:&err)
...
NSLog
함수보다 저수준인 Apple Logging API를 사용하면 개발자는 장치에서 모든 로그를 읽을 수 있는 응용 프로그램을 만들 수 있습니다(다른 응용 프로그램을 소유하지 않은 경우에도).
...
let healthStore = HKHealthStore()
let blood = try healthStore.bloodType()
print(blood.bloodType)
// Add blood type to user defaults
defaults.setObject("BloodType" forKey:blood.bloodType)
defaults.synchronize()
...
String
개체에 저장합니다.
public static String getPassword() {
String inputPassword = "";
ConsoleKeyInfo nextKey = Console.ReadKey(true);
while (nextKey.Key != Console.ReadKey(true)) {
inputPassword.AppendChar(nextKey.KeyChar);
Console.Write("*");
nextKey = Console.ReadKey(true);
}
return inputPassword;
}
String
은 변경이 불가능한 개체이므로 콘텐츠를 null로 만들 수 없습니다. 즉, 가비지 수집 전에 힙을 검사할 수 있는 모든 사용자에게 중요한 데이터가 공개됩니다.String
개체에 민감한 데이터를 저장하면 메모리에서 데이터를 완전히 없앨 수 없습니다.String
개체는 변경이 불가능하므로 중요한 데이터를 저장하는 데 중요한 데이터를 저장할 때 String
을 사용하는 경우가 많습니다. 메모리에서 String
의 값을 제거하는 작업은 JVM 가비지 수집기만 수행할 수 있습니다. 그런데 JVM의 메모리가 부족하지 않으면 가비지 수집기를 실행할 필요가 없으므로 가비지 수집이 수행되는 시기가 보장되지 않습니다. 응용 프로그램 충돌 시에는 응용 프로그램의 메모리 덤프로 인해 중요한 데이터가 노출될 수 있습니다.String
으로 변환합니다.
private JPasswordField pf;
...
final char[] password = pf.getPassword();
...
String passwordAsString = new String(password);
String
개체에 민감한 데이터를 저장하면 메모리에서 데이터를 완전히 없앨 수 없습니다.String
은 민감한 데이터를 저장하는 데 사용되지만 String
개체는 불변이므로 이 개체에 새 값을 할당하면 새 String
이 생성되고 해당 참조가 할당하려는 개체에 할당됩니다. 원래 값은 ARC
(Automatic Reference Counting)가 개체를 할당 해제하고 메모리를 해제할 때까지 메모리에 유지됩니다. Swift는 개체를 포함하는 가장 인접한 범위가 끝날 때까지 개체의 수명을 보장하지 않습니다. 개체가 할당 해제되기 전에 공격자가 메모리의 콘텐트를 덤프하게 되면 콘텐트를 읽을 수 있습니다.String
을 사용하여 메모리에 암호를 저장합니다.
let password = passwordTextField.text!
// use the password
POST
메서드 대신 HTTP GET
메서드를 사용하여 데이터를 서버로 보냅니다.GET
메서드를 이용하는 HTTP 요청은 URL 및 요청 매개변수가 브라우저의 URL 캐시, 중개 프록시 및 서버 로그에 캐시되도록 허용할 수 있습니다. 이로 인해 데이터에 대한 적절한 권리가 없는 개인에게 민감한 정보가 노출될 수 있습니다.예제 2: 응용 프로그램이 NSURLRequest를 사용할 경우, 기본 HTTP 메서드는 GET 입니다.
...
NSString * const USER_URL = @"https://www.somesvr.com/someapp/user";
...
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:USER_URL]];
[request setHTTPMethod:@"GET"];
...
...
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [[NSMutableData data] retain];
} else {
...
POST
메서드 대신 HTTP GET
메서드를 사용하여 데이터를 서버로 보냅니다.GET
메서드를 이용하는 HTTP 요청은 URL 및 요청 매개변수가 브라우저의 URL 캐시, 중개 프록시 및 서버 로그에 캐시되도록 허용할 수 있습니다. 이로 인해 데이터에 대한 적절한 권리가 없는 개인에게 민감한 정보가 노출될 수 있습니다.
...
$client = new Zend_Http_Client('https://www.example.com/fetchdata.php');
$client->request(Zend_Http_Client::GET);
...
POST
메서드 대신 HTTP GET
메서드를 사용하여 데이터를 서버로 보냅니다.GET
메서드를 이용하는 HTTP 요청은 URL 및 요청 매개변수가 브라우저의 URL 캐시, 중개 프록시 및 서버 로그에 캐시되도록 허용할 수 있습니다. 이로 인해 데이터에 대한 적절한 권리가 없는 개인에게 민감한 정보가 노출될 수 있습니다.예제 2: 응용 프로그램이 NSURLRequest를 사용할 경우, 기본 HTTP 메서드는 GET 입니다.
...
let url = NSURL(string: "https://www.somesvr.com/someapp/user")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "GET"
let connection = NSURLConnection(request:request, delegate:self)
...
...
let url = NSURL(string: "https://www.somesvr.com/someapp/user")
let request = NSURLRequest(URL: url!)
let connection = NSURLConnection(request:request, delegate:self)
...
NSURLCredential
을 초기화합니다.NSURLCredential
의 인스턴스를 만들 때는 지속성 특성을 정의해야 합니다. 가능한 값은 다음과 같습니다.NSURLCredentialPersistenceNone
: 자격 증명을 저장하지 않아야 합니다.NSURLCredentialPersistenceForSession
: 이 세션에 대해서만 자격 증명을 저장해야 합니다.NSURLCredentialPersistencePermanent
: 자격 증명을 키 집합에 저장해야 합니다.NSURLCredentialPersistenceSynchronizable
: 자격 증명을 키 집합에 영구적으로 저장해야 하며 또한 소유한 Apple ID에 기반하여 다른 장치로 배포해야 합니다.NSURLCredentialPersistenceSynchronizable
특성은 자격 증명의 배포 및 Apple 클라우드 환경에서의 저장을 의미합니다. 응용 프로그램의 개인 정보 요구 사항에 따라 자격 증명을 Apple 클라우드 환경에 저장하는 것이 허용되지 않을 수 있습니다.
...
NSURLCredential *credential = [NSURLCredential credentialWithUser:user password:password persistence:NSURLCredentialPersistenceSynchronizable];
NSURLCredentialStorage *shared = [NSURLCredentialStorage sharedCredentialStorage];
[shared setDefaultCredential:credential forProtectionSpace:protectionSpace];
...
NSURLCredential
을 초기화합니다.NSURLCredential
의 인스턴스를 만들 때는 지속성 특성을 정의해야 합니다. 가능한 값은 다음과 같습니다.NSURLCredentialPersistenceNone
: 자격 증명을 저장하지 않아야 합니다.NSURLCredentialPersistenceForSession
: 이 세션에 대해서만 자격 증명을 저장해야 합니다.NSURLCredentialPersistencePermanent
: 자격 증명을 키 집합에 저장해야 합니다.NSURLCredentialPersistenceSynchronizable
: 자격 증명을 키 집합에 영구적으로 저장해야 하며 또한 소유한 Apple ID에 기반하여 다른 장치로 배포해야 합니다.NSURLCredentialPersistenceSynchronizable
특성은 자격 증명의 배포 및 Apple 클라우드 환경에서의 저장을 의미합니다. 응용 프로그램의 개인 정보 요구 사항에 따라 자격 증명을 Apple 클라우드 환경에 저장하는 것이 허용되지 않을 수 있습니다.
...
let credential = NSURLCredential(user:foo, password:password, persistence:.Synchronizable)
let shared = NSURLCredentialStorage.sharedCredentialStorage()
shared.setCredential(credential, forProtectionSpace:protectionSpace)
...
SensitiveXMLData
XML 데이터 소스의 민감한 재무 정보 그래프를 생성하는 DataVisualization
제어를 인스턴스화할 수 있습니다.
<asp:Chart ID="Chart1" runat="server" ImageLocation="~/Temporary/Graph"
ImageType="Jpeg" DataSourceID="SensitiveXMLData" ImageStorageMode="UseImageLocation">
<series>
.
.
.
</series>
<chartareas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</chartareas>
</asp:Chart>
Example 1
의 코드는 Chart
제어가 막대 그래프의 JPEG 이미지를 생성하고 이를 임시 디렉터리인 ~/Temporary/Graph
에 작성하도록 지시합니다. 제어가 디스크에 이미지를 작성하면 사용자의 브라우저는 이후의 파일 요청을 보내 사용자에게 표시합니다. 이미지가 디스크에 안전하게 작성되지 않습니다. 또한, 코드는 기본 인프라가 다른 사용자에 의한 무단 액세스로부터 파일을 보호할 것이라고 가정합니다.NSURLCredential
인스턴스를 로컬에서 제거하지만 다른 장치 및 iCloud에 저장된 복사본을 제거하지 못합니다.NSURLCredential
의 인스턴스를 만들 때는 지속성 특성을 정의해야 합니다. 가능한 값은 다음과 같습니다.NSURLCredentialPersistenceNone
: 자격 증명을 저장하지 않아야 합니다.NSURLCredentialPersistenceForSession
: 이 세션에 대해서만 자격 증명을 저장해야 합니다.NSURLCredentialPersistencePermanent
: 자격 증명을 키 집합에 저장해야 합니다.NSURLCredentialPersistenceSynchronizable
: 자격 증명을 키 집합에 영구적으로 저장해야 하며 또한 소유한 AppleID에 기반하여 다른 장치에 배포해야 합니다.NSURLCredentialPersistenceSynchronizable
자격 증명이 다른 장치 및 iCloud로 배포되므로 모든 위치에서 자격 증명을 완전히 제거하지 못하면 인스턴스가 남게 되어 누출 위험성이 있습니다.
...
// Create the credential
NSURLCredential *credential = [NSURLCredential credentialWithUser:user password:password persistence:NSURLCredentialPersistenceSynchronizable];
NSURLCredentialStorage *shared = [NSURLCredentialStorage sharedCredentialStorage];
[shared setDefaultCredential:credential forProtectionSpace:protectionSpace];
// Use the credential as needed
...
// Removes the credential
[shared removeCredential:credential forProtectionSpace:protectionSpace];
...
NSURLCredential
인스턴스를 로컬에서 제거하지만 다른 장치 및 iCloud에 저장된 복사본을 제거하지 못합니다.NSURLCredential
의 인스턴스를 만들 때는 지속성 특성을 정의해야 합니다. 가능한 값은 다음과 같습니다.NSURLCredentialPersistenceNone
: 자격 증명을 저장하지 않아야 합니다.NSURLCredentialPersistenceForSession
: 이 세션에 대해서만 자격 증명을 저장해야 합니다.NSURLCredentialPersistencePermanent
: 자격 증명을 키 집합에 저장해야 합니다.NSURLCredentialPersistenceSynchronizable
: 자격 증명을 키 집합에 영구적으로 저장해야 하며 또한 소유한 AppleID에 기반하여 다른 장치에 배포해야 합니다.NSURLCredentialPersistenceSynchronizable
자격 증명이 다른 장치 및 iCloud로 배포되므로 모든 위치에서 자격 증명을 완전히 제거하지 못하면 인스턴스가 남게 되어 누출 위험성이 있습니다.
...
// Create the credential
let credential = NSURLCredential(user:foo, password:password, persistence:.Synchronizable)
let shared = NSURLCredentialStorage.sharedCredentialStorage()
shared.setCredential(credential, forProtectionSpace:protectionSpace)
// Use the credential as needed
...
// Removes the credential
shared.removeCredential(credential, forProtectionSpace:protectionSpace)
...
MyCreditCard
키는 사용자가 제공하는 계정 관련 일반 텍스트 신용 카드 값을 저장합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>password</key>
<string>BASICSECRET</string>
<key>credentials</key>
<dict>
<key>pin</key>
<string>2345</string>
<key>MyCreditCard</key>
<string>1111 11 2321 1112</string>
<key>MysSn</key>
<string>1111-22-3333</string>
<key>ssn</key>
<string>2345-22-3345</string>
<key>userid</key>
<string>12345</string>
</dict>
</dict>
</plist>
Example 1
의 코드는 모바일 장치의 사용자 개인 정보를 장치에 저장된 보호되지 않는 plist 파일에 저장합니다. 상당수의 개발자들은 plist 파일을 안전한 저장 위치로 신뢰하고 있지만 개인 정보 침해에 대한 우려가 있는 상황에서 무조건 믿어서는 안 됩니다. plist 파일은 장치만 확보한다면 누구라도 읽을 수 있기 때문입니다.
ViewController.h
...
@property (nonatomic, retain) IBOutlet UITextField *ssnField;
...
Example 1
의 코드는 응용 프로그램이 민감한 정보를 수집하도록 설계된 입력 컨트롤을 이용한다는 의미입니다. iOS는 자동 고침 기능의 성능 향상을 위해 텍스트 필드의 입력을 캐시하기 때문에 그러한 입력 컨트롤에 최근 입력된 모든 정보는 파일 시스템에 저장된 키보드 캐시 파일 내에 캐시될 수 있습니다. 키보드 캐시 파일은 장치에 저장되므로 장치를 분실할 경우 이 파일이 복구될 수 있으며, 이로 인해 장치에 포함된 모든 민감한 정보가 유출될 수 있습니다.
...
@IBOutlet weak var ssnField: UITextField!
...
Example 1
의 코드는 응용 프로그램이 민감한 정보를 수집하도록 설계된 입력 컨트롤을 이용한다는 의미입니다. iOS는 자동 고침 기능의 성능 향상을 위해 텍스트 필드의 입력을 캐시하기 때문에 그러한 입력 컨트롤에 최근 입력된 모든 정보는 파일 시스템에 저장된 키보드 캐시 파일 내에 캐시될 수 있습니다. 키보드 캐시 파일은 장치에 저장되므로 장치를 분실할 경우 이 파일이 복구될 수 있으며, 이로 인해 장치에 포함된 모든 민감한 정보가 유출될 수 있습니다.
ViewController.h
...
@property (nonatomic, retain) IBOutlet UITextField *ssnField;
...
Example 1
의 코드는 응용 프로그램이 민감한 정보를 수집하도록 설계된 입력 컨트롤을 이용한다는 의미입니다. iOS가 애니메이션 성능을 향상하기 위해 응용 프로그램이 백그라운드 처리될 때 응용 프로그램의 활성 뷰에 대한 스크린샷을 저장하기 때문에, 백그라운드 이벤트가 처리되는 동안 그러한 입력 컨트롤에 표시되는 모든 정보가 파일 시스템에 저장된 이미지 내에 캐시될 수 있습니다. 화면 캐시 스크린샷은 장치에 저장되므로 장치를 분실할 경우 스크린샷이 복구될 수 있으며, 이로 인해 장치에 포함된 모든 민감한 정보가 유출될 수 있습니다.
...
@IBOutlet weak var ssnField: UITextField!
...
Example 1
의 코드는 응용 프로그램이 민감한 정보를 수집하도록 설계된 입력 컨트롤을 이용한다는 의미입니다. iOS가 애니메이션 성능을 향상하기 위해 응용 프로그램이 백그라운드 처리될 때 응용 프로그램의 활성 뷰에 대한 스크린샷을 저장하기 때문에, 백그라운드 이벤트가 처리되는 동안 그러한 입력 컨트롤에 표시되는 모든 정보가 파일 시스템에 저장된 이미지 내에 캐시될 수 있습니다. 화면 캐시 스크린샷은 장치에 저장되므로 장치를 분실할 경우 스크린샷이 복구될 수 있으며, 이로 인해 장치에 포함된 모든 민감한 정보가 유출될 수 있습니다.Documents
디렉터리에 씁니다.Documents
디렉터리의 용도는 응용 프로그램이 오프라인 모드로 실행할 수 있도록 로컬 정보 또는 사용자 생성 콘텐트와 같은 일시적이지 않은 응용 프로그램 데이터를 저장하기 위한 것입니다. 응용 프로그램의 Info.plist
파일에서 UIFileSharingEnabled
가 설정된 경우 iTunes를 통해 이러한 파일에 액세스할 수 있습니다. 민감한 데이터를 Documents
디렉터리에 쓸 경우 암호화되지 않은 백업에서 또는 iTunes 인터페이스를 통해 데이터가 노출될 수 있습니다.Documents
디렉터리 내에 일반 텍스트로 씁니다.
...
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *passwd_path = [docsDirectory stringByAppendingPathComponent:@"passwords.txt"];
NSString *password = [user password];
[password writeToFile:passwd_path atomically:YES encoding:NSUTF8StringEncoding error:nil];
...
Documents
디렉터리에 씁니다.Documents
디렉터리의 용도는 응용 프로그램이 오프라인 모드로 실행할 수 있도록 로컬 정보 또는 사용자 생성 콘텐트와 같은 일시적이지 않은 응용 프로그램 데이터를 저장하기 위한 것입니다. 응용 프로그램의 Info.plist
파일에서 UIFileSharingEnabled
가 설정된 경우 iTunes를 통해 이러한 파일에 액세스할 수 있습니다. 민감한 데이터를 Documents
디렉터리에 쓸 경우 암호화되지 않은 백업에서 또는 iTunes 인터페이스를 통해 데이터가 노출될 수 있습니다.Documents
디렉터리 내에 일반 텍스트로 씁니다.
let documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let passwd_path = NSURL(fileURLWithPath: documents).URLByAppendingPathComponent("secret.txt")
let password = getUserPassword()
try password.writeToURL(passwd_path, atomically:true, encoding: NSUTF8StringEncoding)
DataType
이 password로 지정되어 있지 않으므로 표시할 때 기본적으로 표시됩니다.
public class User
{
[Required]
public int ID { get; set; }
public string Title { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateOfEmployment { get; set; }
[DataType(DataType.Currency)]
public decimal Salary { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
...
}
Example 1
에서 Password
속성은 [DataType(DataType.Password)]
속성을 지정하지 않았으므로 UI에 표시될 때 기본적으로 숨겨지지 않습니다.TextField
위젯이 숨김 처리하지 않음을 보여 줍니다.
class SelectionContainerDisabledExampleApp extends StatelessWidget {
const SelectionContainerDisabledExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "Please enter your password",
),
),
],
),
),
),
);
}
}
Example 1
에서는 obscureText
속성을 true
로 설정하여 TextField
위젯을 인스턴스화하지 않았으므로 사용자가 "비밀번호를 입력하십시오." 프롬프트에 입력하는 비밀번호가 숨김 처리되지 않습니다.PasswordCallback pc = new PasswordCallback("Please enter your password: ", true);
예제 1
의 pc
는 두 번째 매개 변수인 onEcho
가 true
로 설정된 상태로 인스턴스화되었으므로 사용자가 "비밀번호를 입력하십시오." 프롬프트에 입력하는 비밀번호가 숨김 처리되지 않습니다.
ViewController.h:
...
@property (nonatomic, retain) IBOutlet UITextField *passwordField;
...
ViewController.m:
...
NSString *password = _passwordField.text;
...
예제 1
의 passwordField
는 secureTextEntry
속성을 true
로 설정하지 않았기 때문에 사용자가 텍스트 필드에 입력하는 비밀번호가 숨김 처리되지 않습니다.
...
@IBOutlet weak var passwordField: UITextField!
...
let password = passwordField.text
...
예제 1
의 passwordField
는 secureTextEntry
속성을 true
로 설정하지 않았기 때문에 사용자가 텍스트 필드에 입력하는 비밀번호가 숨김 처리되지 않습니다.
from oslo_config import cfg
...
opts = [
cfg.StrOpt('admin_password',secret=False,
help="User's password")]
...
grp = cfg.OptGroup('mygroup')
cfg.CONF.register_opts(opts, group=grp)
...
logger.warning("Adding %s" % cfg.CONF.mygroup.admin_password)
Example 1
의 코드는 secret
값이 False
로 설정된 상태로 admin_password
를 일반 텍스트(난독 처리되지 않음)로 로그 출력에 씁니다. 많은 개발자가 이벤트 로그를 안전한 데이터 저장소로 신뢰하지만 무조건 신뢰해서는 안 됩니다. 특히 개인 정보가 관련된 경우가 대표적입니다.