Hmm…!!! Thực sự mà nói thì lâu rồi mình cũng không viết lách gì cả, hôm nay hạ quyết tâm lắm mới ngồi vuốt bàn phím được và có lẽ đây là lần đầu mình viết bài trên blog của công ty. Hồi còn là sinh viên mình cũng rất đam mê viết này viết kia, cứ khi nào tạch môn hoặc bị điểm D thì y như rằng mình lại có cảm hứng để viết. Giờ có khác chút là cứ hễ bị N/A hoặc duplicate là mình cũng lại viết…Cuộc sống mà!

Gần đây mình có được giao tasks làm pentest ứng dụng cho 2 công ty (mình sẽ không nêu tên ra ở đây) nên tạm gọi với cái tên thân mật là X và Y. Trong quá trình kiểm thử mình phát hiện ra bug dẫn đến Account Takeover (ATO), bug mình tìm thì cũng đơn giản thôi không có gì là cao siêu cả. Nhưng cái quan trọng hơn là mình muốn chia sẻ lại những thứ mà mình đã làm “Sharing is Caring”.

Vậy ATO là gì ? ATO là tên gọi chung cho những bug mà có thể dẫn đến chiếm tài khoản của người dùng khác, có thể hiểu đơn giản vậy thôi. Để tiện cho việc theo dõi mình sẽ chia làm hai phần, phần 1 sẽ về công ty X và phần 2 là công ty Y.

1. Set new-password without matching Code

Nói qua về website của X một chút, thì đây là một sàn giao dịch tiền ảo hay còn gọi với cái tên rất “ngành” Cryto-cu-den-xi Exchange và X có trụ sở chính ở Malta. Bản thân mình cũng đọc khá nhiều writeup cũng như blog viết về ATO và thường thấy tính năng forgot-password hay dẫn đến lỗi này. Cũng không ngoại lệ thì mình cũng test tính năng forgot-password trên website này, thông thường forgot-password chúng ta thấy sẽ có hai cách phổ biến đó là gửi reset-link hoặc gửi code về địa chỉ email. Ứng dụng của X sử dụng cách thứ 2 đó là gửi mã code, mình sẽ mô tả lại flow của ứng dụng:

Khi click vào liên kết forgot-password, sau đó nhập vào địa chỉ email-> server sẽ trả lại response như hình bên dưới.

Tiếp sau đó chúng ta sẽ được redirect đến địa chỉ có trong giá trị của tham số url, địa chỉ này có kèm theo một đoạn hash rất chi là dài và khó hiểu, theo mình đoán nó sẽ mapping đến địa chỉ email. Tiếp theo chúng ta sẽ nhìn thấy một pop-up thông báo rằng Code để thiết lập lại password đã được gửi đến email và bạn phải nhập Code này thì mới thiết lập lại password được.

Giá trị Code được gửi về mail gồm 5 kí tự (chỉ có kí tự số), như vậy sẽ phải tấn công bạo lực tối đa 100.000 giá trị (brute-force), đen một lỗi ở đây là website sử dụng google captcha với lại Code này chỉ tồn tại trong một khoảng thời gian, như vậy brute-force sẽ không khả thi. Và đến đây mình cũng không có idea gì để test cả :(((, và cứ thế thời gian trôi đi khoảng gần một tuần sau khi đang ngồi xem Seven Deadly Sins đến đoạn Meliodas bán hành thập giới, mình chợt có idea để test, mình tạo 2 accounts để test tạm gọi là test1@gmail.com và test2@gmail.com, mỗi một account mình dùng trên trình duyệt khác nhau. Ban đầu mình thực hiện Forgot-password cho cả 2 email này, Code được gửi về cho cả 2, thay vì sử dụng Code đã được gửi về cho test1@gmail.com thì mình lại sử dụng Code đã được gửi về cho test2@gmail.com để thiết lập password cho test1@gmail.com…và Boomm !!! Thật may mắn mình đã thay đổi được password cho test1@gmail.com , vì đôi khi chúng ta cũng không thể biết được phía backend nó xử lý ra sao cho nên cứ phải test mọi trường hợp có thể xảy ra. Từ một idea đơn giản dẫn đến high impact :))) lỗi ngay sau đó được gửi để đội dev tiến hành fix. Sau khi bug được fix, mình có nhận được thông tin từ bên họ là do mấy anh dev đã vô tình comment dòng so sánh Code với địa chỉ email, đúng là mấy anh dev deeptry chưa bao giờ khiến chúng ta hết bất ngờ lolzz :))

2. IDOR leads to ATO

Về IDOR chắc mình cũng sẽ không giải thích ở đây, vì lỗi này cũng khá quen thuộc và thường gặp rồi. Lại nói qua về Y, Y là một công ty chuyên cung cấp các giải pháp và ứng dụng chỉ dành cho doanh nghiệp như quản lý công việc, hội họp…vv Phải nói là mình cũng khá ấn tượng với sản phẩm của họ, khá nhiều tính năng cũng như là giao diện đẹp như facebook :v

Bug lần này mình test của Y là trên android-app, ngoài những lỗi đặc thù trên mobile (cái này mình hay test theo checklist) mình hay focus chính vào những api phía backend nhiều hơn, và thường ưu tiên test IDOR trước vì nó rất hay gặp trên mobile-app. Cũng rất là tâm linh thôi, app lần này mình cũng tìm được IDOR, nghe có vẻ đơn giản nhỉ ? Vì thực chất nó đơn giản mà :v

Từ IDOR dẫn đến 2 impact chính đó là: đọc được nội dung trao đổi công việc của những công ty là khách hàng của Y và ATO. Ở đây mình chỉ xin chia sẻ về ATO cho nó đúng chủ đề 😛

Chắc không dài dòng nữa, mình nói qua về cách hoạt động của ứng dụng mobile này, ứng dụng cũng khá là đơn giản bao gồm nhưng tính năng chính như: trao đổi tin nhắn, danh sách bạn bè, thông báo, danh sách liên kết đến các ứng dụng khác. Ban đầu khi người dùng đăng nhập, phía server sẽ tiến hành xác thực và trả lại cho chúng ta một access_token và mọi request sau đó được gửi lên server sẽ đi kèm với access_token này, đại khái sẽ là như vậy. Vậy ATO xảy ra ở đâu, mình sẽ đi vào chi tiết sau đây, như đã nói ứng dụng này có một tính năng liên kết đến ứng dụng khác. Ví dụ: danh sách liên kết có những ứng dụng như quản lý công việc, hội họp và từ mobile-app muốn sử dụng những app này thì chỉ việc lựa chọn là xong và có một điều cần đề cập ở đây rằng những app này thực chất lại là webapp (hiển thị qua webview trong andorid). Vì Y có cả trên iso và android, do có sẵn con iporn trong tay mình test luôn vì ngại bật Genymotion (may quá không có SSL Pinning hahaa), sau khi chọn chuyển qua ứng dụng khác request sẽ có dạng như sau:

Giá trị của trường host chính là ứng dụng muốn chuyển đến để sử dụng.
Cấu trúc của access_token:

access_token=user_id.system_id.hash(something).hash(something).

user_id: id của mỗi user trên toàn hệ thống của Y.

system_id: là id ứng với công ty khách hàng của Y, tức là mọi nhân viên của công ty A đều có chung một system_id.

client_key: sau khi fix thì họ mới thêm vào, chứ ban đầu không có @@ (do mình quên ko lưu request lúc đó lại).

Đến đây mình cứ nghĩ là ngon ăn rồi, bởi phía server chỉ kiểm tra xem system_id đã có trên hệ thông hay chưa mà thôi và bruteforce user_id là xong nhưng cuộc sống mà. Nhưng cuối cùng nó vẫn bắt đăng nhập để vào (bạn hình dung nó như là sân bay quốc tế vậy, muốn sang bên Nhật đóng phim thì vẫn phải trình giấy tờ khi sang bên bển ), chắc có lẽ phía server đã thực hiện check đống hash đối với với user_id :sadly

Theo kinh nghiệm hơn 6.9 tháng làm pentest của mình nếu công ty nào có cả web-app, ios-app và android-app thì mình luôn luôn test tất cả để so sánh xem có sự khác biết gì không, và lần này theo như các bạn trẻ hay chơi game gọi là “ăn rùa” thì phải haha 😛

Xem sét request gửi lên tương tự như ios nhưng trên android-app:

Có một sự khác biệt ở đây là request được gửi lên có kèm theo tham số __code=native. Ban đầu mình nghĩ chắc nó cũng như trong ios thôi. Nhưng mà ngoại cảm thế nào mình lại thử test IDOR xem thế nào, và điều gì đến cũng đến ^_^

Chắc là mình cũng viết đến đây thôi với cả lần đầu viết có chỗ nào chưa hợp lý cũng rất mong nhận được những đóng góp vì mình không giỏi viết về kỹ thuật, thế mạnh của mình thiên viết về tình cảm ướt át thôi. Hẹn gặp ở những blog tiếp theo.

No Comments
Post a Comment