# PRS 改版精要 - [Introduction](#introduction) - [Problem](#problem) - [Solution](#solution) # introduction ![](https://i.imgur.com/Z5j0xNL.png) 此張圖為現行的 **Phone Reputation Service (PRS)** 的架構, 現在主要有兩種方式 query PRS,第一種就是當信件進入 Tmase engine 後, 會透過 [Parser 1](https://github.trendmicro.com/CoreTech-ERS/Library-TMASE/blob/d3c6a5a7eae17b3f494e063f54e10a5b83e55ed3/TMASE/src/tmase/CScamFilter.cpp#L439-L447) 去從 Email Body 中抓出並經過前處理後,將 extracted phone 丟到 Eureka 的 prs 參數中,去跟 pattern match 出 RID 第二種則是其他 Team(如 Trend Micro Check) 會直接透過 Eureka API post prs 這個參數來問。 而為了讓兩者去 match pattern 時候的格式是一致的,我們在 Eureka 裡面也做了一個 [Parser 2](https://adc.github.trendmicro.com/CoreTech-ERS/App-eureka/blob/master/internal/msgdecode/decoder.go#L277-L310) 去處理吃進來的 prs value Tmase 跟 Eureka Parser 的範例如下 check prs 參數(處裡 prs 跟 senderinfo 兩個參數) ```go // 示例1:原始字符串包含常用分隔符号,包含无效字符 rawString1 := "+1 (555) 123-4567" processed1, err1 := preprocessPhoneNumber(rawString1) // 输出: // processed1 = "15551234567" // err1 = nil // 示例2:原始字符串不包含分隔符号,但以 0 开头 rawString2 := "0123456789" processed2, err2 := preprocessPhoneNumber(rawString2) // 输出: // processed2 = "123456789" // err2 = nil // 示例3:原始字符串包含非数字字符 rawString3 := "1-800-Flowers" processed3, err3 := preprocessPhoneNumber(rawString3) // 输出: // processed3 = "" // err3 = Invalid char for phone number: - // 示例4:原始字符串中的号码长度小于8 rawString4 := "1234567" processed4, err4 := preprocessPhoneNumber(rawString4) // 输出: // processed4 = "1234567" // err4 = Invalid length for phone number, too short: 1234567 // 示例5:原始字符串中的号码长度大于20 rawString5 := "123456789012345678901" processed5, err5 := preprocessPhoneNumber(rawString5) // 输出: // processed5 = "123456789012345678901" // err5 = Invalid length for phone number, too long: 123456789012345678901 ``` 如果出 error 則會[跳過](https://adc.github.trendmicro.com/CoreTech-ERS/App-eureka/blob/master/internal/msgdecode/decoder.go#L378-L381) 與此同時,透過 amps API 搜集 phone number 的 Parser 3,卻有著一些不太一樣的做法, 我們過去從眾多 [來源](https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/tree/master/app/PRS2BuildSolution#prs-main-flow) 搜集 phone number,在 post 蒐集到的 phone number 以前,會先在 app-pyspark 做一些 [前處理](https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/blob/master/app/PRSFmaSourcing/common.py#L63-L85) ,基本上處理邏輯跟 Parser 1、Parser 2 類似,就是把標點符號拿掉,並把開頭的 0 去掉。接著會把處理後的 phone number post 到 amps prs api,而在進 db 以前,還會經過一段分離 country code 跟 phone number 的 [function](https://adc.github.trendmicro.com/CoreTech-ERS/App-amps-webservice/blob/master/src/SenderPhoneReputationHandler.py#L200-L208) amps api 分離 country code 跟 phone 的簡單圖示如下 ![](https://i.imgur.com/DYvQauZ.png) # problem 1. Parser 不同步 由前例圖中可以得知,現階段我們各區域的 Parser 並沒有完全統一,例如一組電話號碼 `0912123123`,若是從 App-pyspark 輸入,就會被處理成 `912123123` 才打 amps api,最終存在 DB 的資料即為 `912123123`。但如果是直接打 amps api,則會在 DB 存成 `0912123123` 造成結果是,明明是同一筆電話號碼,卻會有兩種被存在 DB 的形式 2. Query data 跟 pattern data 不一樣(trimmed 0 如前述,經過 Eureka 處理後的電話號碼,會把最開頭的 0 給去掉,例如 `0912123123`,會變成 `912123123` 去跟 pattern mapping。但我們在出 Pattern 的時候,卻沒有把開頭的 0 拿掉,像是下方的 pattern data。這就會變成,明明有電話被紀錄在 DB,但最終經過 Eureka 後,卻會回一個沒 detect 的 RID ``` PRS pattern 08030172028,8.0 08064919823,8.0 08011337625,8.0 08067620627,8.0 ``` ![](https://i.imgur.com/bCHqIlq.png) 3. Phone number hard to define if not E.164(+8869121231123) - 現階段我們的 prs 分割 country code 跟 phone number 還是用自己的方式在處理的,而這種做法其實很容易有誤判,像是 `+1 242-555-0123` 的美國手機號碼,就會被我們判成 **Country Code:1242 phone :5550123** - 如果非 E.164 格式,則難以界定該電話是哪一國的電話,像是我們在 prs-fma-sourcing 處理 phone number 去打 amps api 時候,有機會把這類的電話號碼的第一個 0 給去掉,造成問題二的現象。簡單來說,去掉 0 並沒有減少 FP 的發生,卻將 phone number 的一些資訊給去掉了,像是 `0912123123` 跟 `00912123123` 這兩個可能是不同國家的電話,卻可能在 DB 內都存成 `912123123` # Solution ### TMASE 更改 extract 規則 ### EUREKA ### APP-PYSPARK PHONE NUMBER COLLECT ETL ### DNS prs ask ## 改動 ## 改動前數據 ## Good to have ## #### 問題1 ``` 08090080406,8.0 08052500440,8.0 08064856158,8.0 09045743349,8.0 08075371143,8.0 09093243477,8.0 08061335270,8.0 08039213999,8.0 08067547313,8.0 09093807976,8.0 09053256421,8.0 ``` 這些東東 detect 不到 #### 原因 Eureka parser 會把 0 拿掉去 match https://github.trendmicro.com/CoreTech-ERS/Library-TMASE/blob/d3c6a5a7eae17b3f494e063f54e10a5b83e55ed3/TMASE/src/tmase/CScamFilter.cpp#L439-L447 ## Backward Compatibility - Tmase - Eureka - RPS API ## Multiple Request Income Other Request (FBN....) - FBN 用這樣的方式去把這個處理 ## 待處理問題 1. 沒有處理 ATTRIBUTE_MATCHING 這邊如果 prs 是空的該如何處理 2. Tmase Engine parser 改動 3. PRS 有一 ETL 是去找壞壞信,爬出裡面 body 有 phone 然後塞回 DB 的 https://adc.github.trendmicro.com/CoreTech-ERS/App-pyspark/blob/master/app/PRSHoneypotSourcing/prs_honeypot_sourcing.py#L134 但這 ETL 的作法,抓出來看 regex 的 email content 有很大機會碰到 base64 encoded 的 mail body,他好像沒有解開就去 regex match phone number 了(這樣當然啥都 match 不到?),看來我們 insert prs 的東東也沒認真 insert XDDD