私はしばらく前に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/cmdline
proc_pid_cmdline_read
存在するfs/proc/base.c
。access_remote_vm
アドレスからmm->arg_start
アクセスされる(アクセスして)プロセスのメモリ部分は、mm->arg_end
プロセスの開始時にカーネルに書き込まれ、後で変更することはできません。
argv[1]
一部のデーモンはこの機能を使用して状態を反映しています。たとえば、またはまたは同じ文字列に変更します。多くのUNIXバリアントではstarting
available
exiting
setproctitle
これを行う関数です。一部のプログラムはこの機能を使用して機密データを非表示にします。プロセスの開始時にコマンドライン引数が表示されるため、これは使用が制限されています。
ほとんどの高度な言語は、引数を文字列オブジェクトにコピーし、元のリポジトリを変更する方法を提供していません。以下は、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
でこの機能で何度も使用されています。ユーザーパスワード。関数はパラメータ解析で呼び出されるため、カール呼び出しの最初に発生しますが、これが発生する前にコマンドラインをダンプすると、まだパスワードが公開されます。
パラメータはプロセス自体のメモリに格納されるため、デバッガを使用している場合を除いて外部から変更することはできません。
答え2
他の答えはこの質問に非常によく答えます。具体的な答え」この効果はどのように達成されますか?カールソースコードのどこにありますか?":
内部にカールソースコードのパラメータ解析部分、この-u
オプションは次のように処理されます。
case 'u':
/* user:password */
GetStr(&config->userpwd, nextarg);
cleanarg(nextarg);
break;
しかもcleanarg()
機能が定義されました次のように:
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
}
argv
したがって、他の回答で述べたように、ユーザー名:パスワードパラメータが空白で覆われていることは明らかです。
答え3
プロセスはパラメータを読み取ることができるだけでなく、書き込むこともできます。
私は開発者ではないため、これには慣れていませんが、外部では環境パラメータの変更などの操作を実行できます。