ToB企服应用市场:ToB评测及商务社交产业平台

标题: 关于sqlmap中--os-shell如何getshell的源码分析 [打印本页]

作者: 天空闲话    时间: 2024-11-24 01:12
标题: 关于sqlmap中--os-shell如何getshell的源码分析
目录

前言

最近详细看了@v1ll4n师傅写的几篇关于sqlmap源码分析的文章(sqlmap内核分析)收获颇多。借此机会在这里记录一下我较感兴趣的sqlmap中getshell相关部门的分析,就简单从源码的角度看看sqlmap是如何通过--os-shell一键getshell的。
mysql数据库注入getshell

先抛开sqlmap不谈,想要通过数据库getshell大的条件条件就是有权限而且知道相关路径,这里以最为熟知的mysql数据库为例。
使用条件:
以上这三个条件缺一不可:
第一,secure_file_priv是MySQL数据库中的一个系统变量,用于限制数据导入和导出操作。如果将secure_file_priv设置为一个特定的目录路径,则数据库中进行文件导入和导出操作时就只能对这个目录进行操作;如果设置为NULL,则表示禁止文件的导入和导出操作;如果设置为空(不是NULL)则会允许相对自由的文件操作,没有限制。
不同的系统和安装方式导致secure_file_priv的默认值也会有差异。通常情况为NULL,但有的也会指定一个默认的目录如下。

这个参数是不能通过sql语句直接修改的,因为它是一个只读参数。如果想要修改,则只能通过修改配置文件(windows下为my.ini,linux下为my.cnf),然后再通过重启mysql服务的方式来使它生效。
第二,知道网站的绝对路径。如果不知道绝对路径,那么菜刀这类的webshell管理工具就无法毗连。
第三,具有文件的写权限。如果网站目录下面不允许写文件,那么即使是知道网站的绝对路径也没有太大的使用价值。
接下来以linux环境(ubuntu22.04/mysql5.7.42)为例复现一下,这里起首把secure_file_priv的值改为空,为后面写文件提供条件。

常规的写shell方式大概如下:使用union连合查询,再共同select ... into outfile/dumpfile ...语句。
  1. union select '<?php eval($_POST[a]);?>' into outfile '/var/www/html/test.php';
  2. union select '<?php eval($_POST[a]);?>' into dumpfile '/var/www/html/test.php';
复制代码
尝试了一下写文件,报错提示没有权限。

意料之中,因为正常情况下我们其实并不确定mysql是否有权限在我们指定的var/www/html目录下写文件。
办理文件写入权限的问题:
尝试把/var/www/html目录权限改为777,没成功。修改文件的属主等,均没成功 。。。
折腾了很久,最终找到了办理方法:https://stackoverflow.com/questions/36391551/error-1-hy000-cant-create-write-to-file-errcode-13-permission-denied

原因:如果mysqld处于逼迫模式,那么AppArmor就会限制进程对资源的访问权限,AppArmor和SELinux类似,也是一个Linux系统下的逼迫访问控制安全机制。
按照上图给出的办理方法,编辑/etc/apparmor.d/usr.sbin.mysqld文件,在文件底部的位置添加对/var/www/html目录的读写控制。

修改完后,重新加载AppArmor,这次写入成功了。


尝试--os-shell也可以成功getshell。

通过上面一系列的操作,其实可以看到,想要直接通过mysql数据库写shell的方式getshell是比较困难的。在现实环境中,这三个条件几乎不可能同时完全满意。
但是没关系!学习,学习--os-shell getshell的代码实现原理这并不困难o( ̄▽ ̄)o~
接下来进入正题,打开PyCharm看看源码。
源码分析

仔细观察上面使用--os-shell下令输出的信息,可以发现它在网站目录下面写了两个php文件。你可能会和我有同样的疑问,为什么要写两个文件?它们都是什么,又什么作用?为了解释这些疑问,看sqlmap的源码会有找到一个比较清楚的答案。
关于sqlmap的基本流程分析这里不做介绍了,可以参考@v1ll4n师傅写的:https://www.anquanke.com/post/id/159260
这里只针对--os-shell这部门功能的源码进行简要的分析(sqlmap版本1.8#stable)。
有关--os-shell的处理函数被定义在plugins/generic/takeover.py#Takeover.osShell下面。takeover.py模块中另有关于操作系统接受功能的函数定义,这里只关注osShell函数即可。

主要是5个步骤:
1、根据堆叠查询可用性和配置判断是否使用web方式,如果堆叠查询不可用且数据库是mysql,那么就采用web后门模式。
2、获取远程临时路径。
3、初始化环境。
4、执行shell操作部门。
5、最后清理操作部门。
当判断数据库不支持堆叠查询,而且数据库是mysql时web=Ture采用web后门模式。
函数getRemoteTempPath会尝试返回一个用于存储临时文件的远程路径。它会根据不同的数据库管理系统类型、操作系统类型以及相关配置选项来确定符合的临时文件存储路径。

函数initEnv会进行环境初始化操作。当使用web后门模式,就进行web初始化操作webInit。

接下来函数webInit就是核心操作了,定义在lib/takeover/web.py#Web.webInit里面。它用于在网站的根目录写入后门。其中包罗确定脚本语言类型(sapx/asp/jsp/php),获取文件的完备路径,选择符合的上传目录,通过不同方法上传stager文件和后门文件,并进行相关的测试确保后门可以或许正常执行下令。
这个函数比较长,这里挑重点说一下:
第一步确认应用语言类型:
起首会初始化相关变量,获取公开的应用语言类型,存储在choices列表中。然后需要根据当前的url后缀确定默认语言。如果没有通过url后缀确定出来,那么Windows平台默认就时asp,其他均为php。要么又用户输入自己输入应用语言类型。

第二步准备上传目录和上传文件的内容:
sqlmap它会主动通过从不同来源解析文件路径,包罗从原始页面匹配的url中解析,从修改后的url中解析,从请求参数中解析,从cookie中解析。
接着准备上传目录列表directories,可以通过getManualDirectories函数获取手动指定的目录列表,调用getAutoDirectories函数获取主动生成的目录列表。然后使用正则表达式对路径path进行处理。

然后需要准备待写入的stager文件和backdoor后门文件的文件内容,它会起首生成一个随机的后门文件名(tmp+随机字符串),然后从分别本地来获取后门内容和stager的内容。

可以不妨先来看看这两个文件是什么东西,以php脚本为例。
注意:
这里下划线结尾的文件是无法直接打开浏览的,原因是这些文件中包罗了一些恶意的代码,sqlmap为了防止本地的杀软把这些文件误杀了,进行了加密处理。
可以通过sqlmap提供的extra/cloak/cloak.py进行解密:python cloak.py -d -i D:\Temp\sqlmap-1.8\data\shell\backdoors\backdoor.php_
解密后的backdoor.php_如下:
  1. [/code]这段php代码实现了远程代码下令执行的功能,通过url请求中的cmd参数接受下令,然后通过system,proc_open,shell_exec等函数执行此下令,最后输出下令执行结果。
  2. 解密后的stager.php_如下:
  3. [code]
复制代码
这段php实现了一个简单的文件上传功能,根据php的版原来处理上传的文件,并将文件移动到指定的目录下,最后设置上传文件的权限并反馈上传成功的信息。
第三步上传文件:
上传文件起首需要确定上传文件的路径。这里会遍历上传目录列表directories,拼接一个完备的stager文件路径。

然后会调用函数_webFileInject将指定的文件内容注入到指定目录下。

关于_webFileInject函数,它是实现文件写入的核心实现,它通过构造符合的sql查询语句来实现文件的上传操作,最后再获取执行注入操作后的页面内容并返回。

这里通过函数getSQLSnippet来获取一个针对mysql数据库write_file_limit的sql代码片段(data/procs/mysql/write_file_limit.sql),内容如下:
  1. LIMIT 0,1 INTO OUTFILE '%OUTFILE%' LINES TERMINATED BY 0x%HEXSTRING%-- -
复制代码
sql中的LINES TERMINATED BY 0x%HEXSTRING%原来是用作设置每行数据结束的标志,用来定义行结束的格式。这里的思绪是,将我们的要写入的文件内容当作这个结束标志写入文件,固然这是16进制编码后的。
调试就可以清楚地看到此时的payload:

大致这样:
  1. admin' LIMIT 0,1 INTO OUTFILE '/var/www/tmpumutd.php' LINES TERMINATED BY ...stager文件内容(16进制编码)...-- -
复制代码
函数_webFileInject执行完毕后,会返回获取到的请求文件stager页面内容。然后通过并检查页面中是否包罗“sqlmap file uploader”以此来判断是否上传成功。

此时如果没有上传成功的话,就会回使用union查询来上传文件,通过调用函数unionWriteFile来写文件。

上传stager文件成功后,会检查文件stager页面内容是否可动态解释:

接下来要上传backdoor后门文件,但与上传stager文件有所不同,上传backdoor会先调用函数webUpload,如果函数webUpload上传失败,则会提示是否使用和上传stager文件相同的方式。

函数webUpload它会先将文件内容转换为字节省并进行流操作处理。

再调用函数_webFileStreamUpload函数完成最终的上传操作,_webFileStreamUpload上传就需要借助刚才上传的stager文件,最后通过Request.getPage发送请求到stager文件完成后门文件的上传。

第四步执行shell操作:
当webshell的url路径不为空时,就可以调用执行函数shell来获取交互shell,它定义在lib/takeover/abstraction#Abstraction.shell里面。

这里的函数runCmd会调用函数evalCmd来执行最终的下令。起首它会去判断数据库类型来确定下令执行方式,这里是使用web后门的方式执行下令,其他方式先不谈。

函数webBackdoorRunCmd通过后门的url来执行指定的下令,然后从返回页面内容中提取下令执行输出。

最后的最后,执行exit退出下令后,sqlmap会去删除已上传的这两个文件扫除痕迹。

到这里函数osShell的基本执行流程就分析完了,对于sqlmap在mysql数据库通过webshell的方式getshell会有一个基本的明确了。其实关于sqlmap中getshll的另有许多可聊的,包罗udf,另有mssql数据库的使用方式等等,但限于篇幅在此就不详细展开了。
参考文章
https://stackoverflow.com/questions/36391551/error-1-hy000-cant-create-write-to-file-errcode-13-permission-denied
https://xz.aliyun.com/t/7942?time__1311=n4%2BxnD0DyDu73AKex05%2Bb8DOiGC7iQ8oi74D
https://mp.weixin.qq.com/s?__biz=MzIyMjkzMzY4Ng==&mid=2247485339&idx=1&sn=ea76ee0d56b8a95a118a60d111d48160
若有错误,接待指正!o( ̄▽ ̄)ブ

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4