ios系统的攻防宝典

了解ios的系统防御机制

iOS 安全模型平心而论, App Store 确实成功地将许多恶意软件拒之门外。但对开发者来说,应用程序的审查流程是令人沮丧的黑箱操作。苹果的审查流程和方法并不对外公开,有时候你搞不清楚什么功能允许使用,什么功能禁止使用。苹果提供了正式的指导手册,但是遵守了指导的应用同样会被拒绝。当然,什么是恶意程序是由苹果来定义,而不是用户来定义。苹果使用 App Store 来控制或限制 iOS 平台上应用程序的功能,这就意味着如果想要实现某些特定的功能,唯一的手段就是将设备越狱或骗过应用商店的审查。这里有一个名为HandyLight 的应用,它会伪装成一个手电筒应用,但其内部包含一个隐藏模式,能够开启设备共享上网的功能。官方的应用审查永远无法抓到那些钻空子(或者没啥作用)的恶意程序,所以需要另外一套高效的机制,来阻止恶意程序破坏整个操作系统的安全。在本章中你会了解到 iOS 的安全机制架构。在稍后的章节中,将深入挖掘如何在程序中利用这些机制。

 ps :// developer . apple . com / appstore / resources / approval / guidelines . html p :// www . macworld . com / article /1152835/iphone_ flashlight _ tethering . html 

先来看一下 iOS 基本的安全组件是如何阻止恶意攻击和保护数据的。在稍后的章节中将深入探讨大部分机制,这里先简述一下它们的设计思想和实际效果。

苹果手机系统安全启动

当启动一台 iOS 设备时,系统首先会从只读的引导 ROM 中读取初始化指令,即系统引导程序。这个引导 ROM 包含苹果官方权威认证的公钥,它会验证底层启动加载器( LLB )的签名,一旦通过验证就启动它。 LLB 会做一些基础工作,然后验证第二级引导程序 iBoot 。 iBoot 启动后,设备就可以进入恢复模式或启动内核。在 iBoot 验证完内核签名的合法性之后,整个启动程序开始步入正轨:加载驱动程序、检测设备、启动系统守护进程。

这个信任链确保所有的系统组件都由苹果写入、签名、分发,不能来自第三方机构,特别是那些恶意的攻击者以及企图越狱设备的黑客。应用程序启动时也会用信任链去审查签名。所有的应用都必须直接或间接由苹果签名。

越狱的工作原理正是攻击这一信任链。越狱工具的作者需要找到这一信任链条上的漏洞,从而禁掉链条中负责验证的组件。破解引导 ROM 通常是最可取的方法,因为该组件不会因苹果今后的软件更新而改变。

沙盒机制

苹果的沙盒机制,历史上被称作安全带,是一种基于 FreeBSD 系统 TrustedBSD 框架的强制访问控制( MAC )机制,它的主要推动者是罗伯特沃森。它采用一种类似于 Lisp 的配置语言来描述哪些资源系统可以访问,哪些禁止访问。这些资源主要包括文件、系统服务、网络连接、内存资源等。

 MAC 机制不同于传统的访问控制机制(比如自主访问控制( DAC )),它不允许主体(比如用户进程)操作对象(文件、套接字等)。 DAC 最常见的形式就是 UNIX 系统上的用户、组和其他权限,所有这些都可以被授予读、写或执行的权限。3在 DAC 系统中,用户如果拥有一个对象的所有权,也就拥有该对象的修改权限。举个例子,如果你拥有一个文件,你可以将其设置为全局可读或全局可写,这显然破坏了访问控制。

 MAC 是一个广义的术语,在沙盒中它意味着应用程序被关进了一个虚拟的容器。该容器遵循一系列的特定规则,即哪些系统资源可以被访问,比如网络资源、文件读写、进程克隆等。4在 OS X 中你可以部分控制应用程序的沙盒功能,但是在 iOS 平台中,所有的第三方应用程序都要遵循唯一的限制策略。

在文件访问方面,一般只能访问应用程序的包目录;应用可以读写存储在该位置的文件。不过这一基本规则存在少许例外。举例来说,在某些 iOS 版本中,图片一般存储在目录/ private / var / mobile / Media / Photos /中。尽管它在应用程序包目录之外,但第三方应用程序还是可以直接访问,这样应用程序无须获得用户许可就能访问相册。想要阻止应用程序滥用权力,那就只能拜托苹果的上架审查了。

安卓的访问控制机制与 MAC 不同。安卓实现了一个更加传统的 DAC 模型,应用程序都有自己的用户 ID 和属于该 ID 的文件夹,其权限管理严格按照传统的 UNIX 文件权限管理运作。虽然这两种机制工作起来都没有问题,但 MAC 的扩展性总体来说还是更强一些。比如,除了应用目录隔离, MAC 机制还可以限制网络访问或系统守护进程的操作。越狱检测

 

越狱的本质就是通过一系列步骤来禁掉签名机制,从而允许设备运行未经苹果官方审核的应用。越狱还允许你使用一些便利的开发和测试工具,当然这些工具永远不会通过苹果商店的审核。'越狱还有一个至关重要的能力,就是黑箱测试应用程序,在第6章将会深入探讨关于黑箱测试的话题。

和大多数人想的不一样,越狱不一定要禁用掉 iOS 的沙盒机制,它只是允许你在沙盒外安装应用程序。安装在移动用户主目录下的应用程序(即通过苹果官方商店安装)仍然受到沙盒限制。第三方的 iOS 应用程序需要安装在越狱设备中权限更高的/ Applications 目录下,与苹果股票应用安装在一起。

越狱检测很早就有,不过没什么用。它的目的是检测设备是否存在不受信任、未经签名的第三方程序,从而判断设备是否处在高风险环境中。公平地说,第三方程序库中不乏恶意软件和行为不端的应用程序,但总体来说,越狱检测不值得你浪费时间去做,因为它无法阻止一个坚定的攻击者。

有一段时间,苹果官方推出过越狱检测 API ,但很快就在后续的 iOS 版本中删掉了。没有此 API 时,开发者也实现了一些越狱检测方法。目前最流行的越狱检测方法主要有下面几种:

●创建一个新进程,例如调用 fork ()、 vfork ()、 popen ()等方法。

这是明显会被沙盒所禁止的事情。当然,越狱系统上的沙盒依然是有效的,所以该策略毫无意义。无论你的设备越狱与否,这种方法对于来自苹果官方商店的程序来说始终是无效的。

●读取沙盒外部的文件,开发者通常想要尝试访问一些二进制代码,这些二进制代码通常对应于 ssh 、 bash ,还有一些位于 Cydia . app 目录和 Cydia 经常使用的 apt 仓库等位置。但这些检测很容易被绕过,并且Xcon6之类的工具也能帮助用户绕过这些自动检查。

●不要使用太直白的方法名,比如 isJailbroken ,否则攻击者可以轻易定位并禁掉越狱检测。

带你了解ios的攻击类型都有哪些?

苹果手机的攻击类型都有哪些,普通人应该如何有效防御!

取证攻击

1:取证攻击者一旦有权限访问设备或者它的备份,就会尝试获取设备的机密。最常见的做法就是访问设备的物理区域。相比计算机,手机或平板电脑更容易被盗,因此大部分攻击都是取证攻击。

取证攻击可以由一个抱有碰运气心态的攻击者或熟练掌握定向攻击的攻击者发起。对于碰运气的攻击者来说,窃取信息就是偷一部没有任何 PIN 保护的手机,然后他们就能从手机上窃取图片、文字以及所有可以通过正常途径访问到的数据。如果用户开启了两步验证,攻击者也能很轻易地得到这些验证码信息或短信。

一个熟练的取证攻击者可能是一个流氓雇员、公司、政府、执法官员或者专门的敲诈勒索人员。这种攻击者知道某种技术可以用来实现临时越狱,破解简单的 PIN ,然后访问设备文件系统中的数据。这些数据部分来自系统层,部分来自应用层。因此攻击者不但可以获取 UI 所展示的数据,也能得到系统底层的缓存数据。这些缓存数据包括截图、按键记录、 Web 请求中缓存的敏感数据等。

2:代码执行攻击

远程代码执行攻击会在设备上执行一段代码来破坏整个设备和数据,这个过程并不需要实际拿到该设备。这种攻击有多种渠道:网络、二维码、 NFC 、恶意文件解析,以及连接感染病毒的硬件外设。一旦设备执行了远程攻击代码,就可以执行取证攻击,从而获取用户的机密信息。有几种经常出现的代码执行攻击,它们都利用了底层编程语言的漏洞,我们将在第11章探讨。

3:基于 Web 的攻击

基于 Web 的远程代码执行攻击主要使用恶意的 HTML 和 JavaScript 来误导用户或窃取数据。远程攻击者可以操控一个恶意网站或者合法网站,也可以简单地将恶意代码发布到公共论坛。

这些攻击可以从HTML5的数据库或本地存储中窃取数据,还能修改或窃

4:C语言攻击。。。等

ios系统如何预防 Object

ios系统如何预防 Objective - C 格式化字符串攻击

 

和 C 语言类似,你可以给某些 Objective - C API 传入和 printf 一样的格式化操作符。你可以在 Xcode 中直接测试,给 NSLog 传入一个假的格式化字符串即可:

 NSString * userText -@"* x * xtxtxtxtxtxtxtx * x * x * x *xtxtx8x8x8x8x8x"; NSLog ( userText );

和之前的% x 示例类似,这段代码会把内存中的内容以十六进制数的形式输出到控制台。我在真实的 iOS 应用中遇到过一个类似的格式化字符串漏洞,有一段代码将用户输入传递给"格式化"函数,进行一些处理并返回一个 NSString 对象,如代码所示。

 NSString * myStuff =@" Here is my stuff .";

 NSString * unformattedStuff -@" Evil things * x *xtx8xtx";

 myStuff -[ myStuff stringByAppendingFormat :[ UtilityClass formatStuff :

 unformattedStuff . text ]);

代码11-1:格式化字符串的错误用法

这个例子假设①处生成的并存储在 myStuff 中的 NSString 是安全的。毕竟 unformattedStuff . text 中的内容被"格式化"了。但是除非 formatStuff 方法会过滤输入内容,否则生成的字符串仍可能包含格式化字符串分类符。如果出现这种情况,那还是会出现格式化字符串漏洞,生成的字符串会包含从栈中读取的数据。

 NSString 对象自身无法避免格式化字符串攻击。 NSString 的正确传参方法是使用%@分类符,如代码所示。

 NSString myStuff -@" Here is my stuff .";

 myStuff -[ myStuff stringByAppendingFormat :@"&!",[ UtilityClass formatStuff : unformattedStuff . text ]];

代码:正确的传参方法

有了%@分类符,无论 unformattedStuff . text 中包含多少% x 和% n 操作符, myStuff 都会直接输出它们。

% x 和% n 分类符对攻击者来说非常有用,但是即使不使用这两种分类符,攻击者仍然有可能实现意料之外的行为。举个例子,如果尝试读取无法访问的内存,哪怕使用% s 分类符也会导致应用崩溃。上面介绍了格式化字符串的攻击原理和预防方法。

ios系统的C语言攻防

ios系统的C语言攻防

C 语言的遗留问题

 Objective - C 和 Cocoa 可以帮你解决 C 或者 C ++的许多安全问题。然而, Objective - C 其实就是 C ,因此它从根本上说不是一门"安全"的语言,此外某些 Cocoa API 仍然可能丢失数据或者遭受代码执行攻击( code execution attack ),和 C 语言的问题一样。 C 和 C ++很容易和 Objective - C 混编,因此很多 iOS 应用都包含大量 C 和 C ++代码。其原因要么是开发者想使用某个熟悉的第三方库,要么是开发者试图让代码能跨平台使用。此外,就像第1章说过的,有些混编操作是为了防止代码执行攻击,但是这种做法并不能阻挡经验丰富的攻击者。因此,我建议你充分了解这些 Bug 和各种攻击方式。

了解 Objective - C 中遗留的 C 语言问题,并学习如何解决它们。 C 语言存在很多问题,本章只是"精选"出一些比较有代表性的问题,让你初步了解它们的原理和攻击方式。

格式化字符串

格式化字符串攻击,'指的是误用那些能够接收格式化字符串( format string )的 API ,格式化字符串中会包含数据类型信息。在 C 中,最常见的使用格式化字符串的函数就是 printf 系列;还有函数也能使用格式化字符串,例如 syslog 。在 Objective - C 中,这些方法通常带有 WithFormat 或者 AppendingFormat 这样的后缀,不过也有一些例外。下面是几个例子:

·[ Nsstring * WithFormat ]

·[ NSString stringByAppendingFormat ]

·[ NSMutableString appendFormat ]

·[ NSAlert alertWithMessageText ]

·[ NSExceptionraise : format :]

· NSLog ()

攻击者通常会利用格式化字符串漏洞做两件事:执行恶意代码和读取进程内存。漏洞主要来自两个古老的 C 格式化字符串操作符:% n 和% x 。% n 操作符比较少见,它会把前面输出的字符串值当作整数存储在栈上。然而,它会被攻击者用来重写内存。% x 操作符会以十六进制的形式输出字符串,如果没有传入需要输出的值,那它会从栈上读取。

不幸的是,对于我们这些 Bug 猎人来说,苹果公司在使用格式化字符串的 Cocoa 类中禁用了% n 操作符。不过这个% n 格式化字符串仍然能在常规的 C 代码中使用,因此仍然可以利用格式化字符串进行代码执行攻击。2%n之所以能进行代码执行攻击,主要原因是它可以向栈中写入数据,而格式化字符串同样也存储在栈上。具体的攻击方式取决于具体的 Bug ,不过通常来说需要构建一个包含% n 和目标内存地址的格式化字符串,然后就可以向目标内存写入整数数据。结合某些 shell 代码,就可以实现缓冲区溢出攻击( buffer overflow attack )。

和% n 不同,% x 运算符可以同时在 Objective - C 方法和 C 函数中使用。如果攻击者可以向某个缺少格式化字符串分类符( specifier )的输入流插入% x ,那输入会被解析成一个格式化字符串,堆栈中的内容会以十六进制数的形式写入字符串应该出现的位置。如果攻击者可以查看输出,那他们就可以收集进程内存中潜在的敏感信息,例如用户名、密码或者其他个人数据。

当然,这两种攻击方式都有一个前提,那就是应用没有正确处理用户输入。我们来看看攻击者如何在这种情况下使用格式化字符串进行攻击,以及如何预防这种攻击方式。

预防传统的 C 格式化字符串攻击

格式化字符串漏洞的典型场景:程序没有传入格式化字符串,而是给 printf 传了一个变量。如果变量的内容由外部输入并且攻击者可以控制输入,那么他们就可以在这个设备上运行代码或者从内存中提取数据。如果你要测试,可以在 Xcode 中人为制造漏洞,如下:

 char * t ;

 t -"8x8x8x8x8xbx8xbx"/

 printf ( t );

这段代码只是将一串包含% x 分类符的字符串传递给 printf 函数。在实际项目中,这些值可能来自任何地方,比如用户输入框或者 DNS 查询结果。这段代码运行之后,你会看到一段以十六进制数形式输出的字符串被写入控制台。这个输出是存储在栈上的变量值,以十六进制数显示。如果某个应用在栈上存储密码或者密钥,并且会解析攻击者提供的数据,那攻击者就可以使用这种方式把信息输出到某个地方,然后读取数据。如果让上面的例子使用% n 分类符,那代码的行为就会截然不同。下面是修改后的代码:

 char * t ;

 t =" intnintnin ";

 printf ( t );

在 Xcode 中运行这段代码会导致 Xcode 中断于11db并报 EXC _ BAD _ ACCESS 错误。这个错误表示你的程序正在试图对不可访问的内存进行读取或者写入操

200

 iOS 应用安全权威指南

作。当然,在某些精心构造的攻击当中,你可能不会看到报错,代码会被直接执行。

幸运的是,你只要控制用户输入就可以阻止攻击者劫持字符串。在本例中,只要给 printf 指定格式化字符串即可。

ios系统中的数据溢出攻击

ios系统中的数据溢出攻击

进行计算时,如果运算结果超出平台支持的最大整数,就会发生整数溢出( integer overflow )。 C 语言有两种整数类型( Objective - C 也是如此):有符号数和无符号数。有符号整数有正负,无符号整数永远为正。如果你的计算导致这两种整数类型溢出,就会导致不好的结果。无符号整数如果溢出,就会从无符号整数的最大值变成0。如果整数有符号,那么就会跳到一个负值,也就是有符号整数的最小值。如下例所示:

 NSInteger foo -9223372036854775807;

 NSLog (@"$ li ",( long ) foo );

 foo ++;

 NSLog (@"$ li ",( long ) foo );

我们首先定义了一个有符号整数 foo ,它的值是 iOS 平台上有符号整数的最大值。给它加1之后,控制台上的输出会变成负数:-9223372036854775808.

如果你使用无符号整数,同样也能实现整数溢出,控制台输出的应该是0: NSUInteger foo -18446744073709551615;

 NSLog (@"8lu",( unsigned long ) foo );

 foo ++:

 NSLog (@"$ lu ",( unsigned long ) foo );

缓冲区溢出会覆盖栈上的内容,而整数溢出可以让攻击者访问堆空间,下面会介绍具体的攻击方式。

 malloc 引发的整数溢出

计算 malloc ()需要分配的空间时通常会发生整数溢出,导致分配空间太小无法存储目标值。之后在数据被加载到新分配的空间时,溢出的数据会写入分配空间之后的堆空间中,从而造成堆空间溢出。如果攻击者向 malloc ()

206

传入恶意构造的数据,然后覆盖堆空间中的正常指针,就可以实现代码执行攻击

整数溢出漏洞通常是这种形式:

# define GOAT NAME _ LEN 32

 typedef struct Goat [

 int leg _ count ;//山羊通常有4条腿

bool has goatee ;

 char name [ GOAT NAME LEN ];

 struct Goat * parentl ;

 struct Goat *parent2;

 size t kid count ;

 struct Goat ** kids ;

) Goat ;

 int ReadInt ( int socket )(

 int result ;

 read ( socket ,& result , sizeof ( result )); return result ;

 void ReadGoat ( Goat * goat , int socket )(

 read ( socket , goat , sizeof ( Goat ));

 Goat * ReadGoats ( int * count , int socket )(

* count - ReadInt ( socket );

 Goat * goats - malloc (* count * sizeof ( Goat ));

 for ( inti -0; i <* count ;++ i ){

 ReadGoat (& goats [ il , socket );

 return goats ;

这段代码创建了一个 Goat 结构体并声明 ReadGoats 函数,后者接收两个参数,一个是套接字( socket ),另一个是需要从套接字中读取的山羊( goat )数量。在①处, ReadInt 函数会从套接字中读取山羊的数量。

如果要读取的数量非常大,那②处的 malloc ()操作就会导致整数溢出,整数会变成负值。合理操作 count 值,攻击者就可以让 malloc ()分配0字节或者非常小的空间。由于 count 值很大,③处的循环执行时会从套接字中读取很多山羊。由于 goats 空间很小,就会导致内存溢出,从而把数据写入到堆空间中。

预防整数溢出

有几种方法可以预防整数溢出,基本的思路都是在操作整数值之前进行检查。我建议你使用苹果编程范例中提到的方式,如下:

 if ( n >0&& m >0&& INT _ MAX / n >- m )(

 size _ t bytes - n * m ;

 foo - malloc ( bytes );

在计算 bytes 值之前,这个 if 语句会检查 n 和 m 是否大于0,还会使用最大整数除以其中一个值,确保结果比另一个值大。如果这两个条件都满足,那么可以确定 bytes 不会溢出,可以安全地分配内存。

 

 

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱与诚804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值