Phân tích ứng dụng Btalk trên Android – Phần một: Cơ chế xác thực người dùng

May 6, 2014 by pdah · 22 Comments 

Lưu ý: các phân tích trong bài viết này được dựa trên phiên bản Btalk 1.0.6 tải về từ PlayStore. Các vấn đề được nêu trong bài viết này BKAV đã được gửi email thông báo từ trước.

(pdah – cb_ – k9)

Cơ chế đăng ký và kích hoạt

Quá trình xác thực trên điện thoại của Btalk  gồm 3 bước chính:

  1. Đăng ký tài khoản với Btalk:
    • Người dùng gửi thông tin về số điện thoại đang sử dụng cho máy chủ Btalk.
    • Btalk gửi tin nhắn kèm mã số xác thực đến số điện thoại người dùng.
  2. Xác nhận (kích hoạt) tài khoản:
    • Mã số xác thực được nhập và gửi lại Btalk
    • Btalk xác nhận đúng mã xác thực và gửi lại mật khẩu khởi tạo riêng cho mỗi phiên đăng ký.
  3. Đăng ký với hệ thống nhắn tin OpenSIPS
    • Mật khẩu kèm thông tin số điện thoại được gửi lại hệ thống OpenSIPS của Btalk
    • Btalk xác nhận đã nhận được thông tin

Bước 1 – Đăng ký tài khoản với Btalk:

Sau khi người dùng nhập số điện thoại, một HTTP GET Request được gửi từ ứng dụng Btalk đến API https://bmail.vn/service/preauth với các tham số sau:

domain       = bmail.vn
from         = bphone
reqType      = bphoneRegister
txtDomain    = bmail.vn
useServerSms = true
txtUser      = <số điện thoại kèm mã quốc gia>@bmail.vn
timestamp    = <timestamp>
preauth      = <hash>

Tham số preauth được sử dụng để “ký” các thông tin được thiết bị gửi đến máy chủ Btalk. Mục đích chính là để xác nhận thông tin được gửi từ một nguồn hợp lệ. Điều này được thể hiện qua việc API gửi về isTrustedDomain=false nếu chúng ta gửi giá trị ngẫu nhiên cho preauth.

Giá trị của preauth được xác định như sau:

preauth = HMAC_SHA1(key, domain + ’|’ + timestamp + ‘|’ + txtUser)

Nếu thông tin được ký đúng, API trả về một HTTP Response rỗng đồng thời hệ thống gửi một tin nhắn chứa mã số xác thực (gồm 4 ký số) đến số di động của người dùng. Nội dung của tin nhắn có dạng:

Your Btalk code is XXXX.

Bước 2 – Xác nhận tài khoản

Sau khi có mã số xác thực, ứng dụng Btalk tiếp tục gửi một HTTP GET Request đến https://bmail.vn/service/preauth với danh sách các tham số:

txtDomain   = bmail.vn
from        = bphone
reqType     = bphoneRegister
op          = verifyCode
txtDomain   = bmail.vn
txtUser     = <số điện thoại kèm mã quốc gia>@bmail.vn
timestamp   = <timestamp>
verifyCode  = <code>
preauth     = <hash>

Với preauth được xác định bằng:

preauth = HMAC_SHA1(key, timestamp + ’|’ + txtUser + ‘|’ + verifyCode)

Nếu Btalk gửi đúng mã xác nhận, API sẽ gửi về mật khẩu (gồm 8 ký tự). Trên lý thuyết, với số điện thoại và mật khẩu này, chúng ta có thể gửi và nhận tin nhắn thông qua máy chủ của Btalk. Tuy nhiên chúng ta không thể làm điều đó nếu chưa thực hiện bước tiếp theo.

Bước 3 – Đăng ký với hệ thống nhắn tin OpenSIPS

Ứng dụng Btalk gửi một HTTP POST Request đến dịch vụ OpenSIPS tại https://btalk.bkav.com:8443/OpenSipsServices/rest/sip/register

Với tham số:

username  = <số điện thoại kèm mã quốc gia>
password  = <mật khẩu>
timestamp = <timestamp>
preauth   = <hash>

Trong đó

preauth = HMAC_SHA1(key, timestamp + ’|’ + password + ‘|’ + username + ‘@bmail.vn’)

Sau bước này ứng dụng Btalk đã có thể đăng nhập vào hệ thống XMPP của Btalk đồng thời gửi, nhận tin nhắn.

Các vấn đề

Lộ key (khóa) của hàm băm mã hóa

Như chúng tôi mô tả ở trên, Btalk sử dụng HMAC-SHA1 để ký các HTTP requests gửi đi từ ứng dụng trên điện thoại. Về cơ bản HMAC-SHA1 giúp người sử dụng kiểm tra tính đồng nhất của dữ liệu, đồng thời chứng thực phía gửi dữ liệu thông qua tính bí mật của khóa key. Tuy nhiên giá trị của key được nhúng trong ứng dụng Btalk và chúng ta có thể tìm thấy nó dễ dàng:

Configuration.REGISTER_KEY = "41ab3e484f918ff0d378058e50eb0f79e93d19383ca1053830a878a83bcce3fc";

Điều này dẫn đến việc bất kỳ ai cũng có thể giả mạo ứng dụng Btalk để gửi HTTP requests đến máy chủ.

Spam tin nhắn xác thực đến số di động khác

Một hệ quả của vấn đề trên là chúng ta có thể spam số máy di động khác bằng cách liên tục giả lập bước một của cơ chế xác thực.

Lấy cắp thông tin đăng nhập thông qua vét cạn mã xác thực

Ở bước một và hai, mã xác thực chỉ có 4 ký số và không bị vô hiệu trong khoản thời gian nhất định, chúng ta có thể liên tục lặp lại bước hai với tối đa 10.000 khả năng khác nhau của mã xác thực cho đến khi nào nhận được mật khẩu.

Thời gian ước tính để thử chọn hết tất cả các khả năng (10.000 trường hợp) là khoảng 1 giờ đồng hồ. Giả sử nhà phát triển lựa chọn phương án vô hiệu hóa mã xác thực trong 5 phút, chúng ta sẽ có cơ hội thử chọn khoảng 830 trường hợp, đồng nghĩa với khoảng 8.3% cơ hội thành công. Đây vẫn là một con số không nhỏ.

SSL vẫn không an toàn

Mặc dù Btalk sử dụng SSL cho tất cả các bước xác thực người dùng, nhưng nhà phát triển cho phép ứng dụng chấp nhận tất cả các certificate mà nó nhận được bằng cách:

  • Định nghĩa lại lớp BkavSSLSocketFactory thay cho lớp SSLSocketFactory mặc định và bỏ hết tất cả các bước chứng thực certificate.
  • Bỏ qua việc kiểm tra hostname của certificate:
      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
      keyStore.load(null, null);
      BkavSSLSocketFactory socketFactory = new BkavSSLSocketFactory(keyStore);
      (()SSLSocketFactory)socketFactory).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    

Điều này cho phép hacker có thể thực hiện tấn công MITM và “nhìn lén” tất cả dữ liệu của người dùng.

Một vài điều thú vị khác

Giả lập gửi và nhận tin nhắn từ sau khi có được mật khẩu

Trên điện thoại (đã root) hoặc emulator:

Sau khi cài Btalk, điều chỉnh thông tin đăng nhập của ứng dụng tại /data/data/bkav.android.btalk/shared_prefs/bkav.android.btalk_preferences.xml với số điện thoại và mật khẩu lấy được.

...

<string name="bkav_pref_sipx_password">YYYYYYYY</string>
<string name="bkav_pref_sipx_username">84XXXXXXXXXXX</string>

...

Thông qua viết mã

Đoạn mã đơn giản sau giả lập việc gửi và nhận tin nhắn qua Btalk:

import xmpp
import time

username = '84xxxxxxxx'
passwd   = 'yyyyyyy'
to       = '84zzzzzzzzz@bmail.vn'
msg      = 'Hello from a script'

def message_callback(client, stanza):
    sender       = stanza.getFrom()
    message_type = stanza.getType()
    message      = stanza.getBody()

print "Received '%s' from '%s'" % (message, sender)

client = xmpp.Client('bmail.vn', debug=[])
client.connect(server=('chat.bkav.com',5222))
client.auth(username, passwd, 'bmail.vn')
client.RegisterHandler("message", message_callback)

client.sendInitPresence()
message = xmpp.Message(to, msg)
message.setAttr('type', 'chat')
print "Sending message ..."
client.send(message)

print "Waiting for message ..."
while client.isConnected():
    client.send(xmpp.Presence())
    client.Process()
    time.sleep(1)

Cái gì đây ?

Chúng tôi phát hiện một vài đoạn mã thú vị trong ứng dụng Btalk:

Cho dù BKAV đã thay đổi tên đăng nhập và/hoặc mật khẩu của dịch vụ liên quan ở phía máy chủ, việc để lọt những dòng mã như thế này lên Play Store cho thấy nhà phát triển chưa làm tốt khâu kiểm định mã nguồn trước khi xuất xưởng.

(còn tiếp)

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

About pdah
Pythonista, #bamboo CTF crew

Comments

22 Responses to “Phân tích ứng dụng Btalk trên Android – Phần một: Cơ chế xác thực người dùng”
  1. Pham says:

    Đọc cái này mọi người sẽ run rẩy gỡ ngay Btalk
    Thử hình dung một ngày nào đó toàn bộ dữ liệu trong máy của bạn bị đăng lên cho bàn dân thiên hạ chiêm ngưỡng.
    Bkav làm về bảo mật mà quá ẩu tả.
    Thảo nào website bị hack lên hack xuống

  2. chuong says:

    Đây là sản phẩm của người Việt Nam , không mấy công ty ở VN có thể làm được như BKAV . VN mình đa số làm các sản phẩm outsource, làm sản phẩm cho các thương hiệu nước ngoài . Đáng lẽ có Bug thì chỉ nên phản hồi cho nhà sản xuất để sửa chữa , đằng này lại bới móc để hạ uy tín triệt sản sản phẩm trí tuệ phần mềm của người VN để được gì …. ? để làm cho nền công nghệ nước nhà tụt hậu à .
    1 minh chứng đau lòng khác sau vụ Fallpy Bird về cái xấu của người VN

    • pdah says:

      Mục đích của bài viết này không nhằm đả kích công ty BKAV. Việc phân tích và công bố lỗ hổng là chuyện rất bình thường đối với các nhóm nghiên cứu về bảo mật, VNSecurity không phải là ngoại lệ. Chúng tôi vẫn tuân theo đúng quy trình: thông báo lỗi với nhà phát triển trước khi công bố lên website.

      Ngoài ra các ứng dụng OTT nổi tiếng như Whatsapp, Viber, LINE …. đều được cộng đồng bảo mật phân tích và thông báo lỗ hổng rộng rãi chứ không riêng gì Btalk.

      À, tên của ứng dụng mà bạn nhắc đến là Flappy Bird nhé :)

  3. Nguyễn Ngọc Hoàng says:

    Chào tác giả, trước hết mình cảm ơn vì 1 bài viết phân tích ứng dụng rất hay.
    Mình cũng có biết qua về lập trình android nên có 1 số câu hỏi mong đươc giải đáp, có sai mong bạn thông cảm.
    1: 1 ứng dụng gửi nhận tin nhắn qua server như thế này thì cần có thông tin chứng thực, nên vấn đề lưu thông tin chứng thực ở client để sử dụng cho mỗi lần gửi nhận tin nhắn là không thể tránh khỏi. Dù có lưu dạng token hay plain text password thì nếu lấy được thông tin này từ db hay preference(cái này mình chưa tìm hiểu cách lấy) thì thông tin xác thực coi như vẫn bị lộ → ở đây có cách nào để vượt qua vấn đề này không.
    2: Về vấn đề key mã hoá ở trên thì theo mình biết android có phương thức để encode tránh cho người khác decode mã nguồn nhưng hiện nay các tool vẫn có thể decode mã nguồn hay file xml để lấy thông tin này. → Làm thế nào để vượt qua vấn đề này.
    Trên đây là 2 câu hỏi mình muốn thắc mắc, nếu được bạn có thể đưa ra 1 số phương thức mà các app khác như line hay whatpp hay kakao dùng để vượt qua các vấn đề bảo mật trên được không.
    Vì các kiến thức này mình chưa có nhiều nên nếu có sai sót mong tác giả bỏ qua.
    Mình xin cảm ơn.

    • pdah says:

      Chào bạn,

      1. Bài viết của tôi không khẳng định việc lưu định danh người dùng và mật khẩu trên thiết bị là thiếu an toàn. Điều đáng nói ở đây là việc những dữ liệu đó được truyền qua kênh giao tiếp “không an toàn”, ở đây là thông qua SSL mà không có chứng thực certificate.

      2. Có lẽ bạn đang muốn nhắc đến phương pháp obfuscation. Phương pháp này chỉ giúp cho file APK của bạn khó bị dịch ngược hơn chứ không ngăn chặn hoàn toàn, một reverser nghiêm túc vẫn có thể phân tích được ứng dụng của bạn, anh ta chỉ phải tốn nhiều thời gian hơn mà thôi. Một nhược điểm khác của việc Obfuscation là khi ứng dụng gặp lỗi, thông tin của stack trace cũng không đủ trong sáng để developer có thể đọc và hiểu lỗi một cách dễ dàng.

      Thay vì cố gắng viết một ứng dụng android không thể bị dịch ngược, quan điểm của tôi là lập trình viên nên chú tâm vào thiết kế một API an toàn kết hợp với phân tích dữ liệu ở phía máy chủ.

      • Vietnguyen says:

        Mình rất thích câu nói của bạn.

        Thay vì cố gắng viết một ứng dụng android không thể bị dịch ngược, quan điểm của tôi là lập trình viên nên chú tâm vào thiết kế một API an toàn kết hợp với phân tích dữ liệu ở phía máy chủ.

  4. Minh Triet Pham Tran says:

    Các tác giả làm phân tích Android app nên công bố hash của file apk được phân tích để mọi người cùng kiểm chứng :) .

  5. Hưng says:

    hi a !
    theo những gì hiện giờ e biết thì cái tools decode apk chỉ ra được những dòng mã “compile”, không biết a dùng tool gì để “show all” thế ạ ? :D
    và, e vẫn chưa hiểu là tại sao Btalk lại lưu username/password ở Share_pref nhỉ, chả lẽ mỗi lần mở lên phải đăng nhập ? tại sao ko có 1 access_token để giúp làm việc này… thắc mắc quá ^^
    cuối cùng, cám ơn anh vì bài viết quá hay ! :D

    • pdah says:

      Chào Hưng,
      Có nhiều cách để tìm hiểu về mã nguồn của một file apk. Bạn có thể google với từ khóa: … extract java source code from apk …

  6. lava says:

    Đọc lúc đầu thấy bùn cười, đọc tới bước hash mà để seckey ở client là thấy bực rồi. Cty về công nghệ mà làm ăn sống nhăn. Quá nãn cho BKAV.

  7. Naro says:

    Trước đây mình cũng thử viết mã xác thực. Server sẽ gen 1 đoạn code ( n ký tự vừa số vừa chuỗi) và gửi về cho người dùng thông qua tin nhắn. Sau đó người dùng sẽ nhập code đó trên web. Mình thắc mắc là nếu người dùng gửi tin nhắn xác thực thì có bị giới hạn chỉ nhập số hay không vậy ?

  8. Anh Le says:

    Cảm ơn bài viết của bạn! Rất chi tiết. Tuy nhiên, việc bị ảnh hưởng bởi “Spam tin nhắn xác thực đến số di động khác” thì nhiều hãng khác cũng bị như Viber. Viber thực hiện việc block số điện thoại, nhằm ngăn ngừa việc gửi quá nhiều gói tin đăng ký. :)

  9. HenryGau says:

    Bài viết hay. Cho mình hỏi tác giả bằng cách nào có thể tìm được
    Configuration.REGISTER_KEY = “41ab3e484f918ff0d378058e50eb0f79e93d19383ca1053830a878a83bcce3fc”;?
    BkavTalk hình như ko open source, làm sao tác giả bài viết có thể đọc đc mã gốc của Bkav?

    Henry

  10. pixelart says:

    Hi anh, anh có thể cho em biết bằng cách nào để bắt được các $_GET , $_POST được request từ ứng dụng trên android mà anh có thể thấy được các thông số đó từ btalk ko ah

    Cám ơn anh

    • kalizero says:

      Hi ban co the su dung burpsuite hoac bat ky proxy nao tuong tu. Chay emulator bang cach. Emulator.exe @ten_emulator –http-proxy http:localhost:8080

      Viet bang dien thoai ko biet nho co chinh xac ko. Hihi

    • tienpp says:

      Bạn có thể phân tích tĩnh ứng dụng Btalk dưới thiết bị di động (apk trên Android) để biết được các hiện thực trên.

      • Quốc says:

        Cẩn thận vi phạm bản quyền, dịch ngược ứng dụng của người ta. Luật an toàn thông tin có hiệu lực rồi đấy bạn trẻ.

  11. Hà Thanh Tú says:

    các girl mà sử dụng phần mềm này thì MITM có vẻ là thú vị nhất rồi haha

  12. anon says:

    Đáng gia BKAV chỉ cần implement SSL cho đúng + rate limit cái API request thì cái đống preauth kia cũng không cần thiết nữa. Đằng này overengineer lên rồi cuối cùng cũng vẫn sai :))

  13. Trung says:

    Hạy nhưng chỉ tội chưa hiểu mấy :)

  14. Quá hay !
    Hâm mộ a tác giả bài này quá :D