Write-up:VulnHub Flick 2
Bài đăng này đã không được cập nhật trong 3 năm
Mở đầu
Sau khi làm xong bài SecureCode1 (write-up), mình được giới thiệu một tựa game siêu phẩm mo bi lé là Flick2, lần này chúng ta được cho một file apk và mục tiêu của chúng ta là đi tìm lỗi trong app client từ đó có thể tấn công vào server. Ngôn ngữ được sử dụng ở đây là java, ngôn ngữ mình không thích cho lắm nhưng biết sao giờ . Let's GO
Write-up
Sau khi tải file từ Vulnhub ta sẽ có 2 file chính cần để ý là file flick-check-dist.apk và file flickII-dist.ova. Như mình đã nói ở trên đây là bài review source code nên mình sẽ tập trung vào file apk trước.
Source code
Việc đầu tiên ta cần làm đó là tìm cách decompile từ file apk thành các file source code. Ta có thể dễ dàng decompile các file apk thông qua cả web và phần mềm, trong bài này mình sẽ dùng phần mềm jadx bạn chỉ việc tải file exe nếu bạn đã cài jre còn không bạn có thể chọn tả file zip có chứa kèm jre
Sau khi tải phần mềm bạn chỉ việc chọn đường dẫn đến thư mục của file apk là xong các việc còn lại phần mềm sẽ làm hết. Đợi một lúc để phần mềm chạy xong ta sẽ được các file như sau
Sau khi decompile ta có khá là nhiều file làm ta hoang mang nhưng ta có thể bỏ qua các thư mục khác vả chỉ tập vào thư mục com. Tuy nhiên trong thư mục com không phải tất cả các file đều cần quan tâm ví dụ như jcraft.jsh mình có search thử thì biết đây là thư viện hỗ trỡ giống như android.support nên mình bỏ qua luôn.
Giờ mình đã giảm được khá nhiều các file nên bây giờ mình sẽ cố gắng hiểu các hành vi của từng fuction trong chương trình. Sau một lúc đọc tất cả các file mình tiếp tục rút gọn được các class cần tập trung là DoRegisterActivity, CommandActivity và R
Giờ mình cùng tìm hiểu xem các class làm gì
DoRegisterActivity
Về cơ bản thì đầu tiên chương trình sẽ lấy android_id và gửi thông tin này với POST request có dữ liệu dưới dạng json để đăng kí mới
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
JSONObject uuid = new JSONObject();
uuid.put("uuid", deviceId);
Nếu đăng kí thành công ta sẽ nhận được một mã token
if (responseJson.getString("registered").equals("ok")) {
return responseJson.getString("token");
}
Từ những thông tin trên mình đã viết một hàm bằng Go để lấy token Giờ ta đã có được token nhưng ta phải làm gì với nó? Để trả lời câu hỏi này ta phải tiếp tục đến với hàm CommandActivity
CommandActivity
Ngay ở đầu ta có một chuỗi integrity_check nhưng chưa biết phải làm gì với nó nên mình tạm bỏ qua
String integrity_check = "YFhaRBMNFRQDFxJEFlFDExIDVUMGEhcLAUNFBVdWQGFeXBIVWEsZWQ==";
Sau khi đọc toàn bộ class thì mình biết được chương trình sẽ gửi một GET request đến chương trình. Trong request đó sẽ chứa X-UUID và X-Token header tương ứng là UUID của ta và Token mà ta sau khi đăng kí nhận được, cuối cùng là một lệnh bất kì mà ta truyền vào được encode base64
String base64_command = Base64.encodeToString(view.getTag().toString().getBytes(), 0);
new CallAPI().execute("https://" + api_server + "/do/cmd/" + base64_command, deviceId, api_auth_token);
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setRequestProperty("X-UUID", deviceId);
urlConnection.setRequestProperty("X-Token", api_auth_token);
Sau tất cả các thông tin mình có mình đoán đây là một lỗi liên quan đến Command Injection. Xác nhận là thực thi được command nên mình sẽ cố gắng lấy reverse shell. Mình có code một hàm để lấy reverse shell Giờ ta đã có được shell đầu
Privilege Escalation
Khác với bài securecode1, bài này chúng ta có thể leo thang đặc quyền lên root
Robin
Các bạn có nhớ chuỗi integrity_check không? Giờ đã đến lúc dùng đến nó. Trong hàm CommandActivity ta đã bỏ qua hai hàm quan trọng
Về cơ bản thì hàm validate trả lại một chuỗi passoword và hàm còn lại sử dụng kết quả đó để kết nối ssh với username là robin. Việc cần làm bây giờ là tìm được chuỗi password. Mình cũng đã code một hàm để lấy được password
Giờ ta đã có được mật khẩu của robin kết hợp với việc ta đang có reverse shell của nginx nên dễ dàng có được shell của robin
Bryan
Kiểm tra với sudo -l
Để ý ở đây ta thấy có option env_keep+=LD_PRELOAD nên ta dễ dàng có được shell của bryan (chi tiết các làm ở bài này).
Điểm thú vị ở đây là ta phải tìm được đường dẫn đến cc1
Sử dụng lệnh find / 2>/dev/null -name cc1
Sau khi tìm được đường dẫn tiến hành export vào biến PATH
Và ta làm tương tự như link ở trên, ta có shell của bryan
Sean
Tiếp tục recon với lệnh find / 2>/dev/null -perm -u=s -exec ls -la {} +
Dùng lệnh strings để kiểm tra strings /usr/local/bin/backup
Kết quả làm mình khá là ngạc nhiên vì nó cho ra khá rõ ràng các lệnh được sử dụng và điều mình để ý ở đây là lệnh tar đi với dấu * ( hay còn gọi là wildcard). Mình cũng đã trình bày cách leo thang thông qua cách này ở đây
Ta tiếp tục có được shell của sean
Root
Để ý lệnh find ở trên ta còn có một file khác có SUID và owner là root
-rwsr-x--- 1 root sean 866169 Aug 15 2015 /usr/local/bin/restore
Mình chạy thử xem file làm gì nhưng lại báo lỗi không có quyền mặc dù mình đang là sean
Mình vẫn chưa hiểu tại sao lệnh id thông báo mình đang thuộc group sean mà lại không đọc được file cộng với mình biết bài này cần phải khai thác buffer overflow mà mình chưa biết gì về bof nên mình sẽ tạm dừng bài ở đây, khi nào đã nắm vững được cách khai thác mình sẽ quay lại làm tiếp
Conclusion
Qua bài này mình cần tìm hiểu thêm về bof cũng như phải tìm hiểu thêm vì sao trong trường hợp này thuộc group sean mà lại không có quyền chạy. Nếu có bạn nào biết câu trả lời mong các bạn comment giải đáp giúp mình
Link code khai thác ở đây
All rights reserved