首页
社区
课程
招聘
[原创]跟着crownless学Web之(4)extract变量覆盖
发表于: 2019-1-26 11:40 8067

[原创]跟着crownless学Web之(4)extract变量覆盖

2019-1-26 11:40
8067

本文备份于我的博客
大家好,我是Web安全板块的新版主crownless。最近我将以CTF赛题讲解的形式介绍一系列的Web基础知识,讲解的顺序将是循序渐进,因此不需要读者有任何基础知识。希望能吸引更多人关注看雪的Web安全板块,为板块增加人气和活力。
如果你还没有阅读第一篇教程第三篇教程,建议你先阅读之后再阅读本文。
在这篇文章中,你将学到:

话不多说,让我们开始吧。首先打开这次的CTF赛题网站:
fc1K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5K6z5g2)9J5k6e0t1J5y4q4)9J5k6e0t1J5x3q4)9J5k6e0j5%4i4K6y4m8x3U0x3&6x3o6m8Q4x3V1k6V1L8i4y4B7i4K6u0r3L8r3g2$3k6h3H3J5i4K6u0r3
你会发现一片空白,网页的源代码也为空。这里,我提供php后端的源代码供你审计:

首先,flag变量被设置为'xxx',一个简单的字符串。
接着,后端运行了extract函数,从$_GET数组中将变量导入到当前的符号表。什么意思呢?其实很简单。比如如果我们访问了c6eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5K6z5g2)9J5k6e0t1J5y4q4)9J5k6e0t1J5x3q4)9J5k6e0j5%4i4K6y4m8x3U0x3&6x3o6m8Q4x3V1k6V1L8i4y4B7i4K6u0r3L8r3g2$3k6h3H3J5i4K6u0r3i4K6y4r3M7$3W2^5M7%4c8S2M7Y4y4Q4x3@1b7I4,那么$_GET["sixstars"]的值为字符串1。执行extract($_GET);时,就相当于执行了$sixstars='1'
然后,程序将会执行isset($sixstars)。我们看到,为了获取flag,必须执行到echo 'flag{xxx}';,所以isset($sixstars)的返回值必须为 TRUE。所以,我们必须通过extract($_GET);sixstars变量设置为任意值,即使是空字符串也可以。也就是说,即使访问e0aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5K6z5g2)9J5k6e0t1J5y4q4)9J5k6e0t1J5x3q4)9J5k6e0j5%4i4K6y4m8x3U0x3&6x3o6m8Q4x3V1k6V1L8i4y4B7i4K6u0r3L8r3g2$3k6h3H3J5i4K6u0r3i4K6y4r3M7$3W2^5M7%4c8S2M7Y4y4Q4x3@1b7`.也是可以的。但绝对不能不包含sixstars参数。
接着,程序将会执行$content=trim(file_get_contents($flag));。我们分步看。首先会执行file_get_contents($flag)。正常情况下,如果你不通过URL传入flag参数,那么,因为程序的最开始已经执行过$flag='xxx';,所以到了这里将会执行file_get_contents('xxx')file_get_contents函数可以“将整个文件读入一个字符串”。比如如下代码可以将b4eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3g2^5j5h3#2H3L8r3g2Q4x3X3g2U0L8$3#2Q4x3V1k6Q4c8e0N6Q4b7V1c8Q4z5e0q4Q4c8e0N6Q4b7f1u0Q4z5e0W2Q4c8e0N6Q4z5f1q4Q4z5o6c8Q4c8e0k6Q4b7V1q4Q4z5e0m8Q4c8e0c8Q4b7V1u0Q4b7e0y4Q4c8e0N6Q4b7e0m8Q4z5o6q4Q4c8e0S2Q4b7f1k6Q4b7V1u0Q4c8e0g2Q4z5p5k6Q4z5e0k6Q4c8e0g2Q4z5o6S2Q4b7U0l9`.homepage变量中并显示出来。

接着,php又会执行trim函数,它将会“去除字符串首尾处的空白字符(或者其他字符)”。
最后,php将会执行if ($sixstars==$content),如果为TRUE,那么将会显示flag。
读到这里,你想必已经知道了我们该怎么做:首先,给sixstars变量传入一个值,比如1。然后,给flag变量传入一个我们能控制的网站的地址,并让这个我们能控制的网站的源代码设置为1。由于extract能起到“变量覆盖”的作用,在extract后,flag变量就会被覆盖为我们能控制的网站的地址,而不再是'xxx',这样当执行到file_get_contents时php后端将会从我们能控制的网站上读取到1,并将其和sixstars变量比较,并返回TRUE,然后就能打印flag。
虽然这个方法是可行的,但是今天我要教你一个更简单的方法,那就是php伪协议。我们可以直接给flag变量传入data://text/plain,1。意思是明文1。这样file_get_contents('data://text/plain,1')将会直接返回1,就不需要我们在公网上开一台服务器了。
所以,最后我们的payload是:

这里再强调一下,给后端传参的方法是:在?后跟变量名字,不同的变量之间用&隔开。
关于伪协议,我们以后有机会还会碰到。请大家继续关注看雪Web安全板块crownless的CTF赛题讲解。

<?php
$flag='xxx';
extract($_GET);
if(isset($sixstars)) {
    $content=trim(file_get_contents($flag));
    if ($sixstars==$content) {
        echo 'flag{xxx}';
    } else {
        echo 'Oh.no';
    }
}
?>
<?php
$homepage = file_get_contents('ae1K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3g2^5j5h3#2H3L8r3g2Q4x3X3g2U0L8$3#2Q4x3V1k6Q4x3U0N6Q4x3U0W2Q4x3@1t1`.
echo $homepage;
?>

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-1-26 12:39 被crownless编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (12)
雪    币: 403
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2019-1-26 12:46
0
雪    币: 220
活跃值: (4078)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
2019-1-26 12:53
0
雪    币: 4366
活跃值: (353)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
4

学习了 请教一下为什么这个payload不行:

d36K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5K6z5g2)9J5k6e0t1J5y4q4)9J5k6e0t1J5x3q4)9J5k6e0j5%4i4K6y4m8x3U0x3&6x3o6m8Q4x3V1k6V1L8i4y4B7i4K6u0r3L8r3g2$3k6h3H3J5i4K6u0r3i4K6y4r3M7$3W2^5M7%4c8S2M7Y4y4Q4x3@1b7I4x3K6W2Q4x3X3f1J5x3U0c8Q4x3X3f1J5x3U0m8Q4x3X3f1$3y4#2)9J5y4X3q4E0M7q4)9K6b7X3k6D9j5h3N6Q4x3@1c8Z5N6s2c8H3i4K6y4m8i4K6u0r3i4K6u0r3N6%4N6%4i4K6u0W2K9h3k6U0L8$3&6X3K9h3N6Q4x3X3g2E0k6b7`.`.
2019-1-26 17:07
0
雪    币: 3182
活跃值: (13671)
能力值: ( LV12,RANK:322 )
在线值:
发帖
回帖
粉丝
5
自己学习笔记贴一下:

有一些疑问
1、extract读取了整个&Get(包含我们输入的参数),所以变量flag会被覆盖成我们传入的变量?
2、根据php伪协议的特性,利用返回为1(可控),进而与我们sixstars相符合所以成功?
3、php伪协议 data://— 数据(RFC 2397),是其中的一种 ?是不是换一种格式就达不到这种效果了?
看了一下关于data的伪协议还是不清楚干什么用的,file=data:text/plain这种也可以。
是不是控制了了file_get_contents 返回值为,也能相对应的成功?
2019-1-26 17:54
0
雪    币: 2282
活跃值: (426)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
心许雪 学习了 请教一下为什么这个payload不行: ``` a4dK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5K6z5g2)9J5k6e0t1J5y4q4)9J5k6e0t1J5x3q4)9J5k6e0j5%4i4K6y4m8x3U0x3&6x3o6m8Q4x3V1k6V1L8i4y4B7i4K6u0r3L8r3g2$3k6h3H3J5i4K6u0r3i4K6y4r3M7$3W2^5M7%4c8S2M7Y4y4Q4x3@1b7I4x3K6W2Q4x3X3f1J5x3U0c8Q4x3X3f1J5x3U0m8Q4x3X3f1$3y4#2)9J5y4X3q4E0M7q4)9K6b7X3j5`. ...
你没有理解file_get_contents函数的意义,其真正作用是将其参数所指向的文件的##内容##读取到一个字符串中。如果你想让你的payload生效,那么你应该修改flag参数,让其指向一个网站,其源代码仅仅是“139.224.220.67”这个字符串,而不是现在这样包含另外的杂七杂八的东西。或者你应该修改sixstars参数,让其等于139.224.220.67这台主机读取310K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3W2X3j5$3!0F1k6X3W2Y4i4K6u0W2L8h3g2Q4c8e0N6Q4z5f1q4Q4z5o6c8Q4c8e0g2Q4z5o6k6Q4z5o6g2Q4c8e0g2Q4b7f1g2Q4b7U0W2Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0N6Q4z5o6c8Q4b7U0k6Q4c8e0S2Q4z5o6m8Q4z5p5y4Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0N6Q4z5e0c8Q4b7U0q4Q4c8e0c8Q4b7V1q4Q4z5p5g2Z5N6s2c8H3i4K6y4m8i4K6u0r3i4K6u0r3N6%4N6%4i4K6u0W2K9h3k6U0L8$3&6X3K9h3N6Q4x3X3g2E0k6g2!0q4y4W2)9&6z5q4!0m8c8W2!0q4y4q4!0n7z5q4)9^5x3q4!0q4y4q4!0n7z5q4!0m8b7g2!0q4y4g2)9^5b7g2!0m8z5q4!0q4y4W2)9^5x3q4)9^5x3g2!0q4z5g2!0m8x3g2!0n7y4g2!0q4z5g2)9&6c8q4!0m8x3W2!0q4c8W2!0n7b7#2)9^5b7#2!0q4z5q4!0n7c8W2)9&6z5g2!0q4y4W2)9&6z5q4!0m8c8W2!0q4y4q4!0n7z5q4)9^5c8q4!0q4y4g2)9^5c8W2!0m8c8W2!0q4z5q4)9^5x3#2!0n7c8q4!0q4y4g2)9^5x3g2)9&6b7g2!0q4y4g2)9^5z5q4!0n7x3q4!0q4y4#2)9&6b7g2)9^5y4q4!0q4x3#2)9^5x3q4)9^5x3W2!0q4y4W2)9^5z5g2)9^5x3q4!0q4y4q4!0n7b7W2!0m8y4g2!0q4y4q4!0n7c8q4!0m8x3q4!0q4y4g2)9^5c8W2!0m8b7g2!0q4z5q4)9^5x3#2!0n7c8q4!0q4y4g2!0n7x3q4)9&6c8q4!0q4z5q4!0m8c8W2)9&6y4g2!0q4y4q4!0n7c8W2!0m8c8g2!0q4y4W2)9&6y4q4!0n7z5h3k6D9j5h3N6Q4c8e0g2Q4z5p5k6Q4z5o6u0Q4c8e0k6Q4z5e0g2Q4b7U0m8Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0S2Q4b7f1g2Q4b7e0W2Q4c8e0g2Q4z5o6g2Q4b7U0k6Q4c8e0k6Q4z5p5y4Q4z5o6N6Q4c8e0g2Q4z5e0m8Q4z5e0q4Q4c8e0c8Q4b7U0S2Q4z5o6m8Q4c8e0c8Q4b7U0S2Q4b7f1q4Q4c8e0N6Q4b7V1c8Q4z5e0q4Q4c8e0N6Q4b7f1u0Q4z5e0W2Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0g2Q4z5o6g2Q4b7U0k6Q4c8e0k6Q4b7V1q4Q4z5e0m8Q4c8e0c8Q4b7V1u0Q4b7e0y4Q4c8e0N6Q4b7e0m8Q4z5o6q4Q4c8e0c8Q4b7V1u0Q4z5o6g2Q4c8e0c8Q4b7V1u0Q4z5o6g2Q4c8e0k6Q4z5e0S2Q4b7f1k6Q4c8e0u0Q4z5o6m8Q4z5f1x3I4x3K6W2Q4x3X3f1J5x3U0c8Q4x3X3f1J5x3U0m8Q4x3X3f1$3y4#2!0q4x3W2)9^5x3q4)9&6c8q4!0q4z5q4!0n7c8W2)9&6z5g2!0q4y4q4!0n7z5q4!0m8b7g2!0q4y4g2!0m8c8q4)9&6y4#2!0q4y4#2!0m8b7#2!0m8y4W2!0q4y4q4!0n7z5q4!0n7x3W2!0q4x3#2)9^5x3q4)9^5x3R3`.`.
2019-1-26 18:04
0
雪    币: 2282
活跃值: (426)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
理想小青年 自己学习笔记贴一下:有一些疑问1、extract读取了整个&amp;Get(包含我们输入的参数),所以变量flag会被覆盖成我们传入的变量?2、根据php伪协议的特性,利用返回为1(可控),进 ...
1、是的,flag的原值会被覆盖
2、是的,需要同时控制sixstars和flag变量
3、data://text/plain,1顾名思义是“明文数据1”的意思。关于伪协议,以后我们还会再讲。
你也可以在外网开一台服务器005K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4Q4x3X3g2T1i4K6u0W2j5#2)9J5k6h3c8Q4x3V1k6Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0S2Q4b7f1g2Q4b7e0W2Q4c8e0g2Q4z5o6g2Q4b7U0k6Q4c8e0k6Q4b7V1q4Q4z5e0m8Q4c8e0c8Q4b7V1u0Q4b7e0y4Q4c8e0N6Q4b7e0m8Q4z5o6q4Q4c8e0k6Q4z5e0S2Q4b7f1k6Q4c8e0u0Q4z5o6m8Q4z5f1x3I4i4@1f1J5i4K6R3H3i4K6W2p5i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1%4i4K6R3@1i4@1t1$3i4@1f1#2i4K6V1H3i4K6S2q4i4@1f1$3i4K6S2q4i4@1p5%4i4@1f1#2i4K6R3^5i4@1t1$3k6X3I4S2k6#2!0q4y4g2)9^5c8W2)9&6z5q4!0q4z5g2)9^5y4#2)9^5c8W2!0q4y4q4!0n7z5q4!0n7b7h3S2@1N6s2m8Q4x3@1q4Q4x3V1k6Q4x3V1k6S2i4K6u0W2j5W2)9J5k6h3y4Q4x3X3g2V1i4K6u0r3i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1^5i4@1u0r3i4K6V1&6i4@1f1$3i4@1p5H3i4@1t1%4i4@1f1@1i4@1t1&6i4K6W2r3i4@1f1^5i4K6R3K6i4@1u0p5i4@1f1^5i4@1u0q4i4@1u0q4i4@1f1#2i4K6R3^5i4@1t1H3i4@1f1%4i4K6W2n7i4@1t1^5i4@1f1#2i4K6V1H3i4K6S2o6i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1$3i4K6V1#2i4K6R3^5i4@1f1$3i4K6W2q4i4K6W2o6i4@1f1K6i4K6R3H3i4K6R3J5
2019-1-27 10:05
0
雪    币: 3182
活跃值: (13671)
能力值: ( LV12,RANK:322 )
在线值:
发帖
回帖
粉丝
8
crownless 1、是的,flag的原值会被覆盖 2、是的,需要同时控制sixstars和flag变量 3、data://text/plain,1顾名思义是“明文数据1”的意思。关于伪协议,以后我们还会再讲。 ...
谢谢版主 
2019-1-27 20:17
0
雪    币: 4366
活跃值: (353)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
9
crownless 你没有理解file_get_contents函数的意义,其真正作用是将其参数所指向的文件的##内容##读取到一个字符串中。如果你想让你的payload生效,那么你应该修改flag参数,让其指向一个网站 ...
感谢回复。php中file_get_contents('429K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3W2X3j5$3!0F1k6X3W2Y4i4K6u0W2L8h3g2Q4x3U0N6Q4x3U0W2Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4@1f1^5i4@1u0r3i4K6V1@1i4@1f1#2i4K6W2n7i4K6W2q4i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1#2i4@1t1H3i4@1t1I4i4@1f1$3i4K6V1^5i4@1q4r3i4@1f1#2i4@1u0p5i4K6V1K6i4@1f1#2i4K6R3&6i4K6S2p5M7$3g2J5N6X3g2J5i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1#2i4K6R3%4i4@1u0m8i4@1f1#2i4K6S2r3i4@1p5K6i4@1f1%4i4K6W2m8i4K6R3@1K9i4m8Q4c8e0g2Q4z5f1y4Q4b7U0m8Q4c8e0g2Q4z5f1c8Q4z5o6m8Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0c8Q4b7V1y4Q4b7V1y4Q4c8e0c8Q4b7U0W2Q4z5p5g2Q4c8e0k6Q4z5e0S2Q4b7f1k6Q4c8e0c8Q4b7U0S2Q4z5p5c8Q4c8e0W2Q4z5f1y4Q4z5o6m8Q4c8e0S2Q4b7e0k6Q4z5o6q4Q4c8e0k6Q4z5p5y4Q4z5o6N6Q4c8e0g2Q4b7f1g2Q4z5f1q4X3L8r3q4Y4i4@1f1#2i4K6S2r3i4K6R3J5i4@1f1$3i4K6V1#2i4@1t1H3i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1K6i4K6R3H3i4K6R3J5
file_get_contents(string$filename[,bool$use_include_path=FALSE[,resource$context[,int$offset= 0[,int$maxlen]]]] ) :string
我本地测试过了是可以的,因此怀疑是不是服务器的出口ip不是139.224.220.67呢?
➜  webroot cat pediy.php
<?php
$flag='xxx';
extract($_GET);
if(isset($sixstars)) {
    $content=trim(file_get_contents($flag));
    echo $content;
    if ($sixstars==$content) {
        echo 'flag{xxx}';
    } else {
        echo 'Oh.no';
    }
}
?>
➜  webroot curl '17eK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3I4G2j5$3q4D9K9r3!0K6N6q4)9K6b7e0p5H3x3o6R3H3i4K6u0r3M7r3g2V1K9i4W2Q4x3X3g2H3K9s2m8Q4x3@1k6K6K9i4S2K6N6r3q4J5M7#2)9K6c8o6b7#2i4K6u0W2x3e0t1@1i4K6u0W2y4U0k6Q4x3X3f1J5x3e0u0Q4x3U0k6S2L8i4m8Q4x3@1u0X3L8r3q4Y4i4K6y4p5K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3W2X3j5$3!0F1k6X3W2Y4i4K6u0W2L8h3g2Q4x3U0M7`.
45.124.66.212flag{xxx}%
最后于 2019-1-28 17:54 被心许雪编辑 ,原因:
2019-1-28 17:49
1
雪    币: 2282
活跃值: (426)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
心许雪 crownless 你没有理解file_get_contents函数的意义,其真正作用是将其参数所指向的文件的##内容##读取到一个字符串中。如果你想让你的p ...
有可能是的,服务器不是我配置的,所以我也不是很清楚。
2019-1-29 09:57
1
雪    币: 4366
活跃值: (353)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
11
crownless 有可能是的,服务器不是我配置的,所以我也不是很清楚。
thanks~
2019-1-29 10:06
0
雪    币: 239
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
心许雪 crownless 你没有理解file_get_contents函数的意义,其真正作用是将其参数所指向的文件的##内容##读取到一个字符串中。如果你想让你的p ...
应该是服务器出口地址和题目IP不一样导致的吧,我这边看到通过file_get_contents,访问到我的地址是202.120.234.78,并不是题目地址
2019-2-3 22:49
0
雪    币: 73
活跃值: (923)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
继续学习
2019-2-15 09:58
0
游客
登录 | 注册 方可回帖
返回