Monday, August 15, 2016

iOS Jailbreak Unchecked File Operation Result Code

In general, We use temporary files to save data for temporary purpose in our application. 
We save in plists, txt files etc..

But we developers least bother about the error codes of these file operations. We simply write,

      NSError *error = nil;
      [data writeToFile:pathToFile options:NSDataWritingAtomic error:&error];

and not even check the result code whether the write operation is successful or not. This may cause a security breach.

These insecure file operations are a major source of security vulnerabilities. They could be any of below.

Insecure file operations give an attacker the ability to read confidential information.

Attackers can take control of an application or even control of entire system.

Data written  to temporary file may become corrupted. A buffer overflow or or other unintended behaviour may happen when the corrupted file is read back by the application. The application writes data to a temporary file. The write operation fails in the middle. Part of the data is written to the file, and another part is lost. The application does not check the result code of the file operation, and takes no corrective actions. The application reads back the corrupted file, and a buffer overflow or other unintended behavior happens. An attacker exploits the buffer overflow to gain control of the application. 

So it's developer's responsibility to check the result codes of these file operations and take the necessary actions if they fail in the middle.

Fortunately, All the file operations in cocoa gives us the result code whether the operation is successful or not.

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)writeOptionsMask error:(NSError **)errorPtr;
- (BOOL)writeToURL:(NSURL *)url options:(NSDataWritingOptions)writeOptionsMask error:(NSError **)errorPtr;

- (BOOL)fileExistsAtPath:(NSString *)path;
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(nullable BOOL *)isDirectory;
- (BOOL)isReadableFileAtPath:(NSString *)path;
- (BOOL)isWritableFileAtPath:(NSString *)path;
- (BOOL)isExecutableFileAtPath:(NSString *)path;
- (BOOL)isDeletableFileAtPath:(NSString *)path;

- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
- (BOOL)linkItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error NS_AVAILABLE(10_5, 2_0);

- (BOOL)copyItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL error:(NSError **)error NS_AVAILABLE(10_6, 4_0);
- (BOOL)moveItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL error:(NSError **)error NS_AVAILABLE(10_6, 4_0);
- (BOOL)linkItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL error:(NSError **)error NS_AVAILABLE(10_6, 4_0);
- (BOOL)removeItemAtURL:(NSURL *)URL error:(NSError **)error NS_AVAILABLE(10_6, 4_0);

As they are returning a BOOL value, We can simple check it and raise exceptions as shown below to avoid these security vulnerabilities.

    NSError *writeError;

    if (![encryptedData writeToURL:[NSURL fileURLWithPath:
           [NSString stringWithFormat:@"%@",myPath]] options:
                    NSDataWritingAtomic error:&writeError])
        [[NSException exceptionWithName:@"FileWriteError" reason:
                              [error localizedFailureReasonuserInfo:nilraise];

Always check the results codes as they are free of cost :)

Hope this post is useful. Feel free to comment in case of any queries.