0%

其实这次web题目质量一般,可能web只有一道题目做起来让人觉得知识点和考察方式都很好,既简单又困难的那种感觉吧,web题目应该是AK了,但是有一部分没啥营养,这里就记录下两道题目:

1、简单的php

2、高手高手高高手

简单的php

这道题目其实以前也遇到过,不过这里过滤了更多的东西,中心思想还是一致的,我们首先看代码:

1
2
3
4
5
6
7
8
9
<?php
show_source(__FILE__);
$code = $_GET['code'];
if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/is',$code)){
die(' Hello');
}else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){
@eval($code);
}
?>
阅读全文 »

前言

我的手机是安卓9.0 本来一直用的微信6.0,微信6.0证书随便信任,所以抓包也一直没问题。但是最近测试的时候发现微信版本太低会导致部分小程序打开界面有问题,无奈只能升级到最新微信版本,同时进行了抓包的配置。所以记录了一下。

微信版本对手机系统证书的支持

  • 安卓系统 7.0 以下版本,不管微信任意版本,都会信任系统提供的证书
  • 安卓系统 7.0 以上版本,微信 7.0 以下版本,微信会信任系统提供的证书
  • 安卓系统 7.0 以上版本,微信 7.0 以上版本,微信只信任它自己配置的证书列表
阅读全文 »

python的循环引用

什么是循环引用

最近写代码遇见了几次python的循环调用问题,主要原因肯定是编码不规范,应该是共同调用的代码抽离出来重新封装,而不是B里面有A需要的代码,同时A里面也有B需要的代码,这样交叉引用python就会报错

当我们import一个python文件时,python会首先去查找这个文件之前是否被import过,如果这个文件之前有被import过,就不会重新再import一次。否则会倒入,并执行一边代码。

python核心编程这本书也说过这个问题:

加载模块会导致这个模块被执行。也就是被执行模块的顶层代码将直接被执行。这通常包含设定全局变量以及类和函数的声明。一个模块只被加载一次,无论它被导入多少次。这可以阻止多重导入时代码被多次执行

阅读全文 »

什么是JNDI

J2SE,是java2的标准版,主要用于开发桌面的应用程序。

J2SE包含了构成java语言核心的类:数据库连接、接口定义、输入输出、网络编辑等。

J2EE, 是java2的企业版,主要用于分布式的网络程序的开发。

j2ee包含j2se中的类,还包含用于开发企业级应用的类,也包含企业应用中很多的API。例如:JDBC、JNDI、EJB等

不少专家认为,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识

JNDI概念

JNDI全称Java Naming and Directory Interface 翻译过来就是Java命名和目录接口。这个概念搞出来就是为了方便人们来记录一些不容易记录都内容。有点类似于域名和ip的映射。所以如果要深入的学可能会被绕进去,现在你可以简单的理解为他是一个字典,给不同的对象和属性(value)取名(key)。到时候好找出来用。

JNDI作用

网上比较经典的例子就是JDBC连接数据库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Scr {
public static void main(String[] args) {
//JDBC驱动名
String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//数据库URL:这里的tt是数据库名称
String JDBC_URL = "jdbc:mysql://localhost:3306/tt?useSSL=false&serverTimezone=UTC";
// 数据库的用户名与密码
String USER = "root";
String PASS = "admin123";
//通过DriverManager类获得该连接对象才能访问数据库
Connection connection = null;
// 通过Connection获得该结果对象用于执行静态的SQL语句
Statement statement = null;
try {
// 注册JDBC驱动
Class.forName(JDBC_DRIVER);

// 数据库的连接:通过DriverManager类的getConnection方法,传入三个参数:数据库URL、用户名、用户密码,实例化connection对象
connection = DriverManager.getConnection(JDBC_URL,USER,PASS);
// 实例化statement对象
statement = (Statement) connection.createStatement();
// 定义数据库查询语句:查询aa表中的name、sex两列数据
String sql = "SELECT name,sex FROM aa";
// 执行查询语句
ResultSet rSet = statement.executeQuery(sql);
// 展开查询到的数据
while(rSet.next()) {
// 这里getString()方法中的参数对应的是数据库表中的列名
String get_name = rSet.getString("name");
String get_sex = rSet.getString("sex");
// 输出数据
System.out.println("名字:"+get_name);
System.out.print("性别:"+get_sex);
}
// 依次关闭对象
rSet.close();
statement.close();
connection.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

阅读全文 »

cobaltstrike隐藏特征记录

端口特征

端口尽量修改非默认端口,除了是规避特征,也防止被扫。这个修改端口非常简单,这里不再赘述。

证书特征

这里cobalstrike有两个地方需要用到证书,一个是和CS的通信,另一个则是我们创建https监听器时也需要证书,这两个都有默认自带,但是肯定是有特征的,所以都需要自己生成。一般网上教程会忽略对https证书的修改,可能也会被杀软标记。

ulike.store

我们这里直接使用linux自带的keytool命令生成证书

1
keytool -keystore ulike.store -storepass xxxx123 -keypass xxxx123 -genkey -keyalg RSA -alias ulike.com -dname "CN=US, OU=ulike.com, O=Sofaware, L=Somewhere, ST=Cyberspace, C=CN"

这里面的密码我们要记住,后面定制profile还需要使用。

你可以生成两个不同的证书,也可以都适用这一个证书。当然网上还有教程推荐生成带绿标的https证书,我觉得没有那个必要,能用就行,如果你需要一个真正合规的https证书,那你需要申请一个域名,然后去cloudfare或者freessl网站上去申请一个证书,也是免费的。

流量和行为特征

流量特征如果你有深厚的编程功底,可以直接去二开CS,很多安全大厂也是这样做的。当然我没有😂,所以我选择定制一下profile, cs的profile文件可以修改流量特征以及修改beacon的默认行为,目的是为了让通信变得更加隐蔽。

如果你对profile的语法还不够了解,甚至不知道是什么,推荐去读一下官方文档或者这个:https://blog.zsec.uk/cobalt-strike-profiles/

我们这里不直接提供profile 样例,而是说一下应该注意什么:

  • 首先是要修改https http 的各种流量特征,加一些自己的定制字段和header伪造为正常的流量。

  • 修改pipename管道名称

  • 绑定https证书

我们绑定上面的证书在profile中可以这样写

1
2
3
4
https-certificate {
set keystore "ulike.store";
set password "xxxx123";
}

至于其他的一些细节,比如进程注入、反射的beacon.dll文件的具体特征等,可以去github上查找红队大佬的profile案例,理解后学习。每个人的写法不一致,而且被研究后也容易被针对。

vps特征

有时候我们的流量免杀可能都做到位了,但是还是被杀,可以考虑下是不是vps被标记了。更换vps。或者在一开始使用的时候,就可以使用cdn,域前置技术,来规避vps的ip被直接标记。

UTCTF

UTCTF是由德克萨斯大学奥斯汀分校的信息与系统安全协会运营的,面向全世界所有人。此次正好是一个练手机会,最终排名第20,其中主要做了一些web和流量分析的题目,这里简单写下wp。

阅读全文 »

frp常用功能

frp穿透配合Proxifier实现内网穿透

内网穿透常用,一般用来穿透内网进行下一步的渗透。FRP做一层两层穿透确实挺好用的,多层穿透还是直接msf或者nps更方便一点。

服务端配置

1
2
3
4
5
6
7
# frps.ini
[common]
bind_port = 7000
# 工作台配置,不需要可以不配置
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = password
阅读全文 »

前言

同源策略是浏览器安全策略的核心,非同源不得交互,但是有时候一家公司有自己的不同业务,不同的子域名,或者说有合作方,不同的域名端口需要交互数据呢。这就是跨域的需求。

跨域目前一般常见两种方式:Jsonp、CORS、代理。

JSONP

js在script标签中是不受同源策略限制的,我们也经常能看到<script src="http://xxx.xxx.xx.x/xxx.js">,当然img也不受限制,但是img不太好做后续数据的处理。

jsonp的核心是在前端动态创建一个script标签。并设置src属性指向跨域的服务器。服务器返回包含json数据的javascript函数。前端接受到对应函数和对应的数据,直接执行处理就拿到了我们想调用接口拿到的数据。

demo

我们实现一个demo,后端用我比较熟悉的Flask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import Flask, request, render_template_string

app = Flask(__name__)

# 假设这是一个返回JSONP响应的服务端点
@app.route('/jsonp')
def jsonp_demo():
# 获得客户端传递的回调函数名称
callback = request.args.get('callback', 'callbackFunction')
data = {'user': 'Alice', 'id': 123} # 这里是我们想要传递给客户端的数据
response = f"{callback}({data})"
return response

if __name__ == '__main__':
app.run(debug=True)

如果有浏览器访问/jsonp接口就会获取回调函数的名称,然后把这个接口需要传递的数据封装进去。然后前端代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<title>JSONP Demo</title>
<script>
// 定义处理JSONP响应的回调函数
function handleJSONPResponse(data) {
console.log('Received data:', data);
}
</script>
<script>
// 动态添加<script>标签进行跨域请求
function requestJSONP(url, callbackName) {
var scriptTag = document.createElement('script');
scriptTag.src = url + '?callback=' + callbackName; // 添加callback参数到URL
document.head.appendChild(scriptTag);
}
// 调用JSONP请求
// 注意更改URL中的端口号为你的Flask服务器运行的端口号
requestJSONP('http://localhost:5000/jsonp', 'handleJSONPResponse');
</script>
</head>
<body>
<h1>JSONP跨域请求示例</h1>
</body>
</html>

前端请求http://localhost:5000/jsonp接口,并获取了数据打印。如果不使用jsonp,那么直接在当前域下请求别的域的接口是不合法的。所以jsonp解决了跨域问题。

优点:简单高效兼容性好

缺点:只支持GET请求,还有xss漏洞的奉献。(src的低危的主要贡献漏洞😂)

CORS跨域

有些人看完上面的jsonp跨域可能想,为啥不能script标签里面执行AJAX的动态请求呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><title>AJAX Request to Baidu</title>
<script>
document.addEventListener('DOMContentLoaded', function() {
var xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象
// 配置请求方法、URL以及异步处理
xhr.open('GET', 'http://www.baidu.com', true);
// 设置状态变化回调处理请求结果
xhr.onreadystatechange = function() {
// 仅当请求完成且响应就绪时才运行
if (xhr.readyState === 4) {
// 检查HTTP响应状态码是否为200 OK
if (xhr.status === 200) {
// 这里可以获取到返回内容进行处理,例如打印到控制台
console.log(xhr.responseText);
} else {
// 请求失败处理
console.error('AJAX Request to Baidu failed');
}
}
};
// 发送HTTP请求
xhr.send();
});
</script>
</head>
<body>
</body>
</html>
image-20240313105201430

可以看到仍然被同源策略限制。

怎么解决呢?这里就是CORS了。

1、当浏览器发起跨域请求,它会先发送一个“预检(Preflight)”请求,该请求采用OPTIONS方法,并携带诸如OriginAccess-Control-Request-MethodAccess-Control-Request-Headers之类的特定头信息,询问服务器是否愿意接受跨源请求。

2、服务器的回应是关键所在。如果服务器准许,它会回复一个包含Access-Control-Allow-OriginAccess-Control-Allow-Methods等头信息的“预检响应”,明确告诉浏览器哪些跨域行为是被许可的。

3、一旦服务器的“预检响应”亮绿灯,浏览器随即会发送正式的请求。服务器此时通过检查请求头的Origin字段,决定是否允许访问资源,并在响应头中包含Access-Control-Allow-Origin字段,列明哪些域名可以接收响应数据。

CORS不仅仅是关于XMLHttpRequest请求的,它还涵盖了其他安全机制,包括对cookies和认证的处理。大多数现代浏览器都已支持CORS,但一些旧版的浏览器,像是IE10及其以下版本,则不支持这项功能。

代理实现跨域

我们可以实现一个代理服务器来实现跨域,也就是A和B域之间有一个代理服务器。平常我们写python代码用requets请求百度,从来没有人拦截我们对吧,因为我们不是在浏览器操作,那我们可以请求一个我们自身的接口,这个接口从代码层再去另一个服务器拿数据再返回给前端,那这个接口就是一个代理。

通过实现代理来实现跨域也是一种方法,但是好像不太多见。

服务端代理代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const express = require('express');
const fetch = require('node-fetch');

const app = express();
const PORT = 3000; // 代理服务器端口

// 允许跨域
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});

// 代理路由,将请求转发到百度
app.get('/proxy', async (req, res) => {
try {
const response = await fetch('http://www.baidu.com');
const data = await response.text();
res.send(data); // 将从百度获取的数据发送回客户端
} catch (error) {
console.error('Error making proxy request:', error);
res.status(500).send('An error occurred while making proxy request');
}
});

app.listen(PORT, () => {
console.log(`Proxy server is running on http://localhost:${PORT}`);
});

前端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX Proxy Demo</title>
<script>
function makeRequest() {
var xhr = new XMLHttpRequest();

// 使用自己的代理服务器
xhr.open('GET', 'http://localhost:3000/proxy', true);

xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 这里将显示百度首页的HTML
console.log(xhr.responseText);
document.getElementById('response').innerHTML = xhr.responseText;
} else {
console.error('Proxy request failed.');
}
}
};

xhr.send();
}
</script>
</head>
<body>
<h1>AJAX Proxy Demo</h1>
<button onclick="makeRequest()">Request Baidu through Proxy</button>
<div id="response"></div>
</body>
</html>

备注

不太明白一些面试总是会问的特别细,比如一些CORS字段什么的,CSP的一些字段等等,感觉太多啦 有时候确实记不住啊,看见知道是什么意思还不行吗?有点废脑子,有时候知道已经理解啦,但是还是记不住那些参数。

前言

SSRF是非常容易忽略的一个漏洞,我甚至在渗透测试的项目中甚至不会去深究这方面的漏洞,因为它通常危害较小,并且极难利用。但是上次我在一个项目中发现了一个SSRF,并且同服务器还有另一个对内开放的网站,这样这个SSRF就为攻击者建立了一个从对外开放到网站渗透到对内开放的网站。最后利用SSRF探测到了对内开放的那个网站有sql注入,虽然没有getshell,但是还是引起了重视,SSRF在很多时候还是有用武之地的。

SSRF

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。很晦涩!!!举个例子:服务端有一个在线加载图片的功能,你传入一个图片URL,网站就会加载出来对应图片,所以图片的URL是网站服务器去访问的,如果我们利用这点传入一些只有服务端才能进行访问的URL,比如不对外开放的后台地址,那么这个过程就是服务端的请求伪造。

阅读全文 »