page.title=Cấu hình Bảo mật mạng page.keywords=androidn,security,network page.image=images/cards/card-nyc_2x.jpg @jd:body
Android N có tính năng Cấu hình Bảo mật mạng cho phép ứng dụng tùy chỉnh các cài đặt bảo mật mạng trong một tệp cấu hình khai báo an toàn mà không cần sửa đổi mã nguồn ứng dụng. Các cài đặt này có thể được cấu hình cho các miền cụ thể và cho một ứng dụng cụ thể. Các khả năng chính của tính năng này như sau:
Tính năng Cấu hình Bảo mật mạng sử dụng một tệp XML làm nơi bạn sẽ chỉ định các cài đặt cho ứng dụng của mình. Bạn phải bổ sung một mục nhập trong bản kê khai của ứng dụng để trỏ đến tệp này. Đoạn mã sau của một bản kê khai minh họa cách tạo mục nhập này:
<?xml version="1.0" encoding="utf-8"?> ... <app ...> <meta-data android:name="android.security.net.config" android:resource="@xml/network_security_config" /> ... </app>
Một ứng dụng có thể muốn tin cậy một bộ các CA tùy chỉnh thay vì mặc định của nền tảng. Những lý do phổ biến nhất cho điều này là:
Theo mặc định, các kết nối bảo mật (vd: TLS, HTTPS) từ mọi ứng dụng sẽ tin cậy các CA của hệ thống được cài đặt trước và các ứng dụng nhắm mục tiêu mức API 23 (Android M) và thấp hơn theo mặc định cũng tin cậy kho lưu trữ CA được người dùng bổ sung. Một ứng dụng có thể tùy chỉnh các kết nối của riêng nó bằng cách sử dụng {@code base-config} (dành cho tùy chỉnh trên phạm vi ứng dụng) hoặc {@code domain-config} (tùy chỉnh cho mỗi miền).
Giả sử bạn muốn kết nối tới máy chủ của mình có sử dụng các chứng chỉ SSL tự ký hoặc tới một máy chủ có chứng chỉ SSL được cấp bởi một CA không công khai mà bạn tin cậy, chẳng hạn như CA nội bộ của công ty.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
Thêm chứng chỉ CA tự ký hoặc không công khai theo định dạng PEM hoặc DER vào {@code res/raw/my_ca}.
Một ứng dụng không muốn tin cậy mọi CA được hệ thống tin cậy có thể chỉ định bộ CA hạn chế của riêng nó để tin cậy. Điều này sẽ bảo vệ ứng dụng khỏi các chứng chỉ lừa đảo được cấp bởi bất kỳ CA nào khác.
Cấu hình để giới hạn bộ CA đáng tin cậy cũng giống như Tin cậy một CA tùy chỉnh cho một miền cụ thể ngoại trừ việc nhiều CA được cung cấp trong tài nguyên.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
Thêm các CA đáng tin cậy theo định dạng PEM hoặc DER vào {@code res/raw/trusted_roots}.
Lưu ý rằng nếu sử dụng định dạng PEM thì tệp chỉ được chứa dữ liệu PEM
và không có thêm dữ liệu văn bản. Bạn cũng có thể cung cấp nhiều
phần tử <certificates>
thay vì một phần tử.
Một ứng dụng có thể muốn tin cậy các CA bổ sung không được hệ thống tin cậy, điều này có thể do hệ thống chưa thêm CA đó hoặc một CA không đáp ứng các yêu cầu để đưa vào hệ thống Android. Một ứng dụng có thể thực hiện điều này bằng cách chỉ định nhiều nguồn chứng chỉ cho một cấu hình.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
Khi gỡ lỗi một ứng dụng kết nối qua HTTPS thì bạn có thể muốn kết nối tới một máy chủ phát triển cục bộ không có chứng chỉ SSL dành cho máy chủ thương mại của bạn. Để hỗ trợ cho trường hợp này mà không cần chỉnh sửa mã nguồn ứng dụng của bạn thì bạn có thể chỉ định các CA chỉ dùng cho gỡ lỗi mà chỉ được tin cậy khi android:debuggable là {@code true} bằng cách sử dụng {@code debug-overrides}. Thông thường các IDE và công cụ dựng sẽ đặt cờ này tự động đối với các bản dựng không dùng để phát hành.
Làm như vậy an toàn hơn so với mã điều kiện thông thường bởi, là điều kiện bảo mật tiên quyết, các cửa hàng ứng dụng không chấp nhận các ứng dụng được đánh dấu là hỗ trợ gỡ lỗi.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
Các ứng dụng có ý định kết nối tới các điểm đích chỉ sử dụng các kết nối bảo mật có thể bỏ hỗ trợ truyền gửi văn bản không mã hóa (bằng giao thức HTTP không mã hóa thay vì HTTPS) tới các đích đó. Tùy chọn này giúp ngăn các hồi quy tiềm tàng trong ứng dụng do thay đổi trong các URL được cung cấp bởi các nguồn bên ngoài như các máy chủ phụ trợ. Hãy xem {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted NetworkSecurityPolicy.isCleartextTrafficPermitted()} để biết thêm chi tiết.
Ví dụ, một ứng dụng có thể đảm bảo rằng mọi kết nối tới {@code secure.example.com} luôn được thực hiện qua HTTPS để bảo vệ việc truyền gửi dữ liệu nhạy cảm khỏi các mạng có hại.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config usesCleartextTraffic="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
Thông thường thì một ứng dụng sẽ tin cậy mọi CA được cài đặt sẵn. Nếu bất kỳ CA nào trong số này sẽ phát hành một chứng chỉ lừa đảo thì ứng dụng sẽ gặp phải rủi ro từ một cuộc tấn công MiTM. Một số ứng dụng chọn cách giới hạn bộ chứng chỉ được chúng chấp nhận bằng cách giới hạn bộ CA được ứng dụng tin cậy hoặc bằng cách ghim chứng chỉ.
Ghim chứng chỉ được thực hiện bằng cách cung cấp một bộ chứng chỉ theo mã hash của khóa công khai (SubjectPublicKeyInfo của chứng chỉ X.509). Một chuỗi chứng chỉ khi đó chỉ hợp lệ nếu như chuỗi chứng chỉ có chứa ít nhất một trong các khóa công khai được ghim.
Lưu ý rằng khi sử dụng ghim chứng chỉ bạn phải luôn kèm thêm một khóa dự phòng để nếu bạn bị buộc phải chuyển sang các khóa mới hoặc thay đổi các CA (khi ghim vào một chứng chỉ CA hoặc một chứng chỉ trung gian của CA đó) thì kết nối của ứng dụng sẽ không bị ảnh hưởng. Nếu không bạn phải đưa ra một bản cập nhật cho ứng dụng để khôi phục khả năng kết nối.
Ngoài ra, có thể đặt thời gian hết hạn cho các ghim, sau thời gian đó sẽ không tiến hành ghim được. Điều này giúp phòng ngừa các vấn đề về kết nối trong ứng dụng chưa được cập nhật. Tuy nhiên, việc đặt thời gian hết hạn trên các ghim này có thể khiến ghim bị bỏ qua.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </domain-config> </network-security-config>
Các giá trị chưa được đặt trong một cấu hình cụ thể sẽ được kế thừa. Hành vi này cho phép tạo ra các cấu hình phức tạp hơn trong khi vẫn giữ cho tệp cấu hình có thể đọc được.
Nếu một giá trị không được đặt trong một mục nhập cụ thể thì giá trị thuộc mục nhập bao quát hơn tiếp theo sẽ được sử dụng. Các giá trị chưa được đặt trong {@code domain-config} sẽ được lấy từ phần tử cha {@code domain-config} nếu như được lồng, hoặc từ {@code base-config} nếu không được lồng. Các giá trị chưa được đặt trong {@code base-config} sẽ sử dụng các giá trị mặc định của nền tảng.
Ví dụ: hãy xem xét trường hợp tất cả các kết nối tới miền con của {@code example.com} phải sử dụng một bộ CA tùy chỉnh. Ngoài ra, truyền gửi văn bản không mã hóa tới các miền này được cho phép trừ khi kết nối tới {@code secure.example.com}. Bằng cách lồng cấu hình cho {@code secure.example.com} bên trong cấu hình cho {@code example.com} thì {@code trust-anchors} không cần phải được sao lặp.
res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
Tính năng Cấu hình Bảo mật mạng sử dụng một định dạng tệp XML. Cấu trúc chung của tệp này được thể hiện trong đoạn mẫu mã nguồn sau:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
Các phần sau sẽ mô tả cú pháp và các chi tiết khác của định dạng tệp này.
<base-config>
<domain-config>
<debug-overrides>
<base-config usesCleartextTraffic=["true" | "false"]> ... </base-config>
<trust-anchors>
domain-config
.
Bất kỳ giá trị nào chưa được đặt sẽ sử dụng các giá trị mặc định của nền tảng. Cấu hình mặc định cho các ứng dụng nhắm mục tiêu API mức 24 trở lên:
<base-config usesCleartextTraffic="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>Cấu hình mặc định cho các ứng dụng nhắm mục tiêu API mức 23 trở xuống:
<base-config usesCleartextTraffic="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config>
<domain-config usesCleartextTraffic=["true" | "false"]> ... </domain-config>
<domain>
<trust-anchors>
<pin-set>
<domain-config>
được lồngLưu ý rằng nếu nhiều phần tử {@code domain-config} chứa một điểm đích thì cấu hình có quy tắc miền trùng khớp cụ thể nhất (dài nhất) sẽ được sử dụng.
<domain includeSubdomains=["true" | "false"]>example.com</domain>
<debug-overrides> ... </debug-overrides>
<trust-anchors>
<trust-anchors> ... </trust-anchors>
<certificates>
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
Xác định xem liệu các CA từ nguồn này có bỏ qua việc ghim chứng chỉ hay không. Nếu {@code "true"} thì các chuỗi chứng chỉ mà xâu qua một trong các CA từ nguồn này thì khi đó ghim sẽ không được thực hiện. Đây có thể là điều có ích cho các CA gỡ lỗi hoặc để hỗ trợ cho người dùng tấn công MiTM hoạt động truyền gửi bảo mật của ứng dụng.
Mặc định là {@code "false"} trừ khi được chỉ định trong một phần tử {@code debug-overrides} , khi đó mặc định là {@code "true"}.
<pin-set expiration="date"> ... </pin-set>
<pin>
<pin>
để biết định dạng của các ghim.
Việc hết hạn giúp phòng ngừa các vấn đề về khả năng kết nối trong ứng dụng làm cho không nhận được các bản cập nhật cho bộ ghim, chẳng hạn như do người dùng vô hiệu hóa các bản cập nhật ứng dụng.
<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>