690 likes | 829 Vues
資安產學個案研討 許 富 皓 資 訊 工 程 學 系 國 立 中 央 大 學. SQL Injection [ SK ]. SQL Injection Version of Hello World. Let’s surf the Internet for fun. Wow! Be a member for free. What is SQL Injection?. Many web pages take parameters from web users , and make SQL query to the database .
E N D
資安產學個案研討 許 富 皓 資 訊 工 程 學 系 國 立 中 央 大 學
SQL Injection Version of Hello World Let’s surf the Internet for fun. Wow! Be a member for free.
What is SQL Injection? • Many web pages take parameters from web users, and make SQL query to the database. • Take for instance when a user login a web page, the web page accepts that user name and password and makes SQL query to the database to check if the user has valid name and password. • With SQL Injection, it is possible for us to send crafted user name and/or password field that will change the SQL query and thus grant us something else.
SQL Injection Attack Channels • SQL injection is one type of web hacking that require nothing but port 80 and it might just work even if the admin is patch-happy. • It attacks on the web application (like ASP, JSP, PHP, CGI, etc) itself rather than on the web server or services running in the OS.
What You Should Look for? • Try to look for pages that allow you to submit data, i.e: • login page, • search page, • feedback, etc. • Sometimes, HTML pages use POST command to send parameters to another ASP page. Therefore, you may not see the parameters in the URL. However, you can check the source code of the HTML, and look for "FORM" tag in the HTML code. You may find something like this in some HTML codes: <FORM action=Search/search.asp method=post><input type=hidden name=A value=C></FORM>Everything between the <FORM> and </FORM> have potential parameters that might be useful (exploit wise).
What If You Can't Find Any Page That Takes Input? • You should look for pages like ASP, JSP, CGI,or PHP web pages. Try to look especially for URL that takes parameters, like:http://duck/index.asp?id=10
How Do You Test If It Is Vulnerable? • Start with a single quote trick. Input something like:hi' or 1=1-- into login, or password, or even in the URL. • Example:- Login: hi' or 1=1---Pass: hi' or 1=1---http://duck/index.asp?id=hi' or 1=1— • If luck is on your side, you will get login without any login name or password.
Hidden Field • If you must do this with a hidden field, just download the source HTML from the site, save it in your hard disk, modify the URL and hidden field accordingly. • Example:<FORM action=http://duck/Search/search.asp method=post><input type=hidden name=A value="hi' or 1=1--"></FORM>
Web Application Input and Its Corresponding SQL Query • Take an asp page that will link you to another page with the following URL:http://duck/index.asp?category=foodIn the URL, 'category' is the variable name, and 'food' is the value assigned to the variable. In order to do that, an ASP might contain the following code:v_cat = request("category")sqlstr="SELECT * FROM product WHERE PCategory='" & v_cat & "'"set rs=conn.execute(sqlstr)As we can see, our variable will be wrapped into v_cat and thus the SQL statement should become:SELECT * FROM product WHERE PCategory='food'The query should return a result set containing one or more rows that match the WHERE condition, in this case, 'food'.
Why' or 1=1--? • Now, assume that we change the URL into something like this:http://duck/index.asp?category=food' or 1=1--Now, our variable v_cat equals to "food' or 1=1-- ", if we substitute this in the SQL query, we will have: SELECT * FROM product WHERE PCategory='food' or 1=1--'The query now should now select everything from the product table regardless if PCategory is equal to 'food' or not. • A double dash "--" tell MS SQL server ignore the rest of the query, which will get rid of the last hanging single quote ('). • Sometimes, it may be possible to replace double dash with single hash "#".
Other Crafted Input (1) • However, if it is not an SQL server, or you simply cannot ignore the rest of the query, you also may try' or 'a'='aThe SQL query will now become: SELECT * FROM product WHERE PCategory='food' or 'a'='a'It should return the same result.
Other Crafted Input (2) • Depending on the actual SQL query, you may have to try some of these possibilities:' or 1=1--" or 1=1--or 1=1--' or 'a'='a" or "a"="a') or ('a'='a
Attack Types • Buffer Overflow Attacks: • Stack Smashing attacks • Return-into-libc attacks • Heap overflow attacks • Function pointer attacks • .dtors overflow attacks. • setjump/longjump buffer overflow attacks. • Format string attacks: • Integer overflow and integer sign attacks
Why Buffer Overflow Attacks Are So Dangerous? • Easy to launch: • Attackers can launch a buffer overflow attack by just sending a craft string to their targets to complete such kind of attacks. • Plenty of targets: • Plenty of programs have this kind of vulnerabilities. • Cause great damage: • Usually the end result of a buffer overflow attack is the attacker’s gaining the root privilege of the attacked host. • Internet worms proliferate through buffer overflow attacks.
Principle of Stack Smashing Attacks • Overwrite control transfer structures, such as return addresses or function pointers, to redirect program execution flow to desired code. • Attack strings carry both code and address(es) of the code entry point.
Explanation of BOAs (1) G(int a) { H(3); add_g: } H( int b) { char c[100]; int i; while((c[i++]=getch())!=EOF) { } } G’s stack frame b return address add_g H’s stack frame address of G’s frame point C[99] 0xabc Z Y X 0xabb Input String: xyz C[0] 0xaba
Explanation of BOAs (2) Length=108 bytes G(int a) { H(3); add_g: } H( int b) { char c[100]; int i; while((c[i++]=getch())!=EOF) { } } Attack String: xxInjected Codexy0xabc b return address add_g addrress oxabc H’s stack frame address of G’s frame point y C[99] x Injected Code 0xabc 0xabb x x C[0] 0xaba
Injected Code: • The attacked programs usually have root privilege; therefore, the injected code is executed with root privilege. • The injected code is already in machine instruction form; therefore, a CPU can directly execute it. • However the above fact also means that the injected code must match the CPU type of the attacked host. • Usually the injected code will fork a shell; hence, after an attack, an attacker could have a root shell.
Injected Code of Remote BOAs • In order to be able to interact with the newly forked root shell, the injected code usually need to execute the following two steps: • Open a socket. • Redirect standard input and output of the newly forked root shell to the socket.
Example of Injected Code for X86 Architecture : Shell Code • char shellcode[] ="\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
Two Factors for A Successful Buffer Overflow-style Attack(1) • A successful buffer overflow-style attack should be able to overflow the right place (e.g. the place to hold a return address with the correct value (e.g. the address of injected code entry point)).
Two Factors for A Successful Buffer Overflow-style Attack(2) return address buffer where the overflow start injected code address of injected code entry point. offset between the beginning of the overflowed buffer and the overflow target. The offset and the entry point address are non-predicable. They can not decided by just looking the source code or local binary code.
Non-predictable Offset • For performance concerns, most compilers don’t allocate memory for local variables in the order they appear in the source code, sometimes some space may be inserted between them. (Source Code doesn’t help) • Different compiler/OS uses different allocation strategy. (Local binaries don’t help) • Address obfuscation insert random number of space between local variables and return address. (Super good luck may help)
function main()’s stack frame Non-predicable Entry Point Address webserver –a –b security [fhsu@ecsl]# system data 0xbfffffff environment variables argument strings command line arguments and environment variables env pointers argv pointers argc
Strategies Used by Attackers to Increase Their Success Chance • Repeat address patterns. • Insert NOP (0x90) operations before the entry point of injected code. • One-byte long instructions that doesn’t change the semantic of an injected code could replace NOP.
Exploit Code Web Sites • Exploit World • MILWORM • Metasploit • Securiteam
An Exploit Code Generation Program • This program uses the following three loop to generate the attack string which contains the shell code. for(i=0;i<sizeof(buff);i+=4) *(ptr++)=jump; for(i=0;i<sizeof(buff)-200-strlen(evil);i++) buff[i]=0x90; for(j=0;j<strlen(evil);j++) buff[i++]=evil[j];
Return-into-libc Attacks • A mutation of buffer overflow attacks. • Utilize code already resided in the attacked programs’ address space, such as libc functions. • Attack strings carry entry point address(es) of a desired libc function, new frame point address and parameters to the function.
How Parameters and Local Variables Are Represented in an Object File? abc: function prologue *(%ebp-4)=*(%ebp+8) function epilogue abc(int aa) {int bb; bb=aa; : : } aa return address previous frame point ebp a C function equivalent assembly code P.S.: function prologueand function epilogueare added by a compiler bb
A Way to Change the Parameters and Local Variables of a Function. • A parameter or a local variable in an object file is represented through its offset between the position pointed by %ebp and its own position. • Therefore, the value of the %ebp register decides where a function to get its parameters and local variables. • In other words, if an attacker can change the %ebp of a function, then she/he can also change the function’s parameters and local variables.
Function Prologue and Epilogue #include <stdio.h> int add_three_items(int a, int b, int c) { int d; d=a+b+c; return d; } add_three_items: pushl %ebp movl %esp, %ebp subl $4, %esp movl 12(%ebp), %eax addl 8(%ebp), %eax addl 16(%ebp), %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax leave ret 3 function prologue 4 function epilogue leave=movl %ebp,%esp popl %ebp P.S.: the assembly code in this and next slide are created by a Linux C compiler.
Function Calls main() { int a, b,c,f; extern int add_three_items(); a=1; b=2; c=3; f=add_three_items(a,b,c); } main: pushl %ebp movl %esp, %ebp subl $24, %esp andl $-16, %esp movl $0, %eax subl %eax, %esp movl $1, -4(%ebp) movl $2, -8(%ebp) movl $3, -12(%ebp) subl $4, %esp pushl -12(%ebp) pushl -8(%ebp) pushl -4(%ebp) call add_three_items addl $16, %esp movl %eax, -16(%ebp) leave ret 1 2 5 leave=movl %ebp,%esp popl %ebp
Code Created by a Free BSD C Compiler function: pushl %ebp movl %esp, %ebp subl $40, %esp leave ret main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp pushl $3 pushl $2 pushl $1 call function addl $12, %esp leave ret void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } main(int argc, char *argv[]) { int a, b; function(1,2,3); } gcc -S test.c;
bp sp high ret addr (EIP) function: pushl %ebp movl %esp, %ebp subl $40, %esp leave ret main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp pushl $3 pushl $2 pushl $1 call function addl $12, %esp leave ret %ebp … $3 $2 $1 ret addr (EIP) %ebp … leave = movl %ebp, %esp popl %ebp heap bss low
Explanation of Return-into-libc G(int a) { H(3); add_g: } H( int b) { char c[10]; overflow occurs here } parameter 1, e.g. pointer to /bin/sh b any value return address add_g abc(), e.g. system() H’s stack frame address of G’s frame point any value ebp C[9] esp C[0] abc: pushl %ebp movl %esp,%ebp
Explanation of Return-into-libc G(int a) { H(3); add_g: } H( int b) { char c[10]; overflow occurs here } parameter 1, e.g. pointer to /bin/sh b any value return address add_g abc(), e.g. system() H’s stack frame address of G’s frame point any value esp ebp C[9] movl %ebp,%esp (an instruction in function epilogue) C[0] abc: pushl %ebp movl %esp,%ebp
Explanation of Return-into-libc G(int a) { H(3); add_g: } H( int b) { char c[10]; overflow occurs here } parameter 1, e.g. pointer to /bin/sh b any value return address add_g abc(), e.g. system() esp H’s stack frame address of G’s frame point (popl %ebp) any value ebp any value C[9] C[0] abc: pushl %ebp movl %esp,%ebp
Explanation of Return-into-libc G(int a) { H(3); add_g: } H( int b) { char c[10]; overflow occurs here } parameter 1, e.g. pointer to /bin/sh b esp any value return address add_g (ret) abc(), e.g. system() H’s stack frame address of G’s frame point any value ebp any value C[9] C[0] abc: pushl %ebp movl %esp,%ebp
Explanation of Return-into-libc After the following two instruction in function system()’s function prologue is executed pushl %ebp movl %esp, %ebp, the position of %esp and %ebp is shown in the figure. G(int a) { H(3); add_g: } H( int b) { char c[10]; overflow occurs here } parameter 1, e.g. pointer to /bin/sh b any value return address add_g ebp any value esp H’s stack frame address of G’s frame point any value C[9] C[0] abc: pushl %ebp movl %esp,%ebp
Properties of Return-into-libc Attacks • The exploit strings don’t need to contain executable code.
Principle of Heap/Data/BSS Overflow Attacks • Similarly to stack smashing attacks, attackers overflow a sensitive data structure by providing a buffer which is adjacent to the sensitive data structure more data than the buffer can store; hence, to overflow the sensitive data structure. • The sensitive data structure may contain: • A function pointer • A pointer to a string • … and so on. • Both the buffer and the sensitive data structure may locate at the heap, or data, or bss section.
Heap and Data/BSS Sections • The heap is an area in memory that is dynamically allocated by the application by using a system call, such as malloc() . • On most systems, the heap grows up (towards higher addresses). • The data section is initialized at program loading-time. • The bsssection contains uninitialized data, and is allocated atrun-time. • Until it is written to, it remains zeroed (or at least from the application's point-of-view).
Heap Overflow Example #define BUFSIZE 16 int main() { int i=0; char *buf1 = (char *)malloc(BUFSIZE); char *buf2 = (char *)malloc(BUFSIZE); : while((*(buf1+i)=getchar())!=EOF) i++; : }