Web開發基本准則-55實錄-Web訪問安全


  Web開發工程師請閱讀下面的前端開發准則,這是第一部分,強調了過去幾年里我們注意到的Web工程師務須處理的Web訪問安全基礎點。尤其是一些從傳統軟件開發轉入互聯網開發的工程師,請仔細閱讀,不要因為忽視這些基礎點而制造一個又一個的漏洞或突發事件。

Web開發基本准則-55實錄-Web訪問安全

鄭昀 創建於2013年2月

鄭昀 最后更新於2013年10月14日


提綱:

  1. Web訪問安全
  2. 緩存策略
  3. 存儲介質連接池
  4. 業務降級
  5. 並發請求的處理

關鍵詞:

Session Hijacking,XSS(Cross Site Scripting),SQLi(SQL Injection),CSRF(Cross-Site Request Forgery),FormHash,Rate Limits,平行權限


一,Web訪問安全

1.1.利用 FormHash 防 CSRF 和表單自動提交

  FormHash 指的是,通過在 Form 表單中構造一個隱藏的 input 元素,如:

  <input type="hidden" name="formhash" id="formhash" value="{FORMHASH}" />

  讓第三方難以偽造這個 input 的 value,借此阻止網站外部隨意構造表單提交,即防CSRF。適合的業務場景有注冊、登錄、下單、秒殺、抽獎、積分換代金券等等。

  

1.1.1.康盛的做法

  康盛的產品如 Discuz 為了防止灌水機發帖,FormHash 值是這么計算的:

  它的計算函數為 formhash() :

function formhash($specialadd = '') {      

global $_G;  

$hashadd = defined('IN_ADMINCP') ? 'Only For Discuz! Admin Control Panel' : '';   

return substr(md5(substr($_G['timestamp'], 0, -7)

        .$_G['username'].$_G['uid'].$_G['authkey']

        .$hashadd.$specialadd), 8, 8);

}

  首先,substr($_SGLOBAL['timestamp'], 0, -7),截取時間戳前3位(注意,康盛的這種做法允許 formhash 在一定的時間里生效且不變,由於截取了時間戳的前3位,那么有效期范圍是115天)。

  然后與用戶名、用戶UID、authke​y、自定義的key等字符串連接。這里的 authkey 是根據服務器端配置文件里的 authkey 與客戶端 cookies 里的 saltkey 鍵值連接后,md5 一下得到的,所以並不一定是固定值,取決於你怎么向客戶端里種 saltkey cookie 了(康盛選擇的是種一個 random(8) 的隨機值)。

  最后再做一次 md5,截取字符串的8位。

  服務器端用 submitcheck 函數進行驗證時,會再算一遍 formhash 來與客戶端提交的進行比對:$_POST['formhash'] == formhash()

 

  康盛的 formhash 仿造幾率很小,但也不見得是“不同表單不同隨機值”,所以可以在登錄后從康盛產品的網頁中得到一個 formhash 字符串,以及 cookies 里的 saltkey 鍵值,然后構造表單並構造 HTTPRequest,提交即可,115天內有效

  只能說康盛的做法簡單且有一定效果,適合作為你起步的 Plan A 抵擋一陣子。

 

1.2.通過全局 Filter 檢測或過濾 XSS/SQLi/shell注入

  通過烏雲網的漏洞列表,我們可以發現 XSS注入[注1]/SQL 注入無處不在,各大廠商前赴后繼地犯錯。如果框架本身不能有效攔截或檢測,僅憑借鐵打營盤流水兵的工程師自己的覺悟,恐怕朝不保夕。

 

  常見的誤區是,(因為XSS漏洞很常見所以認為)XSS沒什么了不起的,不會起多大風浪。

  一個弱漏洞可能沒事兒,但是攻擊者往往很有恆心毅力,如果被他們找到一連串的弱漏洞,再加上社會工程學的手段(請參考2013年,利用社工攻陷知乎后台的安全案例),千里之堤就會毀於蟻穴。譬如,一個前台的存儲型XSS漏洞,配合管理后台的登錄帳號 Session Hijacking,就能輕易突入管理后台。

  鄭昀推薦你閱讀以下安全案例以增進認識(有圖有真相):

  

  所以,首先,最好是在框架層面增加全局 Filter,對 HTTP Request 中的 $_GET/$_POST/$_COOKIE 進行字符串過濾,這種 Filter 將是強制性的。(出於防范CSRF(Cross-Site Request Forgery,跨站請求偽造)的考慮[注4],工程師盡量不要使用 $_REQUEST。)

  對於 PHP 來說,還可以在開發環境引入 laruence 的檢測 xss/sql/shell 注入的 PHP 擴展模塊:PHPTaint[注2]。

  其次,杜絕裸寫SQL。

  確保所有拼裝SQL參數的地方都有對參數進行校驗的預編譯環節,如使用 java.sql.PreparedStatement

 

1.2.1.大的原則是:不要相信客戶端提交的數據

  要深刻理解XSS的原理,攻擊代碼不一定(非要)在 <script></script> 中

  所以,處理XSS注入的時候,不僅僅要轉義或刪除特殊的 HTML 標記和符號,如尖括號<>,如script,如iframe等,還需要過濾 JavaScript 事件所涉及的大量屬性,如下表所示:

屬性

當以下情況發生時,出現此事件

onabort

圖像加載被中斷

onblur

元素失去焦點

onchange

用戶改變域的內容

onclick

鼠標點擊某個對象

ondblclick

鼠標雙擊某個對象

onerror

當加載文檔或圖像時發生某個錯誤

onfocus

元素獲得焦點

onkeydown

某個鍵盤的鍵被按下

onkeypress

某個鍵盤的鍵被按下或按住

onkeyup

某個鍵盤的鍵被松開

onload

某個頁面或圖像被完成加載

onmousedown

某個鼠標按鍵被按下

onmousemove

鼠標被移動

onmouseout

鼠標從某元素移開

onmouseover

鼠標被移到某元素之上

onmouseup

某個鼠標按鍵被松開

onreset

重置按鈕被點擊

onresize

窗口或框架被調整尺寸

onselect

文本被選定

onsubmit

提交按鈕被點擊

onunload

用戶退出頁面

 表1 JavaScript事件屬性表

  否則,就可能出現下面這兩種的XSS漏洞實例:

例1:

  http://YourDomain.com/index?num=1%22+onmousemove%3Dalert%284%29+wb%3D%22

  %22就是單引號的轉義,%3D是等號,%28是左括號,%29是右括號。鼠標移動可觸發。

例2:

  訪問 http://YourDomain.com/;

  在頁眉的搜索輸入框中輸入關鍵詞:" onmousemove=alert(4) wb=" (注:包含雙引號);

  在搜索結果頁面上,當鼠標移動時,就會彈出XSS種下的JS彈出框。

 

1.3.驗證碼服務不簡單

  圖片驗證碼或者答題驗證碼是為了盡可能狙擊注冊機、秒殺器等非人類行為,自然就成了攻防第一線的重要技術。

  

攻:提前收集驗證碼。適用場景:秒殺。在秒殺開始前就收集好驗證碼,從而提前准備好表單。

防:1)不同業務的驗證碼不得混用,登錄、注冊、抽獎、秒殺、下發短信驗證等各是各的。2)像秒殺這種與時間有關的業務場景,驗證碼就不允許提前生成。即使刻意構造出某個秒殺活動的圖片驗證碼URL訪問,也必須先判斷秒殺活動開始時間,阻止提前訪問。

 

攻:構造表單時使用過期 cookie

驗證碼一般是瀏覽器提交 cookie 里的 verifysession(一個標識本次驗證會話的 Hash 串)和手工輸入的驗證碼字符串 verifycode,服務器端按 F(verifysession)==verifycode 進行校驗。那么秒殺器突破時,別用服務器之前響應的 Hash 串,一直用自己手中掌握的 verifysession 和 verifycode 提交,就可以突破了。即使這一組 verifysession 和 verifycode 在服務器端驗證后立即失效,也無所謂,多准備幾組數據,就拼誰的秒殺器並發提交快即可。

防:1)結合 FormHash 方法聯防。2)針對不同業務生成的驗證碼的過期時間可以單獨設定。可以讓某個業務的驗證碼圖片過期時間很短。

 

攻:OCR識別圖片驗證碼

防:如果業務場景確實非常需要狙擊機器提交,那么上答題驗證碼,但也因此有了“題庫有限”這個弱點。

 

攻:(既然題庫有限那么)通過刷秒殺頁面來收集題目。然后人工快速回答,或者 OCR 識別問題內容,自動匹配答案。

防:FormHash 有一定作用,但對於“按鍵精靈”軟件錄制腳本(而不是機器構造表單),確實難以防范,第三方只要比真正的用戶響應快、提交快即可。

 

攻:答題時,構造表單使用過期題目

原理類似於使用過期 cookie。如果本次秒殺商品對應的答題不是一對一鎖定的(即換其他題提交也可以),那么也可以強制使用過期題目。

防:加Token。讓 Token 的生成與業務的具體場景有關。如一個 Token 由登錄用戶(以user id標識)和當前秒殺商品(以goods id標識)等關鍵信息生成。也是 FormHash 思路的延續。或者當前秒殺綁定題目,禁止使用其他題目答題。

 

攻:上面的措施都擋不住我。

防:攔人。對於黑名單用戶(手動加或自動識別),他能參與秒殺,但總是得到如下提示“系統繁忙:人太多了,休息一下,等等吧”。

 

其他電商的做法參考鄭昀的《對付秒殺器等惡意訪問行為的簡單梳理》 [注6] 。

 

1.4.敏感信息存入 cookies 須防篡改

  電商應用有時候不可避免地存儲了一些敏感數據到客戶端,當然不希望被客戶端篡改。

  所以可以在 set-cookie 時加上防篡改驗證碼,或者不暴露原值直接對稱加密存儲。

  如:user_name=alex|bj95ef23cc6daecc475de

 

  防篡改驗證碼的生成規則可以很簡單:md5(cookieValue+key)或sha1(cookieValue+key),key可以是服務器端掌握的一個固定字符串,也可以很復雜(如LTPA示例[注7])。

 

1.5.IP地址防偽造

  有人會說可以通過 request.getHeader("X-FORWARDED-FOR") 獲得ip字符串,這個頭域簡稱 XFF ,只有在通過了 HTTP 代理或者負載均衡服務器時才會添加該項。

  但一定要知道 XFF 頭僅僅是 HTTP Headers 中的一分子,那自然是可以隨意增刪改的。很多投票系統都有此漏洞,它們簡單地取 XFF 頭中的ip地址,設置為客戶端來源地址,因此第三方可以偽造任何ip投票。

  所以規則一:不要輕信 HTTP Headers 里的IP字段

  

  還與客戶端到服務器端之間的路徑有關,所以工程師要關注生產環境里你的 WebServer 前面到底掛的是什么,Nginx 的 proxy_set_header 是怎么配置的。

  幾種場景:1)F5->Nginx->WebServer;2)F5->WebServer;3)Client->CDN->Nginx。搞清楚場景和配置,拿到真正的 Remote Address,請參考鄭昀的《客戶端的IP地址偽造、CDN、反向代理、獲取的那些事兒[注8]》。

 

1.6.防 Session Hijacking

  當第三方以如下手法獲得了你的瀏覽器標識會話的字符串,那么他也許能以你的身份冒名操作:

  1. 從訪問記錄里獲得 URL 上攜帶的 Session Token;
  2. 利用 XSS 漏洞竊取 Cookie 里存儲的 Session Token。

  所以,首先絕不在 URL 中傳遞 Session Token,除非走 HTTPS 通道。

  其次,需要多管齊下,1)cookie 里的 Session Token,必須設定為 httponly禁止 JavaScript 讀取,以絕后患;2)如果服務器端還需要 cookie 里存儲的用戶ID等信息,那么 cookie 鍵值需要加簽名防篡改;3)根據客戶端的IP地址、User-Agent、Session和其他信息生成一個 UA Token,存儲在 cookie 里;服務器端每次都會核對這個 UA Token 是否正確,如果不正確則退出登錄。這樣,即使第三方拿到了你的 Session Token,也無法處於登錄狀態。

 

1.7.用 Robots.txt 限制住搜索引擎

  每一個對公網暴露的 Web 工程,上線之初理應配有 Robots.txt ,不僅僅是為了SEO,而且要限制站點的某些目錄不允許抓取和收錄。

  內部站點的robots.txt 內容必須(MUST)是

  User-agent: *

  Disallow: /

  不少瀏覽器都會向搜索引擎傳送訪問歷史你以為的內部隱秘訪問地址,可能早已被搜索引擎收錄了,所以對此絕不要掉以輕心。不要給入侵者借搜索“site:YourDomain.com”或“site:YourDomain.com URL:/YourPath” 遍歷內部站點的機會。

  鄭昀推薦你閱讀以下安全案例增進認識:

 

1.8.敏感信息的存儲和展示

  牢記一點,你的數據庫很有可能被拖庫,我們要未雨綢繆,降低拖庫后的危害

  所以,敏感信息請加密存儲

 

1.8.1.密碼的存儲

  首先,絕不能僅僅 MD5(password) 存儲,這樣等同於明文存儲。其次鐵律是,禁止明文存儲(登錄)密碼。

  最簡單的辦法是,隨機生成 SaltKey 並存儲,按 MD5(salt+MD5(password)) 存儲密碼。

  如果密碼需要二次分發(而不是重置密碼),請對稱加密存儲(應用程序掌管公鑰私鑰)。

 

1.8.2.敏感信息的展示

  牢記一點,第三方很有可能拿到你的平台登錄權限(通過 session hijacking,或通過內部人),所以要未雨綢繆,敏感字段不要輕易示人

  所以,敏感信息盡量不要明文展示,即使是合法用戶登錄狀態下

  

  以下信息需“中間若干位星號顯示”,如果沒有特別理由,那么默認不能直接顯示(包括導表):

  • (商戶的)銀行帳號,
  • (商戶的或用戶的)手機號碼和郵箱地址。

 

  鄭昀推薦你閱讀以下安全案例增進認識:

 

1.9.平行權限像XSS一樣是每個新工程師都會跌入的大坑

  未判斷資源使用者與資源擁有者權限是否相符,新工程師特別容易犯這種錯誤,尤其是當框架或業務中心沒有做ACL限制的話。

  鄭昀推薦你閱讀這幾個典型安全案例,希望能警醒大家,犯這種錯誤真的覆水難收,能造成災難性后果

  提醒兩點:

  第一,面向公眾用戶(C)的Web工程,URL上,或提交的表單里,盡量不要出現整數類型的id(如訂單id,如商品id,如活動id,如地址id),否則容易被人猜出順序,隨意更改,從而遍歷數據。請加密你的整數類型id后傳遞(注:切勿直接MD5加密,因為它等同於明文加密)

  第二,面向C或商業用戶(B)的Web工程,接到資源的瀏覽或操作請求后,先校驗請求提交者的身份權限。

 

  公網上的權限校驗大體有幾種場景:

  • 對於平台運營商來說,肯定需要(高級)有權限對這些數據進行讀寫操作,如后台管理平台。
  • 對於在平台上開展業務的第三方來說,一旦與某一個用戶產生了直接的交易,那么可能有權讀寫該用戶的數據,如讀取用戶部分信息,對用戶訂單發起退款申請。
  • 登錄會員有權對自己的數據進行操作。

  針對這些場景,我們可能需要對目標數據的訪問進行不同邏輯的權限檢查。

  權限校驗規則:

  • 如果是平台運營系統請求數據,那么信任發起者身份,不再進行權限校驗。
  • 如果是平台接入第三方請求數據,那么應該檢查該數據的擁有者(即會員或系統管理員)是否授權該系統訪問其信息。
  • 對於會員本身,需要檢查目標數據的擁有者與請求方是否同一用戶。

 

1.10.防表單重復提交

  有兩個含義:

  1. 頁面無刷新情況下,某些業務場景需要主動阻止表單重復提交:
    • 有的業務場景支持重復提交但會提示:如實物類電商,同一個 SKU 提示重復加入購物車、但仍能加入購物車,只是在相同 SKU 上加數量;
    • 有的場景會通過以下手法盡量提前避免表單(尤其是數據未變化的情況下)重復提交,而不用非要到服務器端在數據庫層面做重復數據判斷:
      • 按鈕點擊后變灰(按鈕文字可以更改,如顯示倒計時),收到 Ajax 響應后再恢復,典型場景是填寫手機號碼點擊按鈕下發短信驗證碼時;
  2. 頁面刷新情況下,盡量阻止表單重復提交:
    • 用戶行為有:
      • 用戶按F5刷新(注意,不是Ctrl+F5強制刷新);
      • 用戶點擊瀏覽器的后退或前進功能回到之前的網頁;
    • 這時需要服務器端配合了:
      • POST 表單提交后,服務器端做302跳轉,利用302跳轉清空表單參數
      • 延續 FormHash 思路,服務器端收到 formhash 值后存入緩存,幾分鍾后過期,這樣校驗邏輯可以阻止幾分鍾內的含相同 formhash 值的表單重復提交。

 

1.11.訪問速率限制Rate Limits

  有一些業務場景需要針對用戶短時間內過多的訪問頻次,制定不同的防范措施,如:

  • 停止當前服務,提示訪問過於頻繁請稍后再試;
  • 302跳轉到 ServerBusy 之類的頁面;
  • 短時間內拒絕對方IP地址的請求,如三分鍾;
  • 連續觸發報警閾值,則將對方IP加入黑名單,封殺較長時間,如一天。

  簡而言之,我們希望限制住的是,在用M度量的任何時間周期內,某一個動作(action)的發生次數N。

 

1.11.1.我們所希望的業務限流

  業務限流的目的是:

  • 防掃號防暴力破解場景:防止對手高速掃描(或調用)我們的系統某個URI。這種場景經常發生在凌晨,對於異常訪問,我們系統必須第一時間攔截,在這種情況下,可能不允許太高的突發。
  • 保證系統平穩運行:系統承載能力有限,數據庫支撐能力有限,所以不希望系統由於突發陡增請求而引發下游系統性能出現凸起,當然適量的波動是允許的。

  工程上有幾種做法:

1.11.2.簡單的memcache以秒為單位的度量

 memcache 里的 key 可以為:業務編號_IP地址_時間戳_Limiter種類。時間戳精確到秒或分鍾。

 

1.11.3.漏桶(Leaky Bucket)算法

  Nginx 的 limitReq 模塊采用的就是漏桶算法,分 delay 和 nodelay 兩種處理模式。

  我們用實際例子來演示一下[注11]:

01     #以用戶二進制IP地址,定義三個漏桶,滴落速率1-3req/sec,桶空間1m,1M能保持大約16000個(IP)狀態
02     limit_req_zone  $binary_remote_addr  zone=qps1:1m   rate=1r/s;
03     limit_req_zone  $binary_remote_addr  zone=qps2:1m   rate=2r/s;
04     limit_req_zone  $binary_remote_addr  zone=qps3:1m   rate=3r/s;
05      
06     server {
07      
08     #速率qps=1,峰值burst=5,延遲請求
09     #嚴格按照漏桶速率qps=1處理每秒請求
10     #在峰值burst=5以內的並發請求,會被掛起,延遲處理
11     #超出請求數限制則直接返回503
12     #客戶端只要控制並發在峰值[burst]內,就不會觸發limit_req_error_log
13     # 例1:發起一個並發請求=6,拒絕1個,處理1個,進入延遲隊列4個:
14     #time    request    refuse    sucess    delay
15     #00:01        6        1        1            4
16     #00:02        0        0        1            3
17     #00:03        0        0        1            2
18     #00:04        0        0        1            1
19     #00:05        0        0        1            0
20     location /delay {
21         limit_req   zone=qps1  burst=5;
22     }
23      
24     #速率qps=1,峰值burst=5,不延遲請求
25     #加了nodelay之后,漏桶控制一段時長內的平均qps = 漏桶速率,允許瞬時的峰值qps > 漏桶qps
26     #所以峰值時的最高qps=(brust+qps-1)=5
27     #請求不會被delay,要么處理,要么直接返回503
28     #客戶端需要控制qps每秒請求數,才不會觸發limit_req_error_log
29     # 例2:每隔5秒發起一次達到峰值的並發請求,由於時間段內平均qps=1 所以仍然符合漏桶速率:
30     #time    request     refuse    sucess
31     #00:01         5         0          5
32     #00:05         5         0          5
33     #00:10         5         0          5
34     # 例3:連續每秒發起並發請求=5,由於時間段內平均qps>>1,超出的請求被拒絕:
35     #time    request     refuse     sucess
36     #00:01         5         0           5
37     #00:02         5         4           1
38     #00:03         5         4           1
39      
40     location /nodelay {
41         limit_req   zone=qps1  burst=5 nodelay;
42     }
43      
44     }

 

1.11.4.令牌桶(Token Bucket)算法

  令牌桶具體實現:

  在數據結構上,沒有必要真的實現一個令牌桶。

  基於時間的流逝生成受控制數量的令牌即可——以時間的流逝來洗滌舊跡,也就是將兩次發包或者收包的間隔和令牌數量聯系起來。

 

  令牌桶和漏桶算法最主要的差別在於:漏桶算法能夠強行限制數據的傳輸速率,而令牌桶算法能夠在限制數據的平均傳輸速率的同時還允許某種程度的突發傳輸。

 

  相對於漏桶算法,令牌桶的波動幅度可能是我們系統無法承受的。

  令牌是基於 Request 觸發投放到令牌桶的,如果是按照下面的投放策略

            delta = self.fill_rate * (now - self.timestamp)#fill_rate is the rate in tokens/second that the bucket will be refilled.

            self._tokens = min(self.capacity, self._tokens + delta)

  那么代入演算一下,令牌桶令牌總數 capacity=80,還剩余0張令牌,令牌桶填充速率fill_rate=0.5t/s,流逝的時間是10秒,即過去的10秒沒有任何請求,第11秒突然拿來了一個請求,於是令牌桶里就會放入min(80,5)=5張令牌,意味着第11秒可以消耗5個令牌。

  這也就是我們為什么說令牌桶算法是“只要令牌桶中存在令牌,那么就允許突發地傳輸數據直到達到用戶配置的上限,因此它適合於具有突發特性的流量”的緣故。

 

  了解更多漏桶和令牌桶算法信息,請參考鄭昀的《集群環境下業務限流[注10]》。

 

1.11.5.滑窗(Sliding Window)算法

  淘寶中間件博客上曾提及,『流量預警和限流方案中,滑窗模式通過統計多個單元時間的訪問次數來進行控制,當單位時間的訪問次數達到某個峰值時進行限流。

  在每次有訪問進來時,我們判斷前N個單位時間里總訪問量是否超過了設置的閾值,若超過則不允許執行。

缺點一:

由於訪問量的不可預見性,會出現單位時間的前半段有大量請求涌入,而后半段則拒絕所有請求的情況發生。

缺點二:

其次,我們很難確定這個閾值設置在多少比較合適,只能通過經驗或者模擬(如壓測)來估算。不過即使是壓測也很難估計准確。

  所以滑窗模式往往用來對某一資源的保護上(或者說是承諾比較合適:我對某一接口的提供者承諾過,最高調用量不超過XX),如對 DB 的保護,對某一服務的調用的控制上。

 

  代碼實現思路如下:

  每一個窗(單位時間)就是一個獨立的計數器(原子計數器),用以數組保存。將當前時間以某種方式(比如取模)映射到數組的一項中。每次訪問先對當前窗內計數器+1,再計算前N個單元格的訪問量綜合,超過閾值則限流。

  這里有個問題,時間永遠是遞增的,單純的取模,會導致數組過長,使用內存過多,我們可以用環形隊列來解決這個問題。』

 

-未完待續-


備注參考資源:

1,2012,TankXiao,Web安全測試之XSS

2,2012,laruence,PHP Taint-一個用來檢測XSS/SQL/shell注入的擴展

3,JavaScript事件參考手冊

4,2009,hyddd,淺談CSRF攻擊方式

5,2011,zgynhqf,“秒殺”心得

6,2012,鄭昀, 電商課題:對付秒殺器等惡意訪問行為的簡單梳理

7,2012,鄭昀,電商課題:cookie防篡改

8,2012,鄭昀,電商課題:客戶端的IP地址偽造、CDN、反向代理、獲取的那些事兒

9,2013,鄭昀,5·12和6·17兩知名網站域名被劫持事件實施過程回放

10,2012,鄭昀,電商課題I:集群環境下業務限流

11,2012,jxy918,nginx limit_req限速設置

 

贈圖幾枚:

http://ww1.sinaimg.cn/bmiddle/b0b1926bjw1e9emqkd7h9g206t06te3r.gif

羅輯思維-2013-中國窄門 44

http://ww2.sinaimg.cn/bmiddle/b0b1926bjw1e827o6adb0j20dw0iuac7.jpg

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM