This page looks best with JavaScript enabled

Wining the racing

 ·  ☕ 7 min read  ·  🐉 Edisc
Bài viết này nhằm mục đích ghi lại những kiến thức đã học để nhớ và hiểu rõ hơn. Bài viết tham khảo chủ yếu từ Winning the race: Signals, symlinks, and TOC/TOU

Giới thiệu

  • Không phải tất cả race condition đều là lỗ hổng, những phần lớn các race condition sẽ dẫn tới lỗ hổng ở một nơi nào đó. Nói cách khác, những lỗ hổng hình thành do race condition thường là những lỗ hổng cực kì nghiêm trọng.
  • Trong lập trình đa luồng, race conditions không phải là việc xuất hiện vấn đề và ta khai thác, nó chỉ là việc luồng thực thi không giống như chúng ta kì vọng.
  • Bugs có thể tồn tại ở mọi nơi, từ những ứng dụng Linux ở cấp thấp cho đến triển khai DBMS quan hệ đa luồng.

Race conditions là gì?

  • Hãy tưởng tượng bạn đang tham gia cuộc thi chạy điền kinh và đối thủ của bạn lại là chị Nguyễn Thi Thúy Hiền. Vì đã rất nỗ lực, bạn và chị Hiền ngang tài ngang sức và cũng bước vào giai đoạn nước rút về đích. Thật bất ngờ, cả 2 cùng chạm đích cùng một lúc, hệ thống cho thấy cả 2 chạm vạch đích cùng thời điểm đến hàng nano giây. Nếu chỉ chọn 1 quán quân vậy ai sẽ là quán quân? Bạn ? Hay chị Hiền? Hay cả 2 (việc này sẽ làm giảm giá trị của chức quán quân)? Hay chẳng ai cả? tổ chức thi đấu lại? Mọi khả năng đều có thể xảy ra và chẳng ai biết khả năng nào sẽ xảy ra. Race condition trong trường hợp này cũng tương tự như vậy.
  • Race conditions là một chủ đề cực kì lớn, với nhiều hàm ý bảo mật khác nhau, từ hành vi không dự đoán trước được, không có vẻ nguy hiểm gì cho đến sự cố máy chủ, chiếm quyền điều khiển bằng thực thi dòng lệnh từ xa. Nó bắt nguồn từ việc lập trình viên giả sử chương trình của mình đang chạy tuyến tính hoặc đang chạy song song nhưng không xem xét triệt để, an toàn. Chương trình của họ có thể hoàn hảo khi chạy 1 hoạt động (operation), những khi chạy 2 hay nhiều operations trên nhiều process khác nhau, nó có thể dẫn tới luồng thực thi bị thay đổi, dẫn tới kết quả không mong muốn đối với victim (hoặc mong muốn - đối với attacker).
  • Race conditons không phải luôn là lỗ hổng bảo mật vì một số trường hợp, những hành vi không mong muốn được phát sinh này không mang lại nguy hiểm nào đối với hệ thống cả.
  • Race conditons có thể xuất hiện ở nhiều ngữ cảnh, thậm chí tồn tại ngay trong những thiết bị điện tử cơ bản (cả điện sinh học. Race condtions đã tìm thấy bên trong não của chuột sống). Tiền đề cơ bản cho race conditions là 2 thread chống lại nhau để tìm người thắng cuộc. Người thắng có quyền thao túng luồng thực thi của ứng dụng.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>
#include <signal.h> // keep an eye out for this header especially
#include <race_conditon.h>

int main(void){
    if (something == permitted){
        doThis();
    }
    else {
        printf("lolnope\n");
    }
}
  • Thông thường, race conditons có xu hướng xuất hiện trong những ứng dụng viết bằng C. Đặc biệt trong những chương trình có sử dụng thư viện signal.h vì header này xuất hiện dự báo rằng chương trình sẽ có những race tìm ẩn để dẫn tới số lượng tín hiệu xử lí là ít nhất. Mặt khác, nếu kiểm tra quyền của các tệp có xuất hiện các symlink races cũng cho thấy có nguy cơ về race condition.
  • Đoạn code trên chỉ là mã giả, nó sẽ không chạy, mục đích của đoạn mã giả nhằm giúp chúng ta có cái nhìn trực quan hơn về kiểu tấn công dựa trên race condition. Gỉa sử attacker gửi hai operations tới chương trình tại cùng thời điểm, cùng 1 trạng thái trên luồng mã thực thi (nếu được). Nếu như thời gian chính xác, attacker có thể cho phép một biến nào đó đúng / hoặc sai tại một thời điểm kiểm tra, nhưng biến này không còn được sử dụng tại thời điểm đó. (Này được gọi là TOC/TOU race có nghĩa là Time of Check, Time of Use)
    Giả sử, chúng ta thực hiện lệnh
1
if (something_is_permitted) // check if permitted

Nếu điều kiện đúng thì nó sẽ thực thi doThis() giống như kì vọng của tác giả, tuy nhiên nếu somethig_is_not_permitted mà hàm if này vẫn chấp nhận thì khi thực hiện doThis() sẽ có nguy cơ phát sinh những trường hợp không mong muốn, và tuy theo mã sau đó thế nào mà attacker có thể bypass access controls, escalate privileges, cause a denial of service

  • Khi nói về Race Conditions, mọi người thường nghĩ tới những thứ gì đó rất nhanh, thời gian phải cực kì chính xác để có thể thực thi TOC/TOU race. Điều này không sai, tuy nhiên không phải lúc nào cũng vậy. Cùng xem xét ví dụ về lỗi `slow-paced" race condition:
    • Có một ứng dụng mạng xã hội, người dừng có thể sử đổi thông tin của họ.
    • Một user click vào nút “edit profile”, ứng dụng mở ra một trang web cho phép họ thực hiện sửa đổi.
    • User tiến hành sử đổi bằng bàn phím (go AFK - Away from Keyboard).
    • Quản trị viên nhìn thấy những lỗi không mong muốn trong chức năng sửa đổi thông tin trên website, nên quyết định tắt chức năng này. Do đó, user không thể dùng nó để sửa thông tin của họ.
    • Quay lại với user trên, anh ta vẫn còn đang ở trong trang web cho việc sửa đổi thông tin.
    • Mặc dù new user không thể truy cập vào trang “edit profile”, nhưng user này vẫn còn trang web cho việc sửa đổi thông tin nên anh ta vẫn có thể tiếp tục sửa đổi, mặc dù chức năng này đã bị quản trị viên tắt.
  • Race conditons có thể được gây ra do độ trễ trong networks. Giả sử có một hub và 2 linked nodes. Bob muốn đăng kí một channel #hax và Alice cũng muosn đăng kí cùng chanel này. Xem xét trường hợp sau:
    • Bob kết nối tới IRC từ node #1
    • Alice kết nối tới IRC từ node #2
    • Bob chạy /join #hax
    • Alice chạy /join #hax
    • Cả hai câu lệnh đều được thực hiện từu 2 node khác nhau, cùng 1 thời điểm.
    • Bob trở thành người điều hành của #hax.
    • Alic trở thành người điều hành của #hax.
    • Nguyên nhân cho trường hợp này bởi vì độ trễ mạng, node #1 sẽ có thời gian gửi tín hiệu tới node #2 để cảnh báo rằng Services Daemon đã bị người khác nắm giữ trên cùng network.
(PROTIP: When testing local desktop applications for Race Conditions - for example a compiled binary - use something like GDB or OllyDBG to set a breakpoint between TOC and TOU within the source code of the binary you are debugging. Execute your code from the breakpoint and take note of the results in order to determine any potential security risk or lack thereof. This is for confirmation of the bug only, and not for actual exploitation. As the saying goes, PoC||GTFO. This rings especially true with race conditions considering some of them are just bugs or glitches or whatever you wanna call them, as opposed to viable exploits with real attack value. If you cannot demonstrate impact, you probably should not report it)
Share on

Edisc
WRITTEN BY
Edisc
Cyber Security Engineer

 
What's on this Page