Nghịch chút với Wifi Chùa
Đôi lúc mình cần “kiểm tra độ bảo mật” của một số mạng wifi xung quanh, vì thế mình cần một từ điển các mật khẩu có sẵn (wordlist) để xem mạng wifi đó có đặt password an toàn hay không. Nếu google với từ khóa “password dictionary”, “wpa password list”, “wifi wordlist”… và chịu khó download thì bạn có thể có được một kho mật khẩu khá đồ sộ. Vấn đề là các mật khẩu này được tổng hợp từ mọi nguồn có thể – có rất nhiều password nhưng lại có ít có thể áp dụng ở Việt Nam – với giả thiết rằng các mật khẩu người Việt dùng thường có chứa ít nhiều từ tiếng Việt trong đó hoặc cách đặt mang đặc trưng của người Việt (trừ những mật khẩu được đặt theo một dãy số nào đó, ngày tháng, số điện thoại…). Trong nhiều trường hợp, việc sử dụng những bộ từ điển nói trên sẽ chỉ tốn rất nhiều thời gian khi xét tới việc phải dò khoảng vài trăm triệu hoặc thậm chí vài tỉ các mật khẩu. Vì vậy việc có một kho các từ khóa có thể làm mật khẩu của tiếng Việt sẽ giúp ích nhiều trong việc “penetration testing” này.
Trong hoàn cảnh đó, mình bắt đầu “me” một app chia sẻ password wifi được dùng nhiều ở Việt Nam: Wifi Chùa :D. Và việc thu thập mật khẩu của ứng dụng này hóa ra cũng khá đơn giản.
Đầu tiên mình setup một proxy để bắt các request ra vào từ Wifi Chùa, sử dụng http://mitmproxy.org/. Trong bài mình chạy mitmproxy trên Mac Osx.
brew install mitmproxy
==> Downloading https://homebrew.bintray.com/bottles/mitmproxy-0.11.1.yosemite.bottle.tar.gz
Already downloaded: /Library/Caches/Homebrew/mitmproxy-0.11.1.yosemite.bottle.tar.gz
==> Pouring mitmproxy-0.11.1.yosemite.bottle.tar.gz
Mitmproxy là một chương trình proxy, có thể bắt và can thiệp traffic HTTP/HTTPS đi ngang qua nó. Khi chạy, mitmproxy lắng nghe trên cổng 8080, có chức năng như một transparent proxy, chuyển tiếp traffic qua lại từ thiết bị di động (trong ví dụ của mình là iPhone) tới server khác. Để mitmproxy có thể thấy được traffic này, trên iPhone mình chỉnh lại router (gateway) là địa chỉ IP của máy Mac (`192.168.1.14`):
Trên Mac, mình cần thiết lập một chút để nó forward HTTP/HTTPS traffic cho mitmproxy:
sudo sysctl -w net.inet.ip.forwarding=1
cd /tmp
cat > mitmproxy.conf <<EOT
rdr on en0 inet proto tcp to any port 80 -> 127.0.0.1 port 8080
rdr on en0 inet proto tcp to any port 443 -> 127.0.0.1 port 8080
EOT
sudo pfctl -f mitmproxy.conf
sudo pfctl -e
Cho phép mitmproxy truy xuất tới pfctl:
sudo visudo
# Thêm dòng dưới đây:
ALL ALL=NOPASSWD: /sbin/pfctl -s state
Khởi động mitmproxy:
mitmproxy -T --host
Sau đó mình mở app Wifi Chùa trên iPhone, lúc này mitmproxy sẽ bắt được các request do app gửi đi:
Bạn có thể thấy mitmproxy có thể bắt được các request HTTPS. Tại sao vậy? Kết nối HTTPS sử dụng giao thức bảo mật SSL/TLS, làm sao có thể bị “bắt” dễ dàng như thế? Đơn giản thôi, SSL hoạt động một cách xuyên suốt với người dùng cuối vì chữ ký của CA (Certificate Authority – Nhà cung cấp chứng thư số) được cài sẵn trên hệ điều hành (trường hợp này là iOS). Nếu chữ ký của SSL certificate mà kết nối HTTPS sử dụng không trùng khớp hoặc đến từ một CA không tin cậy, client (app Wifi Chùa) tạo request sẽ từ chối kết nối. Mitmproxy giả vờ là server mà client đang muốn kết nối đến, và giả làm một client đang kết nối tới server thực. Nó tạo ra một SSL certificate và ký certificate này bằng chữ ký CA cũng do nó tạo ra. Vì vậy để client không “la làng” và không chịu “làm việc” khi nó thấy chữ ký lạ của mitmproxy, bạn cần cài đặt chữ ký này trên iPhone. File chữ ký này nằm tại đường dẫn `~/.mitmproxy/mitmproxy-ca.pem`, để cài đặt mình gửi 1 email đính kèm file này vào địa chỉ email trên iPhone có thể nhận được, và sau đó chỉ việc cài nó:
Sau đó mình bật chức năng cập nhật dữ liệu của Wifi Chùa. Sau khi theo dõi và loại bớt các request liên quan đến quảng cáo, analytics này nọ thì mình thấy request này:
Bấm `Tab` để xem response:
Ồ dé, đây là thứ mình cần, các password đã hiện ra một cách trần trụi :D Theo POST request ở trên thì API lấy dữ liệu này nhận vào một số thông tin, trong đó có tên tình/thành phố và trả về các mạng wifi và mật khẩu có trong tỉnh/thành này, có phân trang. Việc tiếp theo của mình là viết một script mô phỏng việc lấy dữ liệu từ 63 tỉnh thành, lần lượt. Sau khi thanh lọc đi các mật khẩu không “đạt chuẩn” (quảng cáo, trẻ trâu khiêu khích, không liên quan…) mình có được khoảng một wordlist khoảng 150.000 dòng. Cũng không tệ.
Bài học có thể rút ra ở đây, ở góc độ người làm app, là để đảm bảo an toàn dữ liệu thì dùng HTTPS thôi là chưa đủ. Nếu bạn không muốn người khác (có thể là đối thủ chẳng hạn) có được dữ liệu của mình như lấy… đồ chùa thì cần bổ sung thêm một số cách mã hóa request và response, để ngay cả khi bị “reverse engineer” kiểu này thì cũng khó khăn nhiều hơn cho kẻ tấn công.
Cập nhật: ngoài phương pháp mình nêu trên thì có một cách cụ thể hữu hiệu để bảo vệ kết nối HTTPS đó là dùng Certificate Pinning. Nôm na là bạn gom SSL certificate của server của bạn vào ứng dụng luôn, và chỉ tạo kết nối nếu certificate của server trùng khớp với certificate trong ứng dụng. Trong trường hợp đó, mitmproxy sẽ cảnh báo không can thiệp được kết nối. Ví dụ:
Warn: Client Handshake failed. The client may not trust the proxy's certificate for graph.facebook.com