什么是SQL注入?:所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

MySQL基础语法:MySQL 教程_w3cschool


浏览器打开sqli.com/sqli-1.php,其源码如下:

代码已经写了注释,如果没有给这个页面传参数,则默认传一个id参数,它的值为1。可以看到,在13行,获取到用户传过来的参数后,直接进入了SQL语句,带进了查询语句,没有任何其他操作,很明显的存在SQL注入。在sql语句中,new被反引号包起来了,关于反引号的作用,请参考预备知识中的“mysql创建表时反引号的作用”。

先在URL后面加一个单引号,可以看到页面报错了,这个警告的意思是:mysql_fetch_array()这个函数第一个参数期望的参数类型是一个资源集,但是给的是一个布尔值,出现该警告的位置在代码的第15行。

查看代码,发现它的第一个参数$result这个参数的值来自第14行,它是mysql_query执行后的返回值。

前面的语句在MySQL里执行出错了,于是返回了false,这说明我们传进去的参数1’破坏了SQL语句,我们可以稍微修改下代码,在第14行后面输出一下当前执行的sql语句。修改后的代码如下:

我们可以直接复制该语句到MySQL中去执行。由于数据库编码是utf8的,直接在mysql客户端中进行查询,中文会显示乱码,所以可以到phpmyadmin中来执行这个sql语句。

访问http://localhost/phpmyadmin/,如果需要输入密码,账号输入root,密码为空,然后点击执行登录。

复制刚才输出的语句:select * from `new` where id = 1',然后点击执行。

这说明我们输入的参数被mysql服务器当作SQL命令执行了!再来看下通过and 1=1和and 1=2来判断网页是否存在SQL注入的原理。首先传个1 and 1=1,页面显示正常,而且最终执行的SQL语句是: select * from `new` where id = 1 and 1=1

再次尝试1 and 1=2,页面除了输出最终执行的SQL页面,没有其他任何输出。

其实这里SQL语句执行并没有出错,问题出在and 1=2上,再来一下这条语句,它从new这个表里面查询数据,但是有限制条件,where指查询满足后面的数据,也就是说需要查找id = 1的数据,并且需要 1=2,但是1=2这是用于不可能满足的。所以,这个语句被数据库准确无误地执行了,但是它并没有找到符合条件的数据,所以没有任何数据输出。而前面加 1 and 1=1能正常返回数据,是因为1=1这个永远为真,所以这个条件可以说是跟没加一样。

通过and 1=1 、 and 1=2来判断页面是否存在注入,是因为我们修改了原本的SQL语句逻辑,当添加and 1=1的时候,这个条件永远成立,所以页面一定返回正常(需要该页面存在注入),但是当添加and 1=2的时候,这个条件永远不成立,所以如果该页面存在注入,必然不会返回任何数据。所以就会说,如果添加and 1=1页面返回正常,添加and 1=2页面返回不正常或者错误,就说明页面存在SQL注入。当然这只能大概判断,而不是说明该页面一定存在注入,其他情况在后面的实验里说。

那万能密码又是怎么回事呢? 网上找到的万能密码都是类似’ or 1=1这种,为什么输入这个字符串就可以绕过登录了呢? 我们也用or 1=1试试,看在这个页面提交这个值是什么效果。

访问http://sqli.com/sqli-1.php?id=1 or 1=1

发现居然输出了多条记录,这里其实输出了new表中所有的数据,所有的建表语句都在sql.sql文件中,可以打开看下sqli数据库中有哪些表,有什么内容。

它这里只要满足id =1 或者1=1任意一个条件,而1=1永远为真,所以返回了所有的数据,其效果与select * from `new`一样。


但是如果仅仅只是读取new这个表里面的数据,对我们来说,其实意义不大,因为即使不存在注入,我们也可以增加ID的值来查看其中所有的信息。比如访问http://sqli.com/sqli-1.php?id=2 可以查看id=2的内容。

我们希望的是能够通过注入,获取一些网站管理员不希望我们知道的数据,比如管理员的账号密码。

在本页面的源码中,注入点在where后面,也就说,从哪个表中查询什么数据是写死的,那么怎么才能通过注入获取其他表中的内容呢? 比如获取user表中的数据。

通过union操作符就可以达到我们的目的,union可以合并两条或者多条select语句的查询结果,它的语法如下:

Select column-1,column-2,…,column-N from table-1 union select column-1,column-2,…,column-N from table-2

它的返回值是两个select语句查询结果组成的表。我们可以通过在第一个查询后面注入一个union运算符,并添加另外一个任意查询,就可以读取到数据库中用户可以访问的任何表。但是,使用union有一些限制:

1.两个查询返回的列数必须型相同。

2.两个select语句对应列所返回的数据类型必须是相同或者是兼容的。

当前的两个select 他们查询的列的个数必须一致,如果第一个select查询了5列,则第二个select也必须查询5列。

如:select title, content from new union select username, password from user;

像上面的查询,列数相同,会返回这2个查询的结果集。

来到phpmyadmin中验证一下,如图:

重点关注怎么知道查询中列的数量,代码中,写的是select * from `new`,直接在代码中看不出来new这个表中有多少列,而需要去查看建表语句,而在实际应用中,除非是开源的CMS,否则你不可能准确知道它查询了多少列,这就需要我们想个办法来获取当前查询的列数。

一个简单的办法是通过order by 子句来确定。Order by 是根据指定的列名进行排序。

Order by 子句可以接受一个列名作为参数,也可以接受一个简单的、能表示特定列的数字,所以可以通过增大order by 子句中代表列的数字来识别查询中的列数。

来到phpmyadmin测试。执行show create table new来查看建表语句

可以看到这个表有3列,然后来测试用order by子句来测试列数量,从1开始,每次查询加1,加到报错为止,如:

1的时候正常,继续增加该值。到4的时候,发现执行出错。

因为这里一共只有3列,但是你要根据第4列来进行排序,当然就会报错了。

再测试一个语句,把* 改成title, content。还是从1开始测试。结果如下:

select title, content from new order by 1 ,结果正常。

select title, content from new order by 3 ,报错。因为我们这里只查询了2列。

现在就来注入页面进行测试。

访问http://sqli.com/sqli-1.php?id=1 order by 1,页面正常。

依次增加order by 子句后面的值,直到4的时候,页面报错。

所以我们可以得出结论,在这个查询中,一共查询了3列,因为4的时候报错了。

然后就可以通过union 来进行查询user表中的数据啦。

根据union的语法,构造注入语句,通过前面的测试已经知道这个查询一共查询了3列,在符合union操作符的前提下,可以构造如下语句:

http://sqli.com/sqli-1.php?id=1 union select null, username, password from user

这样就获取了user表中所有的用户名和密码。

如果你写的网站存在注入,别人很容易就能通过SQL注入拿到管理员账号密码,那么网站就很容易被人篡改,并且导致信息泄露。


这样就获取了user表中所有的用户名和密码。

如果你写的网站存在注入,别人很容易就能通过SQL注入拿到管理员账号密码,那么网站就很容易被人篡改,并且导致信息泄露。

这就需要了解mysql数据库的information_schema 这个数据库了。

构造出获取所有数据库的语句,为:

http://sqli.com/sqli-1.php?id=1 union select 1,schema_name,3 from information_schema.schemata

可以看到返回了所有的数据库名:

其中schema_name 和 数字3的位置可以互换,没有什么影响,因为这里只需要有一个位置输出了就行,其中的数字1和3 可以被其他数字或者字符或者NULL代替,用字符代替的时候,记得用双引号或者单引号引上。虽然1和3可以被代替,但是不能缺少,因为必须要保持3列union才能正确执行。

这里后面的from 为什么是information_schema.schemata而不是schemata呢?

因为在当前执行SQL语句的环境中,它的默认是库是sqli,如果我们要跨库查询,则需要在表名前加上库名,如果不加上库名,则表示在sqli这个数据库的schemata表中查询,由于sqli这个数据库不存在schemata表,所以会报错,如下图:

如果我们输出mysql 的报错信息,就可以看到很明显的提示。

修改sqli-1.php源文件,在执行sql语句的下面加入如下代码:

if(!$result){

die(mysql_error());

}

再次访问上述链接:

提示表sqli.schemata 不存在。

通过前面的注入语句,我们已经获取了所有的数据库库名

在实验步骤二中,我们已经获取了sqli数据库user表中的数据,这次换一个,改成mysql。mysql这个数据库保存了mysql的账号密码信息,在注入的时候,可以读取该表中的数据来读取mysql账号密码。

现在就通过注入来获取mysql的账号和密码。

首先查看mysql这个数据库中有哪些表。构造如下语句:

1 union select 1, table_name,3 from information_schema.tables where table_schema='mysql'

这个表中保存了mysql服务器的账号和密码的hash值。然后构造语句获取该表中的所有列名。构造语句为:

1 union select 1, column_name, 3 from information_schema.columns where table_name ='user' and table_schema='mysql'

访问后返回该表中所有的列名。

存在User字段和Password字段,User字段保存了MySQL服务器的用户名,Password字段保存的是用户的Hash值。

由于在这里有2个位置可以输出,所以我们可以一次查询用户的账号和密码。

构造语句如下:

1 union select 1, User, Password from mysql.user

发现页面只有输出root。进入phpmyadmin确认一下。


SQL注入漏洞-SQL注入原理与实践相关推荐

  1. 【愚公系列】2023年05月 网络安全高级班 065.WEB渗透与安全(SQL注入漏洞-手工注入)

    文章目录 前言 一.SQL注入漏洞-手工注入 1.错误注入 2.布尔注入 2.1 通过`'or 1=1 --` 注入 2.2 通过`admin'or 1=1 --` 注入 3.联合注入 3.1 查看u ...

  2. SQL注入漏洞简介、原理及防护

    目录 1.SQL注入漏洞简介 2.SQL注入漏洞原理 3.SQL注入的分类 4.注入方法 5.SQL注入危害 6.SQL注入防护措施 1.SQL注入漏洞简介 SQL注入漏洞是Web层面最高位的漏洞之一 ...

  3. 注入漏洞-sql注入

     注入漏洞 注入漏洞 1 SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行指定的SQL语句.具体来说,它是利用现有应用程序, ...

  4. SQL注入漏洞-GET注入

    SQL 注入是一种攻击方式,在这种攻击方式中,恶意代码被插入到字符串中,然后将该字符串传递到 SQL Server 的实例以进行分析和执行.任何构成 SQL 语句的过程都应进行注入漏洞检查,因为 SQ ...

  5. 检测到目标url存在框架注入漏洞_HOST注入攻击剖析

    关于网站的渗透测试可能师傅们都有自己一套思路,有个共同点就是目标网站基本属于全静态页面,几乎很少存在动态参数这时意味着客户端无法通过提交参数形式进行测试,理论上也规避掉了许多风险.既然无法从参数层面进 ...

  6. 深入探究宽字节注入漏洞与修补原理

    通俗 在GBK编码时,mysql会认为两个字符是一个汉字(在前一个字节的ascii码大于128的情况下).而经过转义之后的单引号'会变为\',即%5c%27.构造id=1%df%27%23 ,在经过转 ...

  7. V5shop漏洞,V5shop 0day,V5shop注入漏洞,v5shop注入攻击

    漏洞危害:高危 一.漏洞文件:cart.aspx 搜索关键词:inurl:scoreindex.aspx exp : /cart.aspx?act=buy&id=1 and (Select T ...

  8. WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案

    对web安全方面的知识非常薄弱,这篇文章把Xss跨站攻击和sql注入的相关知识整理了下,希望大家多多提意见. 对于防止sql注入发生,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避 ...

  9. 【转】基于SQL的Web系统安全防范——SQL注入漏洞

    攻击研究及防范措施 SQL-Based Web System Security--Structured Query Language InjectionLeak Attack Study And De ...

最新文章

  1. 增强for循环_增强for循环实际用法
  2. Data Binding Library数据绑定框架
  3. Vue Vuex todo举例
  4. Spring Boot中使用Spring Security进行安全控制
  5. C语言_选择结构的程序设计
  6. jquery width,height,innerwidth,innerheight,outerwidth,outerheight方法
  7. Sendmail with Attachment script
  8. 前端下载音频的两种处理方式
  9. spacedesk安卓_【图吧小白教程】安卓平板改数位板
  10. 【沃顿商学院学习笔记】管理学——06腐败带来的间接成本和全球制裁状况Indirect Costs and Sanction
  11. RGB565和RGB888的转换
  12. 《Android项目实战-博学谷》应用图标欢迎界面
  13. C语言semaphore头文件,C语言再学习 -- 常用头文件和函数
  14. 条码枪扫码时,只能在文本框录入一位字符的问题
  15. MLX90614驱动,功能简介以及PEC校验
  16. python苹果支付(服务端)自动订阅版
  17. 【Python网络爬虫】爬虫常见加密解密算法
  18. 青年论坛:谈判的情感力量
  19. 3108 小明爱换钱
  20. concurrent.futures --- 启动并行任务(线程池)

热门文章

  1. php截断,php include 路径截断漏洞的利用
  2. 记在2019,winter is coming
  3. RISCV学习笔记7.8(开源虚拟机篇)--AlmaLinux虚拟机安装modelsim
  4. 如何区分电梯卡为id卡ic卡_UID卡是什么?和IC卡、ID卡有什么区别?
  5. 超兔指纹浏览器(TO12345)是什么?
  6. MATLAB 画三维长方体 介绍+代码
  7. 年末了,是该总结一波了,冲鸭2021
  8. LC3编码开源代码测试
  9. Photoshop辅助线和标尺的技巧
  10. R语言中igraph包的使用(邻接矩阵)