Làm thế nào để curl bảo vệ một mật khẩu xuất hiện trong đầu ra ps?


68

Trước đây tôi đã nhận thấy rằng tên người dùng và mật khẩu được cung cấp curllàm đối số dòng lệnh không xuất hiện trong psđầu ra (mặc dù tất nhiên chúng có thể xuất hiện trong lịch sử bash của bạn).

Họ cũng không xuất hiện trong /proc/PID/cmdline.

(Tuy nhiên, độ dài của đối số tên người dùng / mật khẩu kết hợp có thể được lấy.)

Trình diễn dưới đây:

[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*



[1]+  Stopped                 nc -l 80
[root@localhost ~]# jobs
[1]+  Stopped                 nc -l 80
[2]-  Running                 curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root      3343  3258  0 22:37 pts/1    00:00:00 curl -u               localhost
root      3347  3258  0 22:38 pts/1    00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline 
0000000    7563    6c72    2d00    0075    2020    2020    2020    2020
          c   u   r   l nul   -   u nul  sp  sp  sp  sp  sp  sp  sp  sp
0000020    2020    2020    0020    6f6c    6163    686c    736f    0074
         sp  sp  sp  sp  sp nul   l   o   c   a   l   h   o   s   t nul
0000040
[root@localhost ~]# 

Làm thế nào là hiệu ứng này đạt được? Có phải nó ở đâu đó trong mã nguồn của curl? (Tôi cho rằng đó là một curltính năng, không phải là một pstính năng? Hoặc nó là một tính năng hạt nhân nào đó?)


Ngoài ra: điều này có thể đạt được từ bên ngoài mã nguồn của tệp thực thi nhị phân không? Ví dụ: bằng cách sử dụng các lệnh shell, có thể kết hợp với quyền root?

Nói cách khác, bằng cách nào đó tôi có thể che giấu một đối số xuất hiện trong /prochoặc ở psđầu ra (điều tương tự, tôi nghĩ) mà tôi đã chuyển sang một số lệnh shell tùy ý ? (Tôi đoán câu trả lời cho điều này là "không" nhưng có vẻ đáng giá bao gồm cả nửa câu hỏi thêm này.)



16
Không phải là một câu trả lời, nhưng lưu ý rằng phương pháp này không an toàn . Có một cửa sổ cuộc đua giữa bắt đầu chương trình và xóa các chuỗi đối số trong đó bất kỳ người dùng nào cũng có thể đọc mật khẩu. Không chấp nhận mật khẩu nhạy cảm trên dòng lệnh.
R ..

1
Liên quan lỏng lẻo: Biến môi trường thuộc về ai? có ai trong thực tế sử dụng environtrực tiếp để truy cập các biến môi trường không? - dòng dưới cùng: danh sách đối số, giống như danh sách các biến môi trường, nằm trong bộ nhớ quy trình người dùng đọc / ghi và có thể được sửa đổi bởi quy trình người dùng.
Scott

1
@ JPhi1618, chỉ cần biến ký tự đầu tiên của grepmẫu của bạn thành một lớp ký tự. Ví dụ:ps -ef | grep '[c]url'
Wildcard

1
@mpy, t không phức tạp lắm. Một số regexes khớp với chính họ và một số thì không. curlphù hợp curlnhưng [c]urlkhông phù hợp [c]url. Nếu bạn cần biết thêm chi tiết, hãy hỏi một câu hỏi mới và tôi rất sẵn lòng trả lời.
tự đại diện

Câu trả lời:


78

Khi kernel thực thi một tiến trình, nó sao chép các đối số dòng lệnh vào bộ nhớ đọc ghi thuộc về tiến trình (trên ngăn xếp, ít nhất là trên Linux). Quá trình có thể ghi vào bộ nhớ đó như bất kỳ bộ nhớ khác. Khi pshiển thị đối số, nó đọc lại bất cứ thứ gì được lưu trữ tại địa chỉ cụ thể đó trong bộ nhớ của quy trình. Hầu hết các chương trình giữ các đối số ban đầu, nhưng có thể thay đổi chúng. Các mô tả POSIX củaps tiểu bang đó

Không xác định được liệu chuỗi được biểu thị là một phiên bản của danh sách đối số khi nó được truyền cho lệnh khi nó bắt đầu hay là một phiên bản của các đối số vì chúng có thể đã được ứng dụng sửa đổi. Các ứng dụng không thể phụ thuộc vào việc có thể sửa đổi danh sách đối số của chúng và việc sửa đổi đó được phản ánh trong đầu ra của ps.

Lý do điều này được đề cập là hầu hết các biến thể unix phản ánh sự thay đổi, nhưng việc triển khai POSIX trên các loại hệ điều hành khác có thể không.

Tính năng này được sử dụng hạn chế vì quá trình không thể thực hiện thay đổi tùy ý. Ít nhất, tổng chiều dài của các đối số không thể tăng lên, bởi vì chương trình không thể thay đổi vị trí nơi pssẽ tìm nạp các đối số và không thể mở rộng khu vực vượt quá kích thước ban đầu của nó. Độ dài có thể được giảm một cách hiệu quả bằng cách đặt các byte null ở cuối, bởi vì các đối số là các chuỗi kết thúc null kiểu C (điều này không thể phân biệt được với việc có một loạt các đối số trống ở cuối).

Nếu bạn thực sự muốn đào, bạn có thể xem nguồn của triển khai nguồn mở. Trên Linux, nguồn pslà không thú vị, tất cả các bạn sẽ thấy có mà nó đọc các đối số dòng lệnh từ hệ thống tập tin proc , trong . Mã tạo nội dung của tệp này nằm trong kernel, in . Phần bộ nhớ của tiến trình (được truy cập bằng ) đi từ địa chỉ đến ; những địa chỉ này được ghi lại trong kernel khi quá trình bắt đầu và không thể thay đổi sau đó./proc/PID/cmdlineproc_pid_cmdline_readfs/proc/base.caccess_remote_vmmm->arg_startmm->arg_end

Một số trình tiện ích sử dụng khả năng này để phản ánh trạng thái của chúng, ví dụ: chúng thay đổi chúng argv[1]thành một chuỗi như startinghoặc availablehoặc exiting. Nhiều biến thể unix có setproctitlechức năng để làm điều này. Một số chương trình sử dụng khả năng này để ẩn dữ liệu bí mật. Lưu ý rằng điều này được sử dụng hạn chế vì các đối số dòng lệnh được hiển thị trong khi quá trình bắt đầu.

Hầu hết các ngôn ngữ cấp cao sao chép các đối số vào các đối tượng chuỗi và không đưa ra cách sửa đổi bộ nhớ gốc. Đây là một chương trình C thể hiện khả năng này bằng cách thay đổi argvcác yếu tố trực tiếp.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int i;
    system("ps -p $PPID -o args=");
    for (i = 0; i < argc; i++)
    {
        memset(argv[i], '0' + (i % 10), strlen(argv[i]));
    }
    system("ps -p $PPID -o args=");
    return 0;
}

Đầu ra mẫu:

./a.out hello world
0000000 11111 22222

Bạn có thể thấy argvsửa đổi trong mã nguồn curl. Curl định nghĩa một hàm cleanargtrongsrc/tool_paramhlp.c đó được sử dụng để thay đổi một đối số cho tất cả các khoảng trắng bằng cách sử dụng memset. Trong src/tool_getparam.cchức năng này được sử dụng một vài lần, ví dụ bằng cách xác định lại mật khẩu người dùng . Vì hàm được gọi từ phân tích tham số, nên nó xuất hiện sớm trong lệnh gọi curl, nhưng việc hủy dòng lệnh trước khi điều này xảy ra sẽ vẫn hiển thị bất kỳ mật khẩu nào.

Vì các đối số được lưu trữ trong bộ nhớ riêng của quy trình, chúng không thể được thay đổi từ bên ngoài trừ khi sử dụng trình gỡ lỗi.


Tuyệt quá! Vì vậy, liên quan đến đoạn mã thông số kỹ thuật đó, tôi hiểu nó có nghĩa là nó sẽ tuân thủ POSIX để làm cho hạt nhân của bạn lưu trữ một đối số dòng lệnh gốc của quy trình bên ngoài bộ nhớ đọc ghi của quá trình ( ngoài bản sao trong bộ nhớ đọc ghi) ? Và sau đó có psbáo cáo đối số từ phần bộ nhớ của kernel đó, bỏ qua mọi thay đổi được thực hiện trong bộ nhớ đọc-ghi của các tiến trình? Nhưng (nếu tôi hiểu đúng?) Hầu hết các biến thể UNIX thậm chí không thực hiện trước đây, vì vậy bạn không thể psthực hiện việc thực hiện sau mà không sửa đổi kernel, vì dữ liệu gốc không được giữ ở bất cứ đâu?
tự đại diện

1
@Wildcard Đúng. Có thể có các triển khai Unix giữ nguyên bản gốc nhưng tôi không nghĩ bất kỳ cái nào phổ biến làm được. Ngôn ngữ C cho phép argvthay đổi nội dung của các mục nhập (bạn không thể đặt argv[i], nhưng bạn có thể viết argv[i][0]qua argv[i][strlen(argv[i])]), do đó phải có một bản sao trong bộ nhớ của quy trình.
Gilles

2
Hàm có liên quan trong mã nguồn curl: github.com/curl/curl/blob/master/src/tool_paramhlp.c#L139
sebasth

4
@Wildcard, Solaris làm điều này. Dòng lệnh được xem bởi / usr / ucb / ps là bản sao của quá trình sở hữu (có thể thay đổi). Dòng lệnh được xem bởi / usr / bin / ps là bản sao sở hữu (không thay đổi). Kernel chỉ giữ 80 ký tự đầu tiên mặc dù. Bất cứ điều gì khác được cắt ngắn.
BowlOfRed

1
@Wildcard Thật vậy, các null null là các đối số trống. Trong psđầu ra, rất nhiều đối số trống trông giống như không có gì ở đó, nhưng đúng vậy, nó sẽ tạo ra sự khác biệt nếu bạn kiểm tra có bao nhiêu khoảng trống và bạn có thể quan sát trực tiếp nhiều hơn từ đó /proc/PID/cmdline.
Gilles

14

Các câu trả lời khác trả lời tốt câu hỏi một cách chung chung. Để trả lời cụ thể " Hiệu ứng này đạt được như thế nào? Có phải ở đâu đó trong mã nguồn của curl không? ":

Trong phần phân tích đối số của mã nguồn curl , -utùy chọn được xử lý như sau:

    case 'u':
      /* user:password  */
      GetStr(&config->userpwd, nextarg);
      cleanarg(nextarg);
      break;

cleanarg()chức năng được định nghĩa như sau:

void cleanarg(char *str)
{
#ifdef HAVE_WRITABLE_ARGV
  /* now that GetStr has copied the contents of nextarg, wipe the next
   * argument out so that the username:password isn't displayed in the
   * system process list */
  if(str) {
    size_t len = strlen(str);
    memset(str, ' ', len);
  }
#else
  (void)str;
#endif
}

Vì vậy, chúng ta có thể thấy rõ rằng tên người dùng: đối số mật khẩu argvđược ghi đè bằng khoảng trắng, như được mô tả bởi các câu trả lời khác.


Tôi thích rằng bình luận ở cleanargcác tiểu bang rõ ràng rằng nó đang làm những gì câu hỏi đang hỏi!
Floris

3

Một quá trình không chỉ có thể đọc các tham số của nó mà còn viết chúng.

Tôi không phải là nhà phát triển nên tôi không quen thuộc với công cụ này nhưng có thể từ bên ngoài có thể tiếp cận với cách tiếp cận tương tự như thay đổi các tham số môi trường:

https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another- Processes-en môi-biến


Được rồi, nhưng chạy ví dụ bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'cho thấy ít nhất là trong trình bao, thiết lập các tham số khác với sửa đổi những gì mà kernel xem là tham số quá trình.
tự đại diện

4
@Wildcard Đối số vị trí trong tập lệnh shell là bản sao ban đầu của một số đối số dòng lệnh của quy trình shell. Hầu hết các shell không để kịch bản thay đổi các đối số ban đầu.
Gilles

@Gilles, vâng, đó là điểm nhận xét của tôi. :) Rằng tuyên bố chung rằng một quá trình có thể làm điều đó (câu đầu tiên của câu trả lời này) không trả lời liệu điều này có thể đạt được bằng các tính năng shell hiện có hay không. Câu trả lời cho điều này dường như là "không", đó là những gì tôi đoán ở cuối câu hỏi của mình.
tự đại diện
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.