カールは、パスワードがps出力に表示されないようにどのように保護しますか?

カールは、パスワードがps出力に表示されないようにどのように保護しますか?

私はしばらく前にcurlコマンドライン引数として与えられたユーザー名とパスワードが出力に表示されないことを発見しましたps(もちろんbashレコードには表示されますが)。

にも表示されません/proc/PID/cmdline

(ただし、結合されたユーザー名/パスワードパラメータの長さはエクスポートできます。)

デモは次のとおりです。

[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 ~]# 

この効果はどのように達成されますか? ソースコードのどこかにありますかcurl? (curl機能ではなく機能だと思いましたがps? それとも一種のカーネル機能なのでしょうか?)


返品:バイナリ実行可能ファイルのソースコードの外でこれを達成できますか? たとえば、シェルコマンドを使用してroot権限と組み合わせることはできますか?

つまり、特定の人に渡したパラメータが出力に表示または/proc出力されないように何とか隠すことができますかps?(同じことだと思います)普段着シェルコマンド? (私はこの質問に対する答えが「いいえ」と推測しましたが、追加の質問を含める価値があるようです。)

ベストアンサー1

カーネルがプロセスを実行すると、プロセスに属する読み書きメモリ(少なくともLinuxの場合はスタック)にコマンドライン引数をコピーします。プロセスは他のメモリと同様にこのメモリに書き込むことができます。パラメータが表示されたら、psプロセスメモリの特定のアドレスに保存されているすべての内容を再読み込みします。ほとんどのプログラムは元のパラメータを保持しますが、変更できます。これPOSIXの説明ps指摘

表示された文字列がパラメーター・リストのバージョン(開始時にコマンドに渡される)か、パラメーター・バージョン(アプリケーションによって変更された可能性がある)かは指定されません。アプリケーションは引数リストを変更し、その修正をpsの出力に反映できるとは信じられません。

ほとんどのUNIXバリアントはこれらの変更を反映していますが、他の種類のオペレーティングシステムでのPOSIX実装はそうではない可能性があるため、これに言及します。

プロセスはランダムに変更できないため、この機能は使用が制限されています。少なくともパラメーターの合計長を増やすことはできません。なぜなら、プログラムはpsパラメータを取得した場所を変更できず、領域を元のサイズ以上に拡張することもできないからです。引数は C スタイルの null で終わる文字列 (末尾に複数の null 引数を持つものと変わらない) なので、末尾に null バイトを入れると長さが効果的に短くなります。

本当に詳しく知りたい場合は、オープンソース実装のソースコードを確認してください。 Linuxでのソースはps興味深いものではありません。あなたが見ることができるのはそれですプロセスファイルシステム、存在する。このファイルの内容を生成するコードはカーネルにあります。/proc/PID/cmdlineproc_pid_cmdline_read存在するfs/proc/base.caccess_remote_vmアドレスからmm->arg_startアクセスされる(アクセスして)プロセスのメモリ部分は、mm->arg_endプロセスの開始時にカーネルに書き込まれ、後で変更することはできません。

argv[1]一部のデーモンはこの機能を使用して状態を反映しています。たとえば、またはまたは同じ文字列に変更します。多くのUNIXバリアントではstartingavailableexitingsetproctitleこれを行う関数です。一部のプログラムはこの機能を使用して機密データを非表示にします。プロセスの開始時にコマンドライン引数が表示されるため、これは使用が制限されています。

ほとんどの高度な言語は、引数を文字列オブジェクトにコピーし、元のリポジトリを変更する方法を提供していません。以下は、argv要素を直接変更してこの機能を示すCプログラムです。

#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;
}

出力例:

./a.out hello world
0000000 11111 22222

argvカールソースコードで修正を見ることができます。カールは機能cleanargするsrc/tool_paramhlp.cすべてのスペースを変更するパラメータを使用するときに使用されますmemset。たとえば、編集などsrc/tool_getparam.cでこの機能で何度も使用されています。ユーザーパスワード。関数はパラメータ解析で呼び出されるため、カール呼び出しの最初に発生しますが、これが発生する前にコマンドラインをダンプすると、まだパスワードが公開されます。

パラメータはプロセス自体のメモリに格納されるため、デバッガを使用している場合を除いて外部から変更することはできません。

おすすめ記事