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,以後照用最快。



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