رمزگشایی GPG رو-هوا
این پروژه صددرصد با LLM نوشته شده و از نظر امنیتی قابل اتکا نیست پس Don't try at home. پیوند مخزن: https://github.com/MirS0bhan/gpg-intercept
مشکل
برای سرویس های خودم درحال ساختن گواهینامه(Certificate) های TLS خودامضا بودم، این فرایند چندین پرونده مختلف ایجاد میکنه که مهم ترینشون کلید خصوصی CA هست که به واسطه اون گواهی های امضا میشن. از نظر امنیتی خطرناک حساب میشه اگر گواهی CA رو داخل مرورگر و توزیع یا هر سیستمعاملی نصب کنید و کلید خصوصیش مراقبت نکنید. که این منجر میشه attacker با استفاده از اون کلید گواهی های خودشو امضا کنه و توی شبکه شما بتونه خودشو جای سرویس ها جا بزنه و گواهی خودشو بفرست توی ارتباط TLS و مرورگر یا توزیع شما هیچ خطایی نشون نده. روش های مختلفی برای رمزنگاری است از جمله GPG یا خیلی ساده تر age. مشکلی (نمیشه واقعا اسمشو مشکل گذاشت ولی ما میخوایم یه مسیر دیگهای بریم) که هست اینه من نمیخوام هر دفعه دستور gpg -d رو وارد کنم تا پرونده کلید خصوصی رو رمزگشایی کنم و سپس استفاده کنم ازش و بعدش پاک کنم، مسیر بهتر اینه هر دستوری که میخواد اون پرونده رو بخونه توی حافظه رمزگشایی بشه و هیچوقت کلید خام روی دیسک قابل دسترس نباشه. بعد از مصاحبت ها با کلاد نتیجه این شد که ما میتونیم با استفاده از LD_PRELOAD بیایم و فانکشن هایی توی libc برای خوندن فایل استفاده میشن رو wrap کنیم تا اون رفتاری که مد نظرمون هست اعمال میشه و همین اتفاق افتاد. کلاد spec کدی که لازم بود رو نوشت و اون شد ورودی کوپایلت و کل کد رو نوشت و در نهایت با دیباگ کلاد کار کرد. نتیجه این شد که هر برنامه که به صورت لایبری های cش داینامیک لینک شده باشه و اون برنامه فانکشن های open و مشابهش رو call کنه درخواست اول به فانکشنی که ما نوشتیم میره و به صورت جداگانه چک میکنه آیا پرونده ما شبیه پروندهای هست که gpg رمزنگاری کرده یا نه اگر نبود همونو پاس میده به دستور open اصلی libc و همه چیز عین قبل کار میکنه، ولاغیر شروع میکنه با gpg رمزگشایی کنه که درنتیجه یک صفحه popup میشه تا رمز اون کلید رو از شما بپرسه (این فرایند توسط gpg-agent انجام میشه) و بعد از رمزگشایی پرونده توی حافظه اونو به عنوان محتوای اصلی فایل برمیگردونه به کسی که کال کرده بود.
$ cat ca.key
[encrypted cipher]
LD_PRELOAD=~/Projects/gpg-intercept/gpgintercept.so cat ca.key
-----BEGIN ENCRYPTED PRIVATE KEY-----
[private key content...]