উত্স কোড ছাড়াই প্রোগ্রামটিতে যুক্তিগুলি লুকান


15

আমি যে প্রোগ্রামটি চালাচ্ছি তার জন্য আমার কিছু সংবেদনশীল তর্ক আড়াল করা দরকার তবে সোর্স কোডে আমার অ্যাক্সেস নেই। আমি এটি একটি ভাগ করা সার্ভারেও চালাচ্ছি যাতে আমি এর মতো কিছু ব্যবহার করতে hidepidপারি না কারণ আমার কাছে সুডোর সুবিধা নেই।

এখানে আমি চেষ্টা করেছি এমন কিছু জিনিস রয়েছে:

  • export SECRET=[my arguments], তারপরে কল করার পরে ./program $SECRET, তবে এটি কোনও সাহায্য করবে বলে মনে হচ্ছে না।

  • ./program `cat secret.txt`যেখানে secret.txtআমার যুক্তিগুলি রয়েছে তবে সর্বশক্তিমান psআমার গোপন বিষয়গুলি স্নিগ্ধ করতে সক্ষম।

আমার যুক্তিগুলি আড়াল করার অন্য কোনও উপায় কি এতে প্রশাসকের হস্তক্ষেপ জড়িত নয়?


সেই বিশেষ প্রোগ্রামটি কী? এটি যদি একটি সাধারণ কমান্ড হয় তবে আপনাকে জানাতে হবে (এবং এটির সাথে অন্য কোনও উপায় থাকতে পারে) এটি কোনটি
বেসাইল স্টারিনকিভিচ

14
সুতরাং আপনি বুঝতে পেরেছেন কী চলছে, যে জিনিসগুলি আপনি চেষ্টা করেছেন তাদের কাজ করার কোনও সম্ভাবনা নেই কারণ শেল পরিবেশের ভেরিয়েবলগুলি বিস্তৃত করার জন্য এবং প্রোগ্রামটি চালুর আগে কমান্ড প্রতিস্থাপন সম্পাদনের জন্য দায়ী । ps"আপনার গোপনীয় বিষয়গুলি ছিঁড়ে ফেলার জন্য" যাদুকর কিছু করছে না। যাইহোক, যুক্তিযুক্ত-লিখিত প্রোগ্রামগুলির পরিবর্তে একটি যুক্ত ফাইল হিসাবে সরাসরি স্ট্রিম হিসাবে না নিয়ে কোনও নির্দিষ্ট ফাইল থেকে বা স্টিডিনের কাছ থেকে কোনও গোপন বিষয় পড়ার জন্য একটি কমান্ড-লাইন বিকল্প দেওয়া উচিত।
জেমসডলিন

আমি একটি বেসরকারী সংস্থা দ্বারা রচিত একটি আবহাওয়া সিমুলেশন প্রোগ্রাম চালাচ্ছি। তারা তাদের উত্স কোড ভাগ করে না, বা তাদের ডকুমেন্টেশনগুলি কোনও ফাইল থেকে কোনও গোপন ভাগ করে নেওয়ার কোনও উপায় সরবরাহ করে না। এখানে বিকল্পগুলির বাইরে থাকতে পারে
এমএস

উত্তর:


25

যেমনটি এখানে ব্যাখ্যা করা হয়েছে , লিনাক্স প্রোগ্রামের ডেটা স্পেসে একটি প্রোগ্রামের আর্গুমেন্ট রাখে এবং এই অঞ্চলটির শুরুতে একটি পয়েন্টার রাখে। psপ্রোগ্রাম আর্গুমেন্টগুলি খুঁজে পেতে এবং প্রদর্শন করতে এটি যা ব্যবহার করে ।

যেহেতু ডেটা প্রোগ্রামের স্পেসে রয়েছে তাই এটি এটিকে কাজে লাগাতে পারে। প্রোগ্রামটি পরিবর্তন না করেই এটি করার সাথে একটি main()ফাংশন সহ শিম লোড করা জড়িত যা প্রোগ্রামের আসল মূলটির আগে ডাকা হবে। এই psশিমটি আসল আর্গুমেন্টগুলিকে একটি নতুন জায়গাতে অনুলিপি করতে পারে, তারপরে মূল আর্গুমেন্টগুলি ওভাররাইট করে যাতে এটি নালাগুলি দেখতে পাবে।

নিম্নলিখিত সি কোড এটি করে।

/* /unix//a/403918/119298
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_main.so shim_main.c
 * LD_PRELOAD=/.../shim_main.so theprogram theargs...
 */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>

typedef int (*pfi)(int, char **, char **);
static pfi real_main;

/* copy argv to new location */
char **copyargs(int argc, char** argv){
    char **newargv = malloc((argc+1)*sizeof(*argv));
    char *from,*to;
    int i,len;

    for(i = 0; i<argc; i++){
        from = argv[i];
        len = strlen(from)+1;
        to = malloc(len);
        memcpy(to,from,len);
        memset(from,'\0',len);    /* zap old argv space */
        newargv[i] = to;
        argv[i] = 0;
    }
    newargv[argc] = 0;
    return newargv;
}

static int mymain(int argc, char** argv, char** env) {
    fprintf(stderr, "main argc %d\n", argc);
    return real_main(argc, copyargs(argc,argv), env);
}

int __libc_start_main(pfi main, int argc,
                      char **ubp_av, void (*init) (void),
                      void (*fini)(void),
                      void (*rtld_fini)(void), void (*stack_end)){
    static int (*real___libc_start_main)() = NULL;

    if (!real___libc_start_main) {
        char *error;
        real___libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
        if ((error = dlerror()) != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    real_main = main;
    return real___libc_start_main(mymain, argc, ubp_av, init, fini,
            rtld_fini, stack_end);
}

এতে হস্তক্ষেপ করা সম্ভব নয় main()তবে আপনি স্ট্যান্ডার্ড সি লাইব্রেরি ফাংশনে হস্তক্ষেপ করতে পারেন __libc_start_main, যা মূল কল করতে চলেছে । shim_main.cশুরুতে মন্তব্যটিতে উল্লিখিত হিসাবে এই ফাইলটি সংকলন করুন , এবং এটি প্রদর্শিত হিসাবে চালান। আমি কোডটিতে একটি রেখে এসেছি printfযাতে আপনি পরীক্ষা করে দেখতে পারেন যে এটি আসলে বলা হচ্ছে। উদাহরণস্বরূপ, চালান

LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100

তারপরে একটি করুন psএবং দেখবেন একটি ফাঁকা কমান্ড এবং আরোগুলি প্রদর্শিত হচ্ছে।

কমান্ড আরগগুলি দৃশ্যমান হতে পারে এমন একটি অল্প পরিমাণে এখনও আছে। এটি এড়ানোর জন্য, উদাহরণস্বরূপ, কোনও ফাইল থেকে আপনার গোপনীয়তা পড়তে এবং প্রোগ্রামে পাস হওয়া আর্গগুলিতে এটি যুক্ত করতে শিম পরিবর্তন করতে পারেন।


12
তবে এখনও একটি সংক্ষিপ্ত উইন্ডো /proc/pid/cmdlineথাকবে যা চলাকালীন গোপনীয়তাটি প্রদর্শন করবে (এটি যখন curlকমান্ড লাইনে পাসওয়ার্ডটি গোপন করার চেষ্টা করে)। আপনি LD_PRELOAD ব্যবহার করার সময়, আপনি মুখ্য মোড়কে রাখতে পারেন যাতে পরিবেশ থেকে গোপনীয়তাটি মূলত প্রাপ্ত আরজিভিতে অনুলিপি করা হয়। কল হওয়ার মতো LD_PRELOAD=x SECRET=y cmdযেখানে আপনি থাকার main()সাথে কল করবেনargv[][argv[0], getenv("SECRET")]
স্টাফেন চেজেলাস

কোনও গোপনীয়তা লুকানোর জন্য আপনি পরিবেশটি ব্যবহার করতে পারবেন না কারণ এটি দৃশ্যমান /proc/pid/environ। এটি আরোগুলির মতো একইভাবে ওভাররাইটযোগ্য হতে পারে তবে এটি একই উইন্ডোটি ছেড়ে দেয়।
meuh

11
/proc/pid/cmdlineপ্রকাশ্য, /proc/pid/environনা। কিছু সিস্টেম ছিল যেখানে ps(সেখানে নির্ধারিত একটি নির্বাহী) যে কোনও প্রক্রিয়ার পরিবেশকে উন্মোচিত করেছিল, তবে আমি মনে করি না আপনি আজকাল কোনও উপায়ে এসে পৌঁছে যাবেন। পরিবেশটি সাধারণত যথেষ্ট নিরাপদ হিসাবে বিবেচিত হয় । একই ইউইড সহ প্রক্রিয়াগুলি থেকে প্রাইজিং নিরাপদ নয়, তবে এগুলি প্রায়শই একই ইউইড দ্বারা প্রক্রিয়াগুলির মেমরি পড়তে পারে, তাই এটি সম্পর্কে আপনি তেমন কিছু করতে পারেন না।
স্টাফেন চেজেলাস

4
@ স্টাফেইনচাজেলাস: যদি কেউ গোপনীয়তা পাস করতে পরিবেশ ব্যবহার করে তবে আদর্শভাবে mainমোড়ানো প্রোগ্রামটি যে মোড়ানো প্রোগ্রামের পদ্ধতিতে তা এগিয়ে দেয় তা শিশু প্রসেসের দুর্ঘটনাজনিত ফাঁস এড়াতে পরিবেশের পরিবর্তনশীলটিকেও সরিয়ে দেয়। বিকল্পভাবে মোড়ক একটি ফাইল থেকে সমস্ত কমান্ড-লাইন আর্গুমেন্ট পড়তে পারে ।
ডেভিড ফোস্টার

@ ডেভিডফোস্টার, ভাল পয়েন্ট আমি তা আমলে নিতে আমার উত্তর আপডেট করেছি।
স্টাফেন চেজেলাস

16
  1. প্রশ্নযুক্ত অ্যাপ্লিকেশনটির কমান্ড লাইন ইন্টারফেসের ডকুমেন্টেশন পড়ুন। সরাসরি আর্গুমেন্টের পরিবর্তে কোনও ফাইল থেকে গোপনীয়তা সরবরাহ করার বিকল্প থাকতে পারে।

  2. যদি এটি ব্যর্থ হয় তবে অ্যাপ্লিকেশনটির বিরুদ্ধে কোনও গোপন সরবরাহের কোনও নিরাপদ উপায় নেই এই কারণেই একটি বাগ রিপোর্ট দাখিল করুন।

  3. আপনি সর্বদা সাবধানতার সাথে (!) সমাধানটি সুনির্দিষ্টভাবে আপনার মেইউয়ের জবাবের সাথে মানিয়ে নিতে পারেন । স্টাফেনের মন্তব্য এবং তার অনুসরণগুলি সম্পর্কে বিশেষ বিবেচনা করুন।


12

প্রোগ্রামটি কাজ করার জন্য আপনার যদি যুক্তিগুলি পাস করার প্রয়োজন হয় তবে আপনি যদি hidepidপ্রেফস ব্যবহার না করতে পারেন তবে আপনি ভাগ্য থেকে দূরে থাকবেন ।

যেহেতু আপনি উল্লেখ করেছেন এটি বাশ স্ক্রিপ্ট, আপনার ইতিমধ্যে উত্স কোড উপলব্ধ থাকা উচিত, কারণ বাশ কোনও সংকলিত ভাষা নয়।

যে ব্যর্থ, আপনি পারে ব্যবহার প্রক্রিয়ার cmdline- র পুনর্লিখন পাবে gdbবা খেলার কাছাকাছি অনুরূপ এবং argc/ argvএকবার এটি ইতিমধ্যে শুরু, কিন্তু:

  1. এটি সুরক্ষিত নয়, যেহেতু আপনি এখনও আপনার প্রোগ্রামের যুক্তিগুলি পরিবর্তন করার আগে প্রাথমিকভাবে প্রকাশ করেন
  2. এটি বেশ হ্যাকি, এমনকি যদি আপনি এটি কাজ করতে পেতেন তবে আমি তার উপর নির্ভর করার পরামর্শ দেব না

কোডটি সংশোধন করার জন্য আমি কেবলমাত্র উত্স কোডটি পেতে বা বিক্রেতার সাথে কথা বলার সুপারিশ করব। পসিক্স অপারেটিং সিস্টেমে কমান্ড লাইনে সিক্রেট সরবরাহ করা নিরাপদ অপারেশনের সাথে বেমানান।


11

যখন একটি প্রক্রিয়া একটি কমান্ড কার্যকর করে ( execve()সিস্টেম কলের মাধ্যমে ), এর স্মৃতি মুছে ফেলা হয়। মৃত্যুদন্ড জুড়ে কিছু তথ্য প্রেরণ করার জন্য, execve(): সিস্টেম কল যে জন্য দুটি আর্গুমেন্ট লাগে argv[]এবং envp[]অ্যারে।

এগুলি দুটি স্ট্রিংয়ের অ্যারে:

  • argv[] যুক্তি রয়েছে
  • envp[]var=valueবিন্যাসে (কনভেনশন অনুসারে) স্ট্রিং হিসাবে পরিবেশের পরিবর্তনশীল সংজ্ঞা রয়েছে ।

যখন তুমি কর:

export SECRET=value; cmd "$SECRET"

(এখানে প্যারামিটার সম্প্রসারণের আশেপাশে নিখোঁজ উক্তিগুলি জুড়েছে)।

আপনি নির্বাহ করছি cmdগোপন সঙ্গে ( value) উভয় পাশ argv[]এবং envp[]argv[]হবে ["cmd", "value"]এবং envp[]কিছু [..., "PATH=/bin:...", "HOME=...", ..., "SECRET=value", "TERM=xterm", ...]। যেমন পরিবেশের পরিবর্তনশীল থেকে গোপনের মান পুনরুদ্ধার করার জন্য cmdকোনও getenv("SECRET")বা সমমানের কাজ করা হয় না , SECRETপরিবেশে রাখাই কার্যকর নয়।

argv[]জনসাধারণের জ্ঞান। এটি আউটপুট দেখায় psenvp[]আজকাল হয় না। লিনাক্স এ এটি দেখায় /proc/pid/environ। এটি ps ewwwবিএসডি-তে (এবং psলিনাক্সে প্রোপস-এনজি এর সাথে) আউটপুট দেখায় , তবে কেবল একই কার্যকর ইউআইডি (এবং সেটুয়েড / সেটগিড এক্সিকিউটেবলের জন্য আরও বিধিনিষেধের সাথে) চলমান প্রক্রিয়াগুলিতে। এটি কিছু নিরীক্ষার লগগুলিতে প্রদর্শিত হতে পারে তবে audit নিরীক্ষণ লগগুলি কেবল প্রশাসকদের দ্বারা অ্যাক্সেসযোগ্য হওয়া উচিত।

সংক্ষেপে একটি নির্বাহযোগ্য পরিবেশে প্রবাহিত পরিবেশটি বোঝানো হয় কোনও প্রক্রিয়াটির অভ্যন্তরীণ স্মৃতি হিসাবে ব্যক্তিগত বা কমপক্ষে ব্যক্তিগত হিসাবে (যা কিছু পরিস্থিতিতে সঠিক সুযোগ-সুবিধাগুলি সহ অন্য একটি প্রক্রিয়াও ডিবাগারের সাথে উদাহরণস্বরূপ অ্যাক্সেস করতে পারে এবং পারে এছাড়াও ডিস্কে ফেলে দেওয়া হবে)।

যেহেতু argv[]জনসাধারণের জ্ঞান, তাই একটি কমান্ড যা প্রত্যাশা করে যে এর কমান্ড লাইনে ডেটাটি গোপনীয় ছিল তা ডিজাইনের মাধ্যমে নষ্ট হয়ে গেছে।

সাধারণত, যে কমান্ডগুলিকে একটি গোপনীয়তা দেওয়া দরকার, আপনাকে পরিবেশের পরিবর্তনশীলের মতো এটি করার জন্য আপনাকে অন্য একটি ইন্টারফেস সরবরাহ করে। এই ক্ষেত্রে:

IPMI_PASSWORD=secret ipmitool -I lan -U admin...

অথবা স্ট্যান্ডিনের মতো ডেডিকেটেড ফাইল বর্ণনাকারীর মাধ্যমে:

echo secret | openssl rsa -passin stdin ...

( echoঅন্তর্নির্মিত হওয়ায় এটি এর ফলাফলের মধ্যে প্রদর্শিত হয় না ps)

অথবা একটি ফাইল যেমন এর .netrcজন্য ftpএবং কয়েকটি অন্যান্য কমান্ড বা

mysql --defaults-extra-file=/some/file/with/password ....

কিছু অ্যাপ্লিকেশন curl(এবং এটি এখানে @ মিউহও গ্রহণ করেছেন ) প্রাইভিংargv[] চোখ থেকে প্রাপ্ত পাসওয়ার্ডটি গোপন করার চেষ্টা করে (কিছু সিস্টেমে argv[]স্ট্রিংগুলি স্ট্রোম থাকা মেমরির অংশটি ওভাররাইট করে )। তবে এটি সত্যই সহায়তা করে না এবং সুরক্ষার একটি মিথ্যা প্রতিশ্রুতি দেয়। execve()এটি ওভাররাইটিংয়ের মধ্যে একটি উইন্ডো ছেড়ে দেয় যেখানে psএখনও গোপনীয়তা দেখাবে।

উদাহরণস্বরূপ, কোনও আক্রমণকারী যদি জানেন যে আপনি কোনও স্ক্রিপ্ট চালাচ্ছেন curl -u user:somesecret https://...(উদাহরণস্বরূপ ক্রোন জব করে), তাকে যা করতে হবে তা (অনেক) লাইব্রেরি ক্যাশে থেকে উচ্ছেদ করা হবে curl(উদাহরণস্বরূপ একটি চালিয়ে sh -c 'a=a;while :; do a=$a$a;done') এটির প্রারম্ভিক গতি কমিয়ে দেওয়ার জন্য এবং এমনকি until grep 'curl.*[-]u' /proc/*/cmdline; do :; doneআমার পরীক্ষাগুলিতে সেই পাসওয়ার্ডটি ধরতে খুব অদক্ষ করে নেওয়াও যথেষ্ট।

যদি আর্গুমেন্টগুলি কেবলমাত্র আপনি কমান্ডগুলিতে গোপনীয়করণ করতে পারেন তবে এখনও কিছু জিনিস আপনি চেষ্টা করতে পারেন।

লিনাক্সের পুরানো সংস্করণ সহ কয়েকটি সিস্টেমে স্ট্রিংগুলির প্রথম কয়েকটি বাইট (লিনাক্স ৪.১ এবং এর আগে ৪০৯6) argv[]অনুসন্ধান করা যেতে পারে।

সেখানে, আপনি করতে পারেন:

(exec -a "$(printf %-4096s cmd)" cmd "$secret")

এবং গোপনীয়তা লুকানো হবে কারণ এটি প্রথম 4096 বাইট পেরিয়ে গেছে। ৪.২ যেহেতু লিনাক্স এখন আর এই পদ্ধতিটি ব্যবহার করেছে তাদের অবশ্যই এখন আফসোস করতে হবে কারণ আরগের তালিকাটি আর ছাঁটাই করে না /proc/pid/cmdline। আরও মনে রাখবেন যে এটি psকোনও কমান্ড লাইনের অনেকগুলি বাইট (ফ্রিবিএসডি-তে যেখানে এটি 2048 এর মধ্যে সীমাবদ্ধ বলে মনে হয়) এর চেয়ে বেশি দেখাবে না কারণ এটি একই API এ psব্যবহার করতে পারে না আরও পেতে can't সিস্টেমগুলি যেখানে psনিয়মিত ব্যবহারকারীর সেই তথ্য পুনরুদ্ধার করার একমাত্র উপায় যেখানে এই পদ্ধতিটি বৈধ। (যেমন এটি যখন এপিআই সুবিধা প্রাপ্ত হয় এবং psএটি ব্যবহারের জন্য সেটগিড বা সেটুইড থাকে) তবে এখনও সেখানে সম্ভাব্য সম্ভাবনা নেই।

আর একটি উপায় হ'ল গোপনীয়তাটি পাস নাargv[] করে প্রোগ্রামটি কোডটি ইনজেক্ট করা (ব্যবহার gdbবা একটি $LD_PRELOADহ্যাক) main()এটি শুরুর আগে যেটি argv[]থেকে প্রাপ্ত গোপনীয়তা সন্নিবেশ করে execve()

সাথে LD_PRELOAD, একটি GNU সিস্টেমে অ-সেটুইড / সেটগিড গতিশীলভাবে সংযুক্ত এক্সিকিউটেবলের জন্য:

/* 
 * replace ***** with secret read from fd 9
 * gcc -Wall -fpic -shared -o inject_secret.so inject_secret.c -ldl 
 * LD_PRELOAD=/.../inject_secret.so cmd -p '*****' 9<<< secret
 */
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>

#define PLACEHOLDER "*****"
static char secret[1024];

int __libc_start_main(int (*main) (int, char**, char**),
                      int argc,
                      char **argv,
                      void (*init) (void),
                      void (*fini)(void),
                      void (*rtld_fini)(void),
                      void (*stack_end)){
    static int (*real_libc_start_main)() = NULL;
    int n;

    if (!real_libc_start_main) {
        real_libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
        if (!real_libc_start_main) abort();
    }

    n = read(9, secret, sizeof(secret));
    if (n > 0) {
      int i;

      if (secret[n - 1] == '\n') secret[--n] = '\0'; 
      for (i = 1; i < argc; i++)
        if (strcmp(argv[i], PLACEHOLDER) == 0)
          argv[i] = secret;
    }

    return real_libc_start_main(main, argc, argv, init, fini,
                                rtld_fini, stack_end);
}

তারপর:

$ gcc -Wall -fpic -shared -o inject_secret.so inject_secret.c -ldl
$ LD_PRELOAD=$PWD/inject_secret.so  ps '*****' 9<<< "-opid,args"
  PID COMMAND
 7659 /bin/zsh
 8828 ps *****

কোনও অবস্থাতেই সেখানে psপ্রদর্শিত হবে ps -opid,argsনা ( -opid,argsএই উদাহরণের গোপনীয়তা)। নোট করুন যে আমরা পয়েন্টারেরargv[] অ্যারের উপাদানগুলিকে প্রতিস্থাপন করছি , সেই পয়েন্টারগুলির দ্বারা নির্দেশিত স্ট্রিংগুলিকে ওভাররাইড না করে এটি কারণ আমাদের পরিবর্তনগুলি আউটপুটে প্রদর্শিত হয় না ।ps

সাথে gdb, এখনও অ-সেটুইড / সেটগিড গতিশীলভাবে সংযুক্ত এক্সিকিউটেবল এবং জিএনইউ সিস্টেমে:

tmp=$(mktemp) && cat << EOF > "$tmp" &&
break __libc_start_main
commands 1
set argv[1]="-opid,args"
continue
end
run
EOF

gdb -n --batch-silent --return-child-result -x "$tmp" --args ps '*****'
rm -f -- "$tmp"

তবুও gdb, একটি নন-জিএনইউ নির্দিষ্ট পদ্ধতি যা এক্সিকিউটেবলগুলিকে ডায়নামিকভাবে লিঙ্কযুক্ত বা ডিবাগ প্রতীক থাকতে পারে না এবং লিনাক্সে কমপক্ষে কার্যকর হওয়া কোনও ইএলএফের পক্ষে কাজ করা উচিত:

#! /bin/sh -
# gdb+sh polyglot script to replace "*****" arguments with the content
# of the SECRET environment variable *after* execve and before calling
# the executable's main() function.
#
# Usage: SECRET=somesecret cmd --password '*****'

if ':' - ':'
then
  # running in sh
  # retrieve the start address for the executable
  start=$(
    LC_ALL=C objdump -f -- "$(command -v -- "${1?}")" |
    sed -n 's/^start address //p'
  )
  [ -n "$start" ] || exit
  # re-exec ourself with gdb.
  exec gdb -n --batch-silent --return-child-result -iex "set \$start = $start" -x "$0" --args "$@"
  exit 1
fi
end
# running in gdb
break *$start
commands 1
  # The stack on startup contains:
  # argc argv[0]... argv[argc-1] 0 envp[0] envp[1]... 0 argv[] and envp[] strings
  set $argc = *((int*)$sp)
  set $argv = &((char**)$sp)[1]
  set $envp = &($argv[$argc+1])
  set $i = 0
  while $envp[$i]
    # look for an envp[] string starting with "SECRET=". We can't use strcmp()
    # here as there's no guarantee that the debugged executable has such
    # a function
    set $e = $envp[$i]
    if $e[0] == 'S' && \
       $e[1] == 'E' && \
       $e[2] == 'C' && \
       $e[3] == 'R' && \
       $e[4] == 'E' && \
       $e[5] == 'T' && \
       $e[6] == '='
      set $secret = &($e[7])
      # replace SECRET=xxx<NUL> with SECRE=<NUL>
      set $e[5] = '='
      set $e[6] = '\0'
      # not calling loop_break as that causes a SEGV with my version of gdb
    end
    set $i = $i + 1
  end
  if $secret
    # now looking for argv[] strings being "*****" and replace them with
    # the secret identified earlier
    set $i = 0
    while $i < $argc
      set $a = $argv[$i]
      if $a[0] == '*' && \
       $a[1] == '*' && \
       $a[2] == '*' && \
       $a[3] == '*' && \
       $a[4] == '*' && \
       $a[5] == '\0'
        set $argv[$i] = $secret
      end
      set $i = $i + 1
    end
  end
  # using "continue" as "detach" causes a SEGV with my version of gdb.
  continue
end
run

স্ট্যাটিকালি লিঙ্কযুক্ত এক্সিকিউটেবলের সাথে পরীক্ষা করা:

$ SECRET=/proc/self/cmdline ./replace_secret busybox cat '*****' | tr '\0' '\n'
/bin/busybox
cat
*****

যখন এক্সিকিউটেবল স্থিতিশীল হতে পারে, তখন গোপনীয়তা সংরক্ষণের জন্য আমাদের কাছে মেমরি বরাদ্দ করার কোনও নির্ভরযোগ্য উপায় নেই, সুতরাং আমাদের অন্য কোথাও থেকে গোপনীয়তাটি পেতে হবে যা ইতিমধ্যে প্রক্রিয়া স্মৃতিতে রয়েছে। এই কারণেই পরিবেশটি এখানে সুস্পষ্ট পছন্দ। প্রক্রিয়াটি কোনও কারণে তার পরিবেশ ডাম্প করার সিদ্ধান্ত নিয়েছে বা অবিশ্বস্ত অ্যাপ্লিকেশনগুলি চালিয়ে যাওয়ার সিদ্ধান্ত নেওয়ার SECRETজন্য প্রক্রিয়াটি (এটিকে পরিবর্তিত করে SECRE=) প্রক্রিয়ায় আমরা সেই env বারটিকেও আড়াল করি ।

এটি সোলারিস 11-তেও কাজ করে (প্রদত্ত জিডিবি এবং জিএনইউ বাইনুটিসগুলি ইনস্টল করা আছে (আপনার নাম পরিবর্তন করতে হতে objdumpপারে gobjdump))।

ফ্রিবিএসডি-তে (কমপক্ষে x86_64, আমি নিশ্চিত নই যে স্ট্যাকের প্রথম 24 বাইটগুলি (যা 16 হয় যখন gdb (8.0.1) ইন্টারেক্টিভ প্রস্তাব দিচ্ছে যে সেখানে স্ট্রাকের কোনও বাগ থাকতে পারে), সংজ্ঞা argcএবং argvসংজ্ঞাগুলি প্রতিস্থাপন করুন সঙ্গে:

set $argc = *((int*)($sp + 24))
set $argv = &((char**)$sp)[4]

( gdbঅন্যথায় সিস্টেমের সাথে আসা সংস্করণটি প্রাচীন হিসাবে আপনার প্যাকেজ / পোর্টও ইনস্টল করতে হতে পারে )।


পুনরায় (এখানে প্যারামিটার সম্প্রসারণের আশেপাশে নিখোঁজ উক্তিগুলি জুড়েছে): উদ্ধৃতিগুলি ব্যবহার না করে কী ভুল? আসলেই কি তফাত আছে?
ইউকশিমা হুকসে

@ ইউকাশিমাহক্সে, উদাহরণস্বরূপ দেখুন বাশ / পসিক্স শেলের একটি পরিবর্তনশীল এবং সেখানে লিঙ্কযুক্ত প্রশ্নগুলির একটি ভেরিয়েবলের উদ্ধৃতি ভুলে যাওয়ার সুরক্ষা সম্পর্কিত প্রভাবগুলি দেখুন ।
স্টাফেন চেজেলাস

3

আপনি কি করতে পারেন

 export SECRET=somesecretstuff

তারপরে, ধরে নিই যে ./programআপনি সি তে আপনার লিখছেন (বা অন্য কেউ করেন, এবং এটি আপনার জন্য পরিবর্তন বা উন্নতি করতে পারে), সেই প্রোগ্রামে জেন্তেভ (3) ব্যবহার করুন , সম্ভবত

char* secret= getenv("SECRET");

এবং export আপনি ঠিক ./programএকই শেল চালানো পরে । বা পরিবেশের পরিবর্তনশীল নাম এটিতে প্রেরণ করা যেতে পারে ( ./program --secret-var=SECRETইত্যাদি চালিয়ে ...)

psআপনার গোপনীয়তা সম্পর্কে বলবে না, তবে প্রোক (5) এখনও প্রচুর তথ্য দিতে পারে (কমপক্ষে একই ব্যবহারকারীর অন্যান্য প্রক্রিয়াতে)।

আরও দেখুন এই সাহায্যের প্রোগ্রাম আর্গুমেন্ট ক্ষণস্থায়ী একটি ভাল উপায় ডিজাইন।

গ্লোব্বিং এবং শেলের ভূমিকা সম্পর্কে আরও ভাল ব্যাখ্যার জন্য এই উত্তরটি দেখুন ।

সম্ভবত আপনার সরল প্রোগ্রাম আর্গুমেন্টের চেয়ে programডেটা পাওয়ার (বা আন্তরিক প্রক্রিয়া যোগাযোগ আরও বিজ্ঞতার সাথে ব্যবহার করার) জন্য অন্য কিছু উপায় রয়েছে (এটি অবশ্যই হওয়া উচিত, যদি এটি সংবেদনশীল তথ্য প্রক্রিয়া করার উদ্দেশ্যে থাকে)। এর ডকুমেন্টেশন পড়ুন। অথবা সম্ভবত আপনি সেই প্রোগ্রামটি অপব্যবহার করছেন (যা গোপন তথ্য প্রক্রিয়াকরণের উদ্দেশ্যে নয়)।

গোপন তথ্য গোপন করা সত্যিই কঠিন। প্রোগ্রাম আর্গুমেন্ট মাধ্যমে এটি পাস না যথেষ্ট নয়।


5
এটা তোলে প্রশ্নটি থেকে চমত্কার পরিষ্কার যে সে এমনকি নেই সোর্স কোড জন্য ./program, তাই এই উত্তর প্রথমার্ধে প্রাসঙ্গিক হবে বলে মনে হচ্ছে না।
পাইপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.