code

2017年12月23日 星期六

iOS Universal Links and Android App Links

Android App Links

我們可以把app中的content透過連結,讓使用者直接開啟app到那個特定的content,有以下兩種連結方方法可以做到:

Deep Links: 這是使用URL的方法,我們必須在app中加入intent filters,然後解析intent帶來的data來開啟相對應的activity。潛在問題是其他的app如果也listen相同的intent,則可以獲取此連結開啟權力

Android App Links (Android 6.0+ / api 23+): 設定一個app為某種link的default handler,使用者可以在Android系統設定中更改此設定。好處包括:
  • 需驗證HTTP URL domain ownership,不會被其他app冒用
  • 如果使用者沒安裝app的話,會直接導向web
  • support Instant Apps (不用安裝app就可以使用app)
  • 可以從以下地方導到app content:
    • mobile browser中點擊Google search結果
    • Google Search app
    • Android screen search
    • Google Assistant
可以說App Links是強化版本的URL scheme deep links。怎麼實現App Links呢?

簡單來說:
1. 放一個json file到一個https的網站,讓Android用來驗證網站所有權以及app關聯性。
2. 在app manifest宣告某個activity相關的intent filter,以及要設定autoVerify為true,這樣Android才會在launch activity的第一次就驗證關聯性。

很簡單,困難點反而是在怎麼建立一個https網站,如果對我這種backend白癡來說的話。

iOS Universal Links

iOS Universal Links跟Android App Links就是一樣的東西,行為:
  • 如果有安裝app,則點擊網頁中的link會開啟app中的某個特定畫面
  • 如果沒安裝app則開啟Safari導到這個link連結的網頁
  • 不會被開啟其他宣稱能handle此url的app (同樣經過網站所有權驗證)
  • 不過如果原本已經開啟此domain web page,就不會開啟app
所有權認證的方式跟App Links一樣,放一個json file在某個static path下面,大概長這樣:



上面9JA89QQLNQ是team id,可以在developer portal找到,後面接的就是app id,整個構起一個identify這個app的key, value是一個array (paths),標明哪些path可以由app來handle,如果整個網站都在app有對應的handler,那就像上面黃色字樣寫的"*"。

或是部分被app handle的話:




結論

這兩個平台提供的Dee[ Link方法對server端幾乎沒有影響,設計很好!


2017年12月11日 星期一

Software Security 2 - Buffer Overflow attack

Low-level Security: Buffer Overflow (stack smashing)

這主要發生在C/C++,目前常使用的系統包括: OS kernels, servers (各種http server, memory cache等), embedded systems。

定義: access 一個buffer非合法的index範圍,就是一個buffer overflow attack。


Process 記憶體配置複習

首先一個program要執行時,會有一個process執行它,這個process被分配了某個大小的記憶體,例如在32bit系統上,記憶體位址為 0 ~ 2^32 - 1:


這記憶體位址當然是虛擬(logical address)的,不是真實的physical address (那什麼叫做physical address?),只對此process來說有意義,這個記憶體區塊又分為以下的堆疊:


Text就是code (e.g. function implementation),Heap被malloc管理,而Stack存放local variables和function calls,把Stack和Heap放置呈水平來看:



每當Stack push一個local variable,它會往memory address較低的方向push,而heap剛好相反,每當allocate一個新的memory,heap會往address較高的方向增加。

Compiler在runtime會透過指令去調整stack所占記憶體的大小(push / pop / return),malloc implementation則負責管理跟OS要(allocate)的記憶體,但是要到的記憶體則充分由malloc管理。


Stack and Function calls

假設有一個function有三個傳進來的參數,以及兩個local variables,定義如下:


當一個function的caller呼叫此function時,compiler會先把帶進的參數以相反順序push到stack上,而local variables "通常" 會以宣告的順序push到stack上:



那program要怎麼知道loc2在記憶體中的位置呢? 絕對位置無法得知,因為這個function可能被call很多次,每次呼叫都會push一個loc2到stack上,但是compiler可以知道相對於caller的位置。

先定義stack frame為每次此function被呼叫時使用到的stack範圍:


compiler使用一個稱為 frame pointer (i.e. ebp register),這指向了一個funciton的local variable的起始記憶體位置:

所以在32bit word機器上,loc2 address = %ebp - 2words = %ebp - 8 bytes


假設main()呼叫了func(),首先對compiler來說,main()跟func()沒什麼兩樣,所以先把main的parameters/local variables push到stack上面,就是上圖中的caller's data部分,當然對main()來說,它有儲存自己的frame pointer到ebp register (下圖綠色字眼):


compiler把func()的arg3, arg2, arg1 push到stack上,然後得要在ebp register中記錄func()的frame pointer (i.e. func()的local variable起始位置),可是這樣在func() return之後, 我們ebp register仍然保有的是func()的frame pointer,而不是main()的,這樣main()的接下來未執行的程式就無法找到main()的local variable相對位置,所以我們必須要把這個main()的 frame pointer也push到stack 上:



所以第一個問號就是caller (main())的frame pointer,這樣我們等一下可以直接用這個pointer指向的位置來restore ebp register成caller的frame pointer。

我們還需要push第二個問號: 目前的instruction pointer。
由於func()在text (code)的位置當然不同於main()的位置,所以呼叫func()代表instruction pointer要jump到不同的位置:



所以從func() return 回來的時候,我們不但restore了main()的frame pointer到ebp register,也restore了jump 之前的 instruction pointer到 eip register,這樣就完成了一個function call。



Buffer Overflow

以下這段程式碼,被strcpy造成了buffer overflow (i.e. access 不該access的address):


首先main()呼叫了func(),所以compiler執行過後的stack會長這樣:

strcpy會造成overflow,所以原本記錄著main()的frame pointer變成了:



所以當func() returns,這個錯誤的frame pointer會被複寫到ebp register,造成segmentation fault:



可是如果overflow複寫的不是ebp register,而是另一個local variable?


如果上面的authenticated是一個安全檢查的local variable,則這個buffer overflow造成了檢查漏洞:



Code Injection

buffer overflow既然有可能改寫contiguous memory上面的數值,且可以直接複寫不論多少bytes都可以,所以hacker面臨兩個主要挑戰:

1. 怎麼把自己的惡意的assembly code塞到memory?
2. 怎麼移動instruction pointer指到自已惡意的code來執行?

關於第一點,由於strcpy / sprintf 等有可能造成buffer overflow的function都會在遇到 '\0' byte的時候就停止operation,所以hacker要先避免自己的assembly code有NULL byte。另外當然自己的assembly code必須是完整的,不依賴loader去load其他位置的code。

這個injected code最好是能執行shell command,稱為shellcode,例如以下:

最後一行就是執行了shell command,也就是執行了 "bin/sh"。


再來關於第二點,怎麼移動instruction pointer到自己的code?
還記得呼叫一個funciton的時候,stack frame會長這樣:

所以我們只要把儲存caller instruction pointer的memory (上圖中的 藍色%eip位置),改寫成惡意code的起始位置0xbff即可。問題是我們怎麼知道我們惡意的code是在memory中的哪個位置?

推理,precondition:
(a) hacker不知道原本的source code,所以hacker不知道buffer的記憶體位置以及大小,所以無法知道自己透過overflow inject的code在記憶體的位置

(b) hacker可以access目前eip和ebp register,所以她知道目前這個callee的frame pointer是指向哪裡,所以可以知道存放caller的instruction pointer存放在哪個記憶體位置。

(b) 如果caller的instruction pointer填錯位置(亂猜)的話,則CPU jump後會看到invalid instruction,就panic當機。所以在惡意的code之前塞入一堆noop instruction,這是1-byte instruction,CPU看到這個只會停止一個cycle不做事,不會panic,所以可以提高亂猜卻抵達injected code機率:




所以要使得惡意inject code能被執行就是靠 "猜"一個可能的位置,存放在caller instruction pointer存放的位置,這在function return的時候會jump過去,然而由於是猜測的位置,所以要靠多放一些noops在惡意的code之前來提高jump過後不會panic的機率。

大致上是這樣:






Software Security 1 - Introduction

Computer Security

定義軟體 "不該發生什麼行為"

  • 不該違反保密協定 (confidentiality)
  • 不該違反功能完整性 (integrity)
  • 不該違反存取性 (accessibility)


Hacker exploits "Defects"

flaw是系統設計面的瑕疵,意思是software有超出requirement定義的行為。

bug是系統實作面的錯誤。

defects: hackers利用flaws / bugs 來攻擊的漏洞,defects會被hackers利用來侵入系統,這叫做脆弱性 (vulnerability),所以即便bug可能看起來無關緊要,但很有可能給予hackers攻擊的漏洞或是靈感


Software Security

是focus在code層次 安全性的學問。


OS Security

使用到OS system calls都能受到OS層級的安全性保護,例如Alice不能access Bob的folder,或是如果沒開放port 80,則不可能有人能從port 80連出或連進來。

但是OS security涵蓋不瞭Application 內部的安全細節,例如只有database software能分辨與執行機敏性資料的存取政策,OS是幫不上忙的(也不該)。

此外,OS不能貫徹information flow policies,稍後會說明。


Firewalls and Intrusion Detection System (IDSs)

防火牆主要是用來過濾可以存取資料的連線,主要利用hosts / ip / ports 等protocol定義內容來過濾。

侵入偵測系統IDS則是會分析封包內容,找出符合可能風險模式的封包,予以阻擋。

防火牆允許的port不一定是它預設要保護的service,例如port 80不一定是執行http server,例如SOAP是利用http protocol來交換message的一種協定,但這邊就做了很多http server做不到的事,所以防火牆如果假設port 80只會是http server (通常都是)那就可能形成一個可以exploit的入口。

IDS也是能有被降低分析能力的攻擊方法。


Anti-virus Scanners

這是local端的IDS,但也有可能因為performance考量而犧牲了偵測能力。


2017年12月6日 星期三

Keychain & TouchID 整合

Keychain

keychain是一個database,每個key-value pairs稱為一個keychain item,所有的values都加密過,特別適合用來儲藏小size的user secrets。

Keychain需要link ios Security.framework,我們的application透過SecItem API來存取keychain items:



app process透過SecItem API把我們的request丟給另一個process "securityd",這算是一個中間人,因為他雖然可以query Keychain database,但是並沒有decrypt keychain value的能力,所以"securityd"會再把這個encrypted value丟到Apple A7+ chip上面的硬體security code processor稱為 Secure enclave,由此module決定是否要decrypt。

Keychain安全性

1. 被使用者iphone密碼保護
2. 被使用者iphone 出廠設定的unique device secret保護
3. keychain只有當使用者解鎖之後才能access
4. access control (只有儲存data的app能access自己的data)

總之Keychain是Apple保護某個on disk的secrets的功能,我們可以確信此protection是安全的,但是我們application的責任就是:不能把解密過後的secrets長期放到memory中(e.g. global/static variables),或是透過網路傳送


SecItem APIs

SecItem是C API:






Data protection classes

Keychain裡面的item能否被access,藉由設定以下幾種可能的protection profiles給kSecAttrAccessible attribute:



包括以下幾種(詳見api document說明):



但是以上幾種不能確定使用者到底有沒有設定device passcode,除非使用以下:


上面這個protection class 是說keychain只有當user authenticate之後才能access,而且當user lock device之後就不能access。當passcode被移除的話,在Secure enclave上的passcode secret就會被移除,所以再也無法解密被保護的items。


Keychain Access Control List (ACL)

每當app要access被ACL和touch id保護的keychain item的時候,以下這個畫面就會跳出來:



輸入device passcode標準介面:



ACL定義:
1. authentication,藉由policy control:



2. item accessibility



Touch ID Authentication

touch ID可以用來當作authenticate,用來驗證可否存取keychain裡面的item,安全性來自Secure enclave,所有的touch id data都存放在secure enclave中,而且所有的touch id operations都在secure enclave中完成,即便OS kernel被compromised也不影響其安全性,因為是一個sandbox。

Secure enclave如果發現touch id數次驗證未過的話,就會強制只能透過device passcode authenticate,重新輸入device passcode之後就能恢復使用touch id authentication。

注意keychain key operations也是在secure enclave中完成,所以跟touch id搭配是非常適合的。

使用ACL來進行touch id authentication是由LocalAuthentication framework提供API來讓application使用:




Code Example

儲存secrets: 原本沒有ACL control的keychain storage如下


如果我們加上ACL control:



讀取secrets



SecItemCopyMatching會啟動LocalAuthentication 功能,所以系統的指紋辨試或是passcode輸入畫面就會出現。不過為了不要block main thread,這個SecItemCopyMatching最好是放到global queue中。



2017年12月5日 星期二

孫正義社內簡報技巧

把簡報技巧列入心理學範疇,我覺得是合理的,怎麼讓台下關鍵決策者聽進去,是一個心理學挑戰

社內簡報其實只有一個假設和兩個原則。
假設聽者非常忙碌,所以簡報必須:

1. 形式簡單快速
2. 符合商業邏輯


簡單快速原則

(1) 正文頁最多 5 ~ 9 頁
這個就是只講重點!要懂取捨,每個簡報只討論一個主題。

(2) 3 ~ 5分鐘簡報完畢
如果滿足第一點,第二點會自動滿足


商業邏輯原則

提案通常是要改善一些現況,所以商業簡報邏輯如下:


  • 闡述現況及其成因
  • 提出改善方法 (兩個以上的話,需有優缺點比較)
  • 闡述(或推論)改善成效


以上三者最好有數字佐證



技巧篇

以上是簡報製作的兩個大原則,這邊筆記實作的技巧。
日本書很有趣,實作都講得非常詳細(連簡報字體都會建議 @@),這邊建議還是直接參考原著,並且製作一份template,以後照用最快。



蠻推薦這本書的,但是還是要做出一點個人風格,要不然看過這本書的主管一看就知道:你是這本書的信徒啊(好像也沒什麼不好)



2017年11月27日 星期一

Software Testing 5 - Code Review and Defects

Code review

code review / inspection對找出defects很有幫助,不過實務上似乎很少進行。通常能透過code review找到的defects如下:

1. 缺少或是錯誤的comments
2. 重複性的code
3. 過於複雜的設計
4. 無法測試的路徑
5. 錯誤使用技術
6. coding errors (這啥?!)

 細分的話,其實code review還可以分成以下三類:
1. walkthru:
找個senior的幫你看一些部分,稱為peer review。

2. code review:
這是最常進行的,可能牽涉多個reviewers,主要檢查implementation。


3. inspection
這是最正式的code review流程,可以有以下腳色:

Moderator – works with author to schedule inspection, send out materials, runs meeting, follows up with author on follow-ups from inspection (often team lead or project manager)
·         Author – provides moderator with inspection material, explains material as needed, responds to questions, responsible for rework based on inspection comments
·         Reader – walks though the code, saying what it does in English and stops for comments on that piece
·         Reviewer – technical experts for the document being inspected; provides comments and questions

·         Recorder – one of the reviewers who agrees to document issues raised at the meeting; usually compiles a list with categories (defect, suggestion, comment, etc.) and distributes to all after meeting; opens internal defect reports to help track fixes


Defect Management

俗稱bug XD,就是不按照design發生的行為。

defect不一定能找出來,找出來也不一定要或能修改,修改後也不一定正確。
所以必須要有系統性的方法來面對defects,需要一個defect tracking system。

defect 可以有類似以下的tracking status:



Defect Report


defect reports不只是展現QA人員的專業,也是developers的重要資產。
defect report需要包含以下:
1. isolation: 切割出可以復現的操作方法
2. generalization: 即便切割出來,但仍需要考量此defect對整體性的影響
3. severity: bug分級定義,根據發生機率以及衝擊性

綜合以上,一個可能的defect report template長這樣:

Item
Description
Title
A unique, concise and descriptive title for a defect is vital. It will allow the defect to be easily identified and discussed.
Good : “Closed” field in “Account Closure” screen accepts invalid date
Bad : “Closed field busted”
Severity
An assessment of the impact of the defect on the end user
Status
The current status of the defect
Initial configuration
The state of the program before the actions in the “steps to reproduce” is to be followed. All too often this is omitted and the reader must guess or intuit the correct pre-requisites for reproducing the defect.
Software
Configuration
The version and release of software-under-test as well as any relevant
hardware or software platform details (e.g. Win 7 vs Win Vista)
Steps to Reproduce
An ordered series of steps to reproduce the defect
Good :
1. Enter “Account Closure” screen
2. Enter an invalid date such as “54/01/07” in the “Closed” field
3. Click “Okay”
Bad: If you enter an invalid date in the closed field it accepts it!
Expected behavior
What was expected of the software, upon completion of the steps to reproduce.
Good: The functional specification states that the “Closed” field should only
accept valid dates in the format “dd/mm/yy”
Bad: The field should accept proper dates.
Actual behavior
What the software actually does when the steps to reproduce are followed.
Good: Invalid dates (e.g. “54/01/07”) and dates in alternate formats (e.g.
“07/01/54”) are accepted and no error message is generated.
Bad: Instead it accepts any kind of date.
Impact
An assessment of the impact of the defect on the software-under-test. It is
important to include something beyond the simple “severity” to allow readers to understand the context of the defect report.
Good: An invalid date will cause the month-end “Account Closure” report to crash the system and corrupt all affected customer records.
Bad: This is serious dude!
(Proposed solution)
An optional item of information testers can supply is a proposed solution.
Testers often have unique and detailed information of the products they test and suggesting a solution can save designers and developers a lot of time.
Priority
An optional field to allow development managers to assign relative priorities to defects of the same severity
Root Cause
An optional field allowing developers to assign a root cause to the defect such as “inadequate requirements” or “coding error”



Root Cause Analysis

root cause analysis通常有助於降低未來defect發生的可能性,可能的種類如下:

Classification
Description
Requirements
The defect was caused by an incomplete or ambiguous requirement with the result assumption differing from the intended outcome.
Design Error
The design differs from the stated requirements or is ambiguous or incomplete resulting in assumptions.
Code Error
The code differs from the documented design or requirements or there was a syntactic or structural error introduced during coding.
Test Error
The test as designed was incorrect (deviating from stated requirements or design) or was executed incorrectly or the resultant output was incorrectly interpreted by the tester, resulting in a defect “logged in error”.
Configuration
The defect was caused by incorrectly configured environment or data.
Existing bug
The defect is existing behavior in the current software (this does not determine whether or not it is fixed).



2017年11月25日 星期六

Software Testing 4 - Test case, suite, report

Testing the design

requirement / documentation / spec 其實也可以test,主要針對以下五個方向去檢驗:
1. specific: 越明確越好
2. measurable: 能夠量化
3. testable: 其實就是1. 2. 的結果
4. consistent: 要跟先前的spec一致
5. exclusive: 把"不該做的"也明列出來。


non-functional (non-feature) test cases

非功能性的tests,包括:
1. usability
2. scalability
3. performance
4. security
5. logging
6. reliability
.
.
.
通常是functional test通過之後,才會進行non-functional tests。


Performance testing

舉performance testing來說,一個明顯困難點在於通常不能用production environment來測試,因為會影響營運,所以必須有一個test environment來模擬production environment。

此外performance testing重點在測試系統弱點,這屬於白箱測試,只有系統開發者知道哪些是可能的弱點,不要因為"政治因素"害怕去測試這些點的極限。

此外要有baseline當比較對象,因為有些時候performance improvement沒什麼太大意義,如果baseline profile已經達到,可能不需要投入資源去提升performance。

performance testing包括以下種類:
1. load testing: 測試在不同的load狀態下,系統有什麼behavior
2. stress testing: 找出系統能承受的最大capacity
3. soak(endurance) testing: 主要瞄準長時間狀態下,系統的在某個load的承受能力
4. spike testing: 這是測試突然增加極大load會讓系統產生什麼行為


Test plan的重要性

test是要規劃的! 不是自己隨興加減測試,事實上這是一個挑戰!
先要有個認知是: 100% coverage是不可能的。

事實上要把test plan當成一個project,所以也會有project management中需要考量的三元素: resource / budget / schedule

所以選擇測試標的,也是一個學問,可能的方向:
1. 趕時間做出來的item
2. remote data / api 接介
.
.

test coverage廣度: 盡可能發現系統中潛在bug
test coverage深度: 在某些容易發生bug的系統,大量重複深入測試


Test Suite

就是一堆test cases的集合,歸類成某一類。


Test report

可能包含以下項目:

1. scope: 測試涵蓋了那些範圍,也該列出未涵蓋的範圍
2. 測試通過標準: 那些問題一定要fix,test cases通過率
3. 測試方法
4. 最後結果
5. defects/status: 列出目前測試出來,尚未解決的defects

上面講的有點籠統,主要是還是要看相關人員想要看到資訊才能做後續決策。




2017年11月22日 星期三

ios XCode9 Continuous Integration

名詞解釋

scheme: 就是build script
bot: 執行schemes,也可以排程的process
Integration: 每次bot執行一次稱為一次integration

Continuous Integration Chart


好處
1. 早期整合,早期發現問題
2. 在server build/test,不用浪費開發者時間
3. 可以排程,測試各版本simulators/devices
4. 產生報表


pre-XCode9: 安裝XCode Server

要先安裝macOS server app:


這邊先略過了,畢竟xcode9已經發表了。


post-XCode9

藏在xcode 裡面:

WWDC 2017有影片說明整合進去xcode。

1. automatic code signing
2. 整合進入xcode 9
3. 自動在simulators / devices 上測試


Code Signing

app需要簽名認證,辨別是真實發行者,ios在app runtime會檢查此數位簽名,才能才能確保以下三件事情:


製作一個signature需要以下三個文件:


1. certificate:
2. provisioning file:
3. entitlement:

以上的細節可以在2016 WWDC XCode Automatic Code Signing影片中詳細解釋。

簡單來說,Xcode 9最大的改進就是把automatic code signing放入 Xcode Server

也唯有automatic code signing才能讓xcode server去在手機上自動化測試app,因為需要code signing (只要target有設定automatic signing):



這背後依賴另一個command line executable : Xcodebuild,所以第三方CI server(e.g. jenkins) 也可以利用此Xcodebuild command去做automatic code signing。



Setup XCode Server in XCode 9

1. 先到xcode preferences打開xcode server:



把右上角switch打開會自動設定,結果如下:



2.  在accounts pane加入xcode server當成“開發者一員”,因為這樣才會有bot (軟體機器人)讓我們來排成做事:



至於Manual Signing影片中有講到,可以先略過。


Setup a bot

在product menu最後有一個"create bot",點下去之後xcode會自動去看目前project是否是來自某個git repository (猜測應該是去scan專案目錄)以及下載的branch,然後會要求設定登入帳號密碼。

之後會有一連串的設定,都可以先採取預設值就好,反正都可以在更改。
接下來會來到要不要授權此 "server team member"來管理 automatic signing issues:



建立bot之後,似乎會馬上進行一次integration,所謂的integration包含以下步驟:
(a) 從repository下載branch
(b) build app
(c) provisioning / signing
(d) test


Distribution Signing 

開發過程中打包的app 稱為archive,這是需要development signing,流程相對簡單。
如果要發布到app store,需要做distribution signing,把archive再打包成.ipa檔案:



事實上有三種distribution signing,adhoc / enterprise / app store:


XCode server可以distribute signing似乎是個很大個改進?不確定,總之台下有歡呼就是了,之後有需要用到再說吧。



優點

1. 整合性超高
2. 可以parallel test,比較神奇的是,某些simulator連launch都沒有,不知道怎麼測試出來的?



3. automatic signing