Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

4. Điều kiện để tấn công Remote Code Injection thành công.

Trong phần này, chúng tôi phân tích ba điều kiện cần thiết để Remote Code
Injection thành công vào các ứng dụng Android bằng cách sử dụng các đoạn mã
được dịch ngược làm ví dụ.

4.1. Không có hoặc bỏ qua kiểm tra xác thực:

Nói chung, các ứng dụng thường đảm bảo rằng các tài nguyên đã tải xuống
chưa được sửa đổi bằng cách sử dụng kiểm tra xác thực để xác minh tính toàn vẹn
của các tài nguyên đã tải xuống. Về vấn đề này, các máy chủ cung cấp một giá trị
băm duy nhất được tạo bởi hàm băm (chẳng hạn như MD5 và SHA-256) với tài
nguyên và ứng dụng so sánh giá trị băm được cung cấp với giá trị băm mới được
tính cho tài nguyên đã tải xuống. Nếu giá trị băm mà ứng dụng tính toán giống với
giá trị băm được cung cấp, ứng dụng sẽ xác định rằng không có gì sai với tài
nguyên đã tải xuống. Ngoài ra, các máy chủ có thể đính kèm thông tin xác thực
(như chữ ký) vào tài nguyên bằng cách ký điện tử giá trị băm vào sản phẩm đang
được phân phối. Điều này cho phép ứng dụng kiểm tra tài nguyên đã tải xuống
bằng cách xác minh chữ ký của nó. Những kẻ tấn công sau đó có thể giả mạo tài
nguyên chỉ khi chúng có thể đánh cắp khóa ký tên của máy chủ.

Tuy nhiên, kết quả khớp giá trị băm không nhất thiết đảm bảo rằng các tài
nguyên đã tải xuống không bị kẻ tấn công giả mạo. Điều này là do nếu giá trị băm
được cung cấp được truyền qua giao thức văn bản gốc, với sự trợ giúp của các
cuộc tấn công MITM, kẻ tấn công có thể bỏ qua kiểm tra xác thực bằng cách thay
đổi giá trị băm. Hơn nữa, và quan trọng nhất, các nhà phát triển đã quên hoặc
không nhận ra tầm quan trọng của kiểm tra xác thực đối với các tài nguyên đã tải
xuống [6]. Ví dụ, như đã thảo luận trong phần 2, nếu ứng dụng tự cập nhật không
xác minh tài nguyên đã tải xuống trong quy trình tự cập nhật, kẻ tấn công có thể
thực hiện thành công cuộc tấn công remote code injection bằng cách sửa đổi thông
tin cập nhật hoặc bằng cách thay thế tài nguyên tải về. Mặc dù ứng dụng tự cập
nhật xác minh các tài nguyên đã tải xuống bằng cách sử dụng giá trị băm do máy
chủ tương ứng cung cấp, nhưng điều này không đảm bảo rằng các tài nguyên đã tải
xuống không bị kẻ tấn công sửa đổi. Ví dụ, trong liệt kê 1, ứng dụng tự cập nhật sẽ
xác minh tài nguyên đã tải xuống bằng cách kiểm tra xem giá trị băm MD5 được
cung cấp hay không. Trong trường hợp này, nếu giá trị băm được truyền qua giao
thức văn bản gốc (HTTP), với sự trợ giúp của các cuộc tấn công MITM, kẻ tấn
công có thể bỏ qua kiểm tra xác thực bằng cách sửa đổi giá trị băm (trong
‘mvalue’, trong liệt kê 1). các cuộc tấn công vẫn có thể thành công trong trường
hợp kiểm tra xác nhận bị bỏ qua.

Liệt kê 2: Tải xuống tài nguyên mà không cần kiểm tra xác thực (được dịch
ngược từ Appnext SDK [15]).

Một ví dụ khác trong đó tài nguyên DRU được tải xuống mà không cần kiểm tra
xác thực được minh họa trong liệt kê 2. Đoạn mã cho các chi tiết của hình ảnh
được tải xuống trong Appnext SDK [15], một nền tảng phân phối ứng dụng và
kiếm tiền trên thiết bị di động. SDK tải xuống các tệp hình ảnh dưới dạng lưu trữ
ZIP từ máy chủ bên ngoài với liên kết tải xuống cố định tại địa chỉ trực tuyến
http://www.appnext.com/android/images2.zip, (dòng (3) trong liệt kê 2), được mã
hóa cứng trong ứng dụng. Sau đó, nó lưu trữ kho lưu trữ ZIP đã tải xuống trong thư
mục của ứng dụng trực tuyến mà không cần kiểm tra xác thực. Trong trường hợp
này, nếu DRU có thể bị lạm dụng để ghi đè lên các tệp thực thi hiện có, kẻ tấn
công có thể thực hiện thành công một cuộc tấn công remote code injection. Lưu ý
rằng các DRU như cập nhật tài nguyên hình ảnh xảy ra với tần suất rất cao trong
các triển khai ứng dụng ngày hôm nay.

4.2. Tập tin ghi đè lỗ hổng.


Sau khi kẻ tấn công truyền thêm dữ liệu của chúng bằng cách vượt qua kiểm
tra xác thực tài nguyên, dữ liệu truyền thêm được lưu trữ ở một vị trí cụ thể theo
triển khai DRU của ứng dụng, thường là trong thư mục dữ liệu của ứng dụng (/
data / data / NAMEAGE NAME) hoặc trong bộ nhớ ngoài ( chẳng hạn như thẻ
SD). Nếu DRU mà kẻ tấn công nhắm đến là cập nhật mã ứng dụng, mã được chèn
sẽ được thay thế bằng tài nguyên mã hiện có (ví dụ: .dex, .jar hoặc .so), sau đó
được tải và thực thi khi ứng dụng kích hoạt logic cập nhật. Trong những trường
hợp như vậy, kẻ tấn công chỉ cần truyền dữ liệu mà không có bất kỳ cân nhắc nào
để thực hiện một cuộc tấn công remote code injection thành công.

Mặt khác, không thể có DCL trong ứng dụng, điều này phổ biến trong phần
lớn các ứng dụng. Tuy nhiên, những kẻ tấn công vẫn có thể thực hiện thành công
các cuộc tấn công remote code injection bằng cách sử dụng các lỗ hổng ghi đè lên.
Nếu có một lỗ hổng ghi tùy ý trong ứng dụng, kẻ tấn công có thể khai thác nó để
ghi đè lên các tệp thực thi hiện có như .dex, .so và .jar. Watson [7] và Welton [8]
đã chỉ ra rằng trích xuất ZIP không an toàn có thể được sử dụng cho lỗ hổng ghi
tùy ý; do đó, các cuộc tấn công remote code injection có thể thành công với sự trợ
giúp của các lỗ hổng ghi đè lên.

Trong phần này, chúng tôi phân tích thêm các tệp khác ghi đè lên các lỗ
hổng có thể được sử dụng cho các cuộc tấn công remote code injection.

Khai thác ZIP không an toàn. Các ứng dụng Android đã triển khai kho lưu
trữ ZIP để tải xuống hoặc tải lên các tệp tài nguyên một cách hiệu quả đến các máy
chủ bên ngoài của chúng qua mạng. Tuy nhiên, như được hiển thị bởi Watson [7]
và Welton [8], nếu các nhà phát triển không xem xét ý nghĩa bảo mật của trích xuất
ZIP không an toàn [16], các lỗ hổng ghi đè tùy ý cho phép kẻ tấn công ghi đè lên
các tệp hiện có với dữ liệu chỉ định được truyền vào của họ.

Liệt kê 3 cho thấy một ví dụ về trích xuất ZIP không an toàn được triển khai
trong Appnext SDK[15]. Appnext SDK cập nhật tài nguyên hình ảnh của nó bằng
cách tải trực tiếp tệp lưu trữ ZIP (images2.zip) có chứa nhiều tệp .png từ máy chủ
của nó (doInBackground () trong liệt kê 2). Sau khi tải xuống kho lưu trữ ZIP,
Appnext SDK giải nén kho lưu trữ ZIP đã tải xuống, được lưu trữ trong thư mục
bên trong của ứng dụng (/ data / data / PACKAGE NAME / appnext / image2.zip),
để các tệp hình ảnh có thể được đặt trong mục đích thư mục (/ data / data /
PACKAGENAME/ appnext / files /). Để đạt được điều này, trước tiên phương
thức unzip () lấy một tên tệp (dòng (6)), sau đó nó sử dụng để tạo một luồng đầu ra
tệp để ghi vào tệp hình ảnh (dòng (14)). Do đó, nếu đầu vào của tên tệp không
được diệt virus và chứa thông tin truyền tải đường dẫn, nó có thể khiến tệp được
trích xuất bên ngoài thư mục dự định. Ví dụ: nếu tên tệp là
./../../../data/data/PACKAGE NAME / files / target.so, sẽ thay thế tệp target.so. Kẻ
tấn công có thể khai thác thực tế này để ghi đè lên các tài nguyên mã tùy ý hiện có
với dữ liệu được truyền vào của chúng. Lưu ý rằng lỗ hổng này xảy ra khi ứng
dụng không được diệt virus đầu vào của tên đường dẫn hoặc xác thực vị trí của nó.

Liệt kê 3: Trích xuất ZIP không an toàn (được dịch ngược từ Appnext
SDK ).

Nội dung không an toàn - Thực hiện bố trí. Các trình duyệt web hiện đại
thường sử dụng tiêu đề HTTP để tải xuống mạnh mẽ tài nguyên bên ngoài thay vì
hiển thị nó trên trình duyệt. Để tải xuống mạnh mẽ với tiêu đề HTTP, máy chủ
thêm trường Xử lý nội dung bao gồm tham số tên tệp trong tiêu đề phản hồi HTTP
(dòng (3) trong liệt kê 4) và, trong quá trình tải xuống tài nguyên bên ngoài ở phía
máy khách, trình duyệt lấy tên tệp từ tiêu đề phản hồi HTTP và lưu trữ tài nguyên
đã tải xuống với tên tệp được cung cấp.
Các nhà phát triển Android thường sử dụng tiêu đề phản hồi HTTP làm siêu
dữ liệu để lấy thông tin của tài nguyên đã tải xuống. Ví dụ: một ứng dụng có thể
truy xuất tên tệp của tài nguyên đã tải xuống từ tiêu đề phản hồi HTTP để hiển thị
tên tài nguyên trên màn hình hoặc lưu tài nguyên đã tải xuống vào bộ nhớ trong.
Để thực hiện việc này, trước tiên, ứng dụng sẽ nhận được giá trị của trường Xử lý
nội dung bằng cách sử dụng các API mạng như
org.apache.http.HttpResponse.getFirstHeader() và phương thức
java.net.HttpURLConnection.getHeaderField (). Sau đó, ứng dụng sẽ phân tích tên
tệp bằng API chuyên dụng, chẳng hạn như đoán FileName() trong lớp
android.webkit.URLUtil hoặc trình phân tích cú pháp do người dùng bảo vệ thực
hiện khớp biểu thức chính quy. Tuy nhiên, trong trường hợp này, nếu ứng dụng
không phân tích đúng tên tệp và chỉ sử dụng tên này làm tên tệp để tạo tệp, lỗ hổng
ghi đè tùy ý có thể tồn tại. Ví dụ: khi sử dụng khớp biểu thức chính quy với tệp
đính kèm chuỗi mẫu; Tên tập tin “s∗filename “s∗=“s∗““([̂“”]∗)“”, nếu trình so
khớp đánh giá tệp đính kèm; chuỗi filename=“./../../../target”, trình so khớp sẽ tìm
thấy một nội dung trong chuỗi ./../../../target chuỗi có chứa thông tin truyền tải
đường dẫn. Do đó, như với trích xuất ZIP không an toàn, kẻ tấn công có thể ghi đè
lên các tệp tùy ý bằng cách sửa đổi trường Xử lý nội dung trong tiêu đề HTTP.

4.3. Mã kích hoạt điểm.

Để thực hiện thành công một cuộc tấn công remote code injection, dữ liệu
được truyền vào phải được thực hiện trong ngữ cảnh của ứng dụng khi ứng dụng
khởi động hoặc trong khi nó đang chạy. Do đó, kẻ tấn công phải xác định một
điểm kích hoạt dữ liệu được truyền vào và thực thi nó. Tự cập nhật là một ví dụ tốt
về mã chứa điểm kích hoạt mã, theo đó dữ liệu được truyền và thực thi sau khi tải
xuống mã mới được phát hành.

Trong tiểu mục này, chúng tôi điều tra các điểm kích hoạt mã có thể có thể
được sử dụng cho các cuộc tấn công remote code injection.

Liệt kê 4: Kết hợp xử lý nội dung trong tiêu đề HTTP.


Thư viện thời gian chạy. Các ứng dụng Android có thể bao gồm các thư viện
thời gian chạy (như tệp .jar hoặc .so), được tải khi ứng dụng khởi động hoặc trong
khi ứng dụng đang chạy bằng cách sử dụng phương pháp thư viện tải (trong trường
hợp .so) hoặc trình tải DexClass (trong trường hợp .jar ). Bộ công cụ phát triển bản
địa (NDK) cho phép các nhà phát triển xây dựng mã nguồn C / C ++ của riêng họ
hoặc tận dụng các thư viện dựng sẵn. Các nhà phát triển có thể sử dụng các thư
viện riêng để cải thiện hiệu năng của ứng dụng hoặc sử dụng lại các thư viện của
nhà phát triển của riêng họ hoặc của nhà phát triển khác. Ngoài ra, các nhà phát
triển có thể tải các lớp từ .jar hoặc .apk để thực thi các phương thức không có trong
ứng dụng. Các thư viện thời gian chạy này có thể được sử dụng làm mục tiêu cho
các điểm kích hoạt mã. Trong Android, khi một ứng dụng sử dụng các thư viện gốc
do Android NDK xây dựng, các thư viện này được lưu trữ trong thư mục / lib và có
đặc quyền hệ thống. Do đó, các thư viện riêng trong / lib không thể được sử dụng
cho các điểm kích hoạt. Tuy nhiên, khi các nhà phát triển tạo thư viện (bao gồm .so
và .jar) và đánh dấu chúng là có thể ghi và đưa chúng vào thư mục ứng dụng / tài
sản, các thư viện này có thể được coi là điểm kích hoạt tiềm năng. Sau khi ứng
dụng được cài đặt, các thư viện này có thể được lưu trữ trong thư mục bên trong
của ứng dụng, chẳng hạn như / data / data / PACKAGE NAME / files. Những kẻ
tấn công biết thông tin đường dẫn này có thể ghi đè lên một trong những thư viện
này để thực hiện tải trọng được tiêm.

Multidex(đa chiều). Nền tảng Android hỗ trợ multidex để đối phó với giới
hạn tham chiếu 64k giới hạn tổng số phương thức có thể được gọi trong một DEX
duy nhất đến 65.536, bao gồm các phương thức khung Android, phương thức thư
viện và phương thức bảo vệ người dùng [17]. Để hỗ trợ multidex, trong thời gian
xây dựng, công cụ xây dựng Android sẽ xây dựng một dex chính (class.dex) và các
dex phụ khác (ví dụ: class2.dex và class3.dex) khi cần và đóng gói chúng thành tệp
.apk để phân phối. Trong khi cài đặt ứng dụng, các dex thứ cấp được trích xuất vào
thư mục / data / data / PACKAGE NAME / code cache / juniordexes / và được tải
khi ứng dụng khởi động. Ví dụ: ứng dụng Runtastic [18] có chứa multidex
(class2.dex) trích xuất dex thứ cấp vào thư mục tương ứng và đổi tên thành com
.runtastic.android-1.apk. Classes2.dex. Theo đó, nếu những kẻ tấn công có thể ghi
đè lên dex thứ cấp này, chúng có thể kích hoạt tải trọng được tiêm khi ứng dụng
khởi động.
Runtime.exec (). Cũng như các ứng dụng Java (một ứng dụng không thể tạo
một thể hiện của lớp Runtime, nhưng có thể lấy một cá thể bằng cách gọi phương
thức getRuntime()), các ứng dụng Android cũng có thể lấy một thể hiện của lớp
Runtime bằng cách gọi phương thức getRuntime(). Sử dụng phương thức exec()
của lớp Runtime, các ứng dụng có thể thực thi các thực thi tùy ý trong một quy
trình riêng biệt bằng cách đơn giản cung cấp lệnh shell được chỉ định làm đối số.
Điều này hoạt động tương tự như phương pháp hệ thống Linux () và do đó, các nhà
phát triển ứng dụng Android thường sử dụng phương pháp này để thực hiện dễ
dàng. Tuy nhiên, phương thức exec() của lớp Runtime có thể được sử dụng cho
điểm kích hoạt mã để khởi chạy các cuộc tấn công remote code injection. Nếu kẻ
tấn công biết đối số được truyền cho phương thức exec() và thay thế tệp hiện có mà
đối số trỏ tới, nó có thể trở thành điểm kích hoạt mã.

Ví dụ, Umeng PushSDK [19], một trong những dịch vụ thông báo đẩy phổ
biến của Trung Quốc, thực hiện phương thức exec () để cung cấp dịch vụ thông
báo đẩy của họ thông qua lệnh shell. Đặc biệt, nó tạo ra một thể hiện của Process
bằng cách gọi Runtime.getRuntime().exec("sh") và chuyển hướng luồng dữ liệu
của nó sang các phiên bản DataInputStream / DataOutputStream để ứng dụng có
thể thực thi các lệnh bằng cách ghi vào DataOutputStream hoặc đọc từ
DataInutputStream. Khi ứng dụng khởi động, thư viện đẩy sẽ kiểm tra xem tệp
ServerDaemon có tồn tại trong thư mục tệp của ứng dụng (/ data / data / APP
PACKAGE NAME / files /) hay không, và nếu nó tồn tại, nó sẽ thực thi tệp thông
qua phương thức exec() với các đối số được chỉ định. Trong trường hợp tệp
ServerDaemon không tồn tại trong thư mục tệp, thư viện sẽ tạo tệp DaemonServer
mới và sau đó cũng thực hiện nó. Kẻ tấn công có thể lợi dụng thực tế này để xác
định điểm kích hoạt mã; nghĩa là, họ có thể thực thi mã được chèn bằng cách ghi
đè tệp đích được truyền dưới dạng tham số của phương thức exec(), chẳng hạn như
ví dụ về tệp DaemonServer.

5. Tự động phát hiện

Để phát hiện các ứng dụng có khả năng dễ bị tấn công bằng remote code
injection, chúng tôi đã phát triển một công cụ phân tích tĩnh
(https://gitlab.com/zemis0ls0l/remote code injection attacks) để tự động xác định
các đoạn mã đáp ứng ba điều kiện được mô tả trong phần 4. Trong phần này,
chúng tôi phác thảo thiết kế và triển khai công cụ phát hiện tĩnh của chúng tôi.
5.1. Tổng quan.

Hình 1 minh họa ba thành phần chính của công cụ phát hiện của chúng tôi:
bộ tiền xử lý, bộ cắt chương trình và trình kiểm tra lỗ hổng. Ở mức cao, công cụ
phát hiện tĩnh của chúng tôi lấy .apk chạy làm đầu vào và chuyển đổi nó thành
Jimple (Jimple là ngôn ngữ trung gian phổ biến dựa trên ba thành phần trên mỗi
câu lệnh trong mã thường được sử dụng để tối ưu hóa mã byte) [20], một khung
phân tích tĩnh cung cấp Jimple cho cả Java và Android (Khung Soot bao gồm
Dexpler [21] để chuyển đổi mã byte Dalvik thành Jimple) và phân tích biểu đồ
cuộc gọi. Sau đó, dựa trên việc cắt chương trình [22] với các điểm đặc biệt(nghĩa là
API) và phương pháp phỏng đoán, công cụ phát hiện sẽ phân tích mã liên quan đến
DRU để xác định các đoạn mã đáp ứng ba điều kiện. Đầu ra của công cụ bao gồm
một tập hợp thông tin có thể được sử dụng để xác định xem ứng dụng có dễ bị tấn
công bằng remote code injection hay không. Lưu ý rằng công cụ phát hiện hoạt
động trên Jimple và không yêu cầu mã nguồn của ứng dụng được phân tích.

Hình 1: Tổng quan về thiết kế của công cụ phát hiện tĩnh.

5.2. Tiền xử lý.

Cũng như các nghiên cứu phân tích tĩnh hiện đại khác cho các ứng dụng
Android (như Bartel và cộng sự [23], Geneiatakis và cộng sự [24], Woodpecker
[25], Chex [26] và Paddyfrog [27] ), trước tiên, công cụ phát hiện của chúng tôi
dịch mã byte Dalvik sang biểu diễn trung gian và sau đó xây dựng biểu đồ luồng
điều khiển liên thủ tục (ICFG) (còn được gọi là biểu đồ siêu điều khiển (sCFG))
đại diện cho tất cả các đường dẫn thực thi có thể có của ứng dụng , cho một tệp
.apk nhất định. Do độ chính xác của phân tích tĩnh phụ thuộc vào biểu đồ luồng
điều khiển, nên phải xây dựng một ICFG chính xác để cải thiện độ chính xác của
phân tích tĩnh. Tuy nhiên, không giống như các ứng dụng Java, vì các ứng dụng
Android dựa trên khung cũng như hướng sự kiện, việc tạo ra ICFG tương ứng là
một thách thức. Ví dụ: thay vì một phương thức chính, các ứng dụng Android chứa
nhiều điểm nhập được gọi theo khuôn khổ Android. Ngoài ra, khung Android cho
phép các ứng dụng đăng ký các loại cuộc gọi lại khác nhau, cũng được gọi bởi
khung này. Điều này có nghĩa là các đoạn mã có trong các phương thức gọi lại
không thể được phân tích mà không nhận ra các cạnh ẩn như vậy vì ICFG không
chính xác không có luồng điều khiển đến phương thức gọi lại.

Trong công việc này, để xây dựng các ICFG chính xác, chúng tôi tận dụng
FlowDroid [28], một khung phân tích không rõ ràng tĩnh cung cấp phân tích luồng
dữ liệu liên dòng và nhạy cảm với bối cảnh cho các ứng dụng Android. FlowDroid
mô hình vòng đời thành phần của khung Android và tái cấu trúc lại biểu đồ luồng
điều khiển khi xác định các phương thức gọi lại mới được phát hiện. Thật không
may, FlowDroid không hỗ trợ xác định các lớp liên quan đến luồng trong các ứng
dụng Android (bao gồm AsyncTask, Thread và Runnable) tạo ra các luồng điều
khiển ngầm thông qua các cuộc gọi lại. Tuy nhiên, trong Android, các tác vụ tải
xuống tài nguyên thường được triển khai bằng cách sử dụng các lớp luồng vì các
hoạt động mạng không thể chạy trên luồng chính (nhà phát triển có thể sử dụng
Thread, AsyncTask cho các tác vụ chạy ngắn và dịch vụ cho các tác vụ chạy dài để
thực hiện các hoạt động mạng). Do đó, việc xác định các cạnh liên quan đến luồng
là cần thiết cho công cụ phát hiện của chúng tôi. Để phân tích chính xác các ứng
dụng, chúng tôi thêm các tiện ích mở rộng để hỗ trợ các lớp phân luồng như vậy.
Ví dụ: để hỗ trợ lớp AsyncTask, chúng tôi xác định tất cả các phiên bản
AsyncTask và tăng biểu đồ cuộc gọi bằng cách thêm các cạnh kết nối với phiên
bản AsyncTask. Điều này có thể được thực hiện bằng cách thay thế lời gọi của
exec() bằng các lệnh gọi tới onPreExecute(), doInBackground() và
onPostExecute(). Cuối cùng, chúng tôi xây dựng lại ICFG bằng cách kết hợp xây
dựng CFG gia tăng FlowDroid với các phần mở rộng của chúng tôi. ICFG được
xây dựng lại được sử dụng cho bước cắt chương trình hai chiều tiếp theo.

5.3. Chương trình cắt.

Để trích xuất các lát Jimple, chúng tôi thực hiện thuật toán cắt tiến và lùi
(xem phụ lục A), dựa trên phương pháp cắt chương trình nhận thức mạng do Choi
và cộng sự đề xuất. [29, 30]. Thuật toán cắt hoạt động hai chiều dựa trên ICFG
được xây dựng ở bước trước. Thuật toán bắt đầu tại các điểm thú vị được xác định
trước (mạng API I/O và các tham số của nó), chẳng hạn như
java.net.URL.openConnection() và org.apache .http.client.HttpClient.execute()
bằng cách thêm các biến của các điểm này đến một danh sách công việc. Sau đó,
nó tiến lên và lùi lại trên ICFG trong khi phân tích sự phụ thuộc dữ liệu giữa các
biến trong danh sách công việc và biến hiện tại trong các câu lệnh Jimple. Để phân
tích tiến / lùi liên văn bản, thuật toán của chúng tôi sẽ giữ một ngăn xếp cuộc gọi
ghi lại phương thức hiện tại (tức là người gọi) và vị trí của nó. Theo cách này, bộ
cắt chương trình cung cấp phân tích luồng dữ liệu theo ngữ cảnh. Trình cắt chương
trình tiếp tục phân tích đệ quy theo cách này. Phân tích kết thúc khi không có mục
nào trong danh sách công việc, khi nó đạt đến điểm vào của ứng dụng (trong
trường hợp cắt ngược) hoặc khi gặp API chìm (trong trường hợp cắt tiến) như
FileOutputStream.write( ).

Ví dụ, trong liệt kê 2, trình cắt chương trình bắt đầu tại
java.net.URL.openConnection() và đi về phía trước và lùi lại trong khi phân tích sự
phụ thuộc dữ liệu. Việc cắt lát ngược chấm dứt tại dòng (3) trong liệt kê 2 và lát cắt
chuyển tiếp chấm dứt ở dòng (18) trong liệt kê 3. Lưu ý rằng, để dễ đọc, chúng tôi
đã sử dụng mã Java thay vì Jimple IR và chỉ liệt kê các kết quả của việc cắt chương
trình trong đoạn mã.

Khi bộ cắt chương trình đã trích xuất các lát, bộ phân tích phụ thuộc xen kẽ
xác định các phụ thuộc giữa các lát được trích xuất. Mục tiêu của phân tích này là
xác định bất kỳ sự phụ thuộc nào giữa phản hồi HTTP và yêu cầu HTTP. Hình 2
cho thấy một ví dụ về cách phân tích phụ thuộc xen kẽ hoạt động theo các lát cắt
request (requestA và requestB) và phản hồi (answerA và answerB). Trong hình,
một ứng dụng nhận siêu dữ liệu (dòng (5) trong requestA) và sau đó phân tích cú
pháp (dòng (2) trong answerA) để lấy URL tải xuống tài nguyên. Sau đó, bằng
cách sử dụng URL thu được, ứng dụng sẽ tải xuống và lưu trữ tài nguyên (dòng (2)
trong requestB và dòng (3) trong answerB ). Trong trường hợp này, một sự phụ
thuộc tồn tại giữa answerA và requestB. Để xác định điều này, chúng tôi tận dụng
cách tiếp cận không rõ ràng được đề xuất bởi Choi và cộng sự [29, 30], trong đó sự
phụ thuộc được xác định bằng cách xác định luồng dữ liệu từ nguồn (dòng (1)
trong responseA) đến phần chìm (dòng (1) trong requestB).
Hình 2: Xây dựng URL, phân tích chuỗi và phân tích phụ thuộc xen kẽ.

Cuối cùng, chương trình cắt ghi lại các lát Jimple bao gồm yêu cầu / phản
hồi HTTP và các phụ thuộc của nó cho bước tiếp theo, trong đó các đoạn mã đáp
ứng ba điều kiện về lỗ hổng cho các cuộc tấn công remote code injection được xác
định.

5.4. Kiểm tra lỗ hổng.

Sau khi chương trình cắt trích xuất tất cả các lát cắt hoạt động mạng, cũng
như các phụ thuộc của chúng (yêu cầu và phản hồi HTTP), trình kiểm tra lỗ hổng
xác định các đoạn mã đáp ứng ba điều kiện cho lỗ hổng tấn công remote code
injection. Trình kiểm tra lỗ hổng đạt được điều này bằng cách thực hiện các
phương pháp phỏng đoán sau. Lưu ý rằng trình kiểm tra lỗ hổng sử dụng phân tích
không rõ ràng FlowDroid cung cấp phân tích luồng dữ liệu liên dòng và nhạy cảm
theo ngữ cảnh và liên văn bản.
(1) Xác định các kiểm tra xác thực không hoặc có thể bỏ qua. Để xác định
các trường hợp không có kiểm tra xác thực, chúng tôi tìm thấy lớp phân loại thông
báo được sử dụng, chẳng hạn như java.security.MessageDigest, từ các lát phản hồi
đã cho. Nếu không có việc sử dụng các phương thức phân loại thông báo như
update() hoặc digest(), chúng tôi xem xét rằng không có kiểm tra xác thực tồn tại.
Tuy nhiên, mặc dù ứng dụng xác thực tài nguyên bằng cách sử dụng giá trị băm
được cung cấp, nếu giá trị băm được truyền qua HTTP, kiểm tra xác thực có thể
được bỏ qua như được mô tả trong phần 4. Do đó, để xác định kiểm tra xác thực có
thể bỏ qua, chúng tôi sử dụng trình tạo URL tạo ra một URL cung cấp các mạng
API I / O được cung cấp các lát yêu cầu HTTP được tạo ra thông qua việc cắt
ngược. Trình tạo URL mô hình các API Java và Android cấp cao như append() và
toString(), được sử dụng cho các thao tác chuỗi (chúng tôi sẽ mô tả thêm về trình
tạo URL bên dưới). Nếu URL được tạo là HTTP, chúng tôi coi việc kiểm tra xác
thực bị bỏ qua ngay cả khi các chức năng phân loại thông báo có mặt trong các lát.

(2) Phát hiện lỗ hổng ghi đè tập tin. Đưa ra các lát phản hồi HTTP được tạo
ra bằng cách chuyển tiếp, để xác định trích xuất ZIP không an toàn, trước tiên
chúng tôi tìm thấy một phiên bản của java.util.zip.ZipInputStream và các lớp tệp
như java.io.File. Sau đó chúng tôi kiểm tra xem mã có xác nhận tên của từng mục
trước khi giải nén nó không. Để đạt được điều này, bộ phân tích chuỗi chỉ định
ngẫu nhiên một chuỗi ban đầu chứa thông tin truyền tải đường dẫn (ví dụ:“
../../../../Target”) làm giá trị của java.util.zip.ZipEntry.getName() và sau đó trình
phân tích chuỗi theo dõi các lát trong khi cập nhật các thao tác của nó (dựa trên các
mô hình API) cho đến khi gặp phương thức tệp. Khi chuỗi ban đầu được truyền
cho tham số trong phương thức tệp, nếu thông tin truyền tải đường dẫn của chuỗi
ban đầu không thay đổi (hoặc được lọc ra), chúng tôi coi đó là tệp ghi đè lên lỗ
hổng; đó là một trích xuất ZIP không an toàn.

Tương tự, để xác định việc triển khai ContentDisposeition không an toàn,
trước tiên, chúng tôi tìm thấy một lời gọi phương thức
(org.apache.http.HttpResponse .getFirstHeader() hoặc
java.net.HttpURLCconnectection .getHeaderField()) và các phương thức ghi tệp,
rồi kiểm tra xem mã có phân tích chính xác tên tệp từ trường Xử lý nội dung hay
không. Một trong hai phương pháp có thể được sử dụng để phân tích tên tệp từ
trường Xử lý nội dung: API thao tác chuỗi hoặc khớp biểu thức chính quy. Phương
thức đầu tiên thường tìm thấy một chuỗi nhất định bằng indexOf() và phân tách
chuỗi bằng subString(). Do đó, cách tiếp cận tương tự được sử dụng để tìm các
trích xuất ZIP không an toàn có thể được sử dụng để mô hình hóa các API thao tác
chuỗi này bằng cách sử dụng bộ phân tích chuỗi. Phương thức thứ hai phân tích tên
tệp bằng cách khớp một biểu thức chính quy. Để tạo điều kiện cho phương thức
này, chúng tôi trích xuất một chuỗi không đổi được truyền đến tham số trong
java.util.regex.Potype.compile() và sau đó đánh giá chuỗi mẫu này bằng chuỗi thử
nghiệm của chúng tôi (“./../../ .. /../../target.so”). Phù hợp hơn với biểu thức chính
quy, nếu kết quả giống với chuỗi thử nghiệm ban đầu của chúng tôi, chúng tôi coi
đó là một lỗ hổng ghi đè lên.

(3) Xác định điểm kích hoạt. Để xác định các điểm kích hoạt, chúng tôi sử
dụng ba thuộc tính khác nhau của ứng dụng Android. Xác định multidex là đơn
giản. Các ứng dụng Android chứa các tệp dex (.dex) trong thư mục gốc bên trong
tệp .apk, là định dạng lưu trữ ZIP. Do đó, chúng ta có thể dễ dàng xác định
multidex bằng cách giải nén tệp .apk và sau đó kiểm tra xem các tệp dex thứ cấp
(chẳng hạn như class2.dex) có tồn tại hay không. Không giống như multidex, xác
định thư viện thời gian chạy và Runtime.exec() cần phân tích chuỗi. Trình phân
tích chuỗi bắt đầu bằng cách phát hiện các phương thức
dalvik.system.DexClassLoader(), java.lang.System.loadLibrary() và
java.lang.Runtime.exec (). Nếu tìm thấy các yêu cầu phương thức, bộ phân tích
chuỗi thực hiện phân tích ngược về giá trị tham số của phương thức để xây dựng
một chuỗi không đổi. Khi chuỗi không đổi được tạo, bộ phân tích chuỗi sẽ kiểm tra
nó bằng cách so sánh nó với các tệp thực thi đã biết. Trong trường hợp thư viện
thời gian chạy, chúng tôi so sánh chuỗi hằng với tên của các tệp thực thi, được
trích xuất trong thư mục / nội dung bên trong tệp .apk. Nếu có chúng khác nhau,
chúng tôi xem xét nó có chứa một điểm kích hoạt. Trong trường hợp
Runtime.exec(),chúng tôi lọc ra các trường hợp trong đó chuỗi hằng được tạo có
chứa một trong các tệp thực thi nằm trong “/bin” và “/sbin”. Sau khi lọc, nếu có bất
kỳ chuỗi hằng số còn lại, chúng tôi coi đó là điểm kích hoạt. Theo cách này, chúng
ta có thể xác định các điểm kích hoạt có thể.

(4) Phân biệt giao thức truyền thông có an toàn hay không. Mặc dù các ứng
dụng có thể đáp ứng ba điều kiện được xác định cho các cuộc tấn công remote
code injection thành công, nhưng nếu các ứng dụng sử dụng giao thức HTTPS,
chúng có thể không dễ bị tấn công remote code injection. Do đó, chúng tôi phân
tích thêm các ứng dụng để xác định xem chúng có sử dụng HTTPS hay không. Để
kết thúc việc này, chúng tôi đã triển khai mô-đun trình tạo URL, tạo URL bằng
cách quay lại từ trình khởi tạo URL chẳng hạn như java.net.URL.URL() hoặc
phương thức org.apache.http.client.methods.HttpGet(). Trong quá trình phân tích
ngược, trình xây dựng URL mô hình các API thao tác chuỗi như java
.lang.StringBuilder.append trong đó các chuỗi không đổi được thêm vào để xây
dựng một URL đầy đủ. Ngoài ra, trình tạo URL xử lý các tham chiếu đến các đối
tượng tài nguyên, chẳng hạn như Android.R, có giá trị được lưu trữ dưới dạng tệp
do người dùng xác định trong .apk (ví dụ: res/value/string.xml). Khi tạo URL đầy
đủ, trình tạo URL phân biệt giữa một URL tĩnh, được mã hóa cứng trong mã và
một URL động, xuất phát từ các đầu vào mạng khác. Điều này đạt được bằng cách
xác định các kết quả phân tích phụ thuộc xen kẽ (sử dụng bộ phân tích phụ thuộc
xen kẽ trong phần 4). Trong trường hợp URL tĩnh, nếu URL bắt đầu bằng “HTTP:
//”, thì chúng tôi cho rằng nó dễ bị tấn công remote code injection. Tuy nhiên,
trong trường hợp URL động, vì chúng tôi không thể xác định các URL được tạo
động, do giới hạn của phân tích tĩnh, chúng tôi cho rằng nó có khả năng bị tổn
thương.

Mặt khác, có những trường hợp HTTPS không được triển khai đúng cách, có
nghĩa là những kẻ tấn công khai thác HTTPS được thực hiện sai để thực hiện các
cuộc tấn công MITM. Để giải quyết các trường hợp như vậy, sử dụng Mallodroid
của Fahl và cộng sự. [9], chúng tôi xác định HTTPS được thực hiện sai, chẳng hạn
như tin tưởng tất cả các chứng nhận hoặc cho phép tất cả tên máy chủ lưu trữ. Nếu
HTTPS được thực hiện sai được tìm thấy, chúng tôi cũng xem xét nó dễ bị tấn
công bằng remote code injection.

You might also like