19th-day

 · 2019-8-18 · 次阅读


44.程序逻辑问题(http://ctf5.shiyanbar.com/web/5/index.php)
  进入页面后是一个提交框并且可以看到框中已经有数据了,然后有个welcome to simplexue.点提交查询试试,然后是登陆失败。F12看一下,在源代码中发现一个Index.txt点进去看一下,可以看到如下代码:
if($_POST[user] && $_POST[pass]) {
$conn = mysql_connect(“****, “*”, “****“);
mysql_select_db(“phpformysql”) or die(“Could not select database”);
if ($conn->connect_error) {
die(“Connection failed: “ . mysql_error($conn));
}
$user = $_POST[user];
$pass = md5($_POST[pass]);

$sql = “select pw from php where user=’$user’”;
$query = mysql_query($sql);
if (!$query) {
printf(“Error: %s\n”, mysql_error($conn));
exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row[“pw”];

if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
echo “

Logged in! Key:**

“;
}
else {
echo(“

Log in failure!

“);

}
}
很明显应该是一道代码审计类题目,根据题目说是逻辑问题现在来读一下代码。其中的mysql_fetch_array函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有。返回根据从结果集取得的行生成的数组,如果没有更多行则返回 false。strcasecmp比较两个字符串(不区分大小写
如果$pass=$row[pw]就返回0.其余情况均不为0.可以看到sql语句是直接拼接在了用户的可控输入上,这种是很容易进行sql注入的,因而需要构造自己的sql语句得到自己想输入的密码:payload:Username’ union select md5(1) #,密码就输入1。然后就解出来了key,这里说明一下。这样输入用户名的方式首先用户名不变保持它的提示用户名,之后在查询中多返回一项密码的md5值而这样查询结果作为直接判断的依据,因而自己输入的md5里面的1就成了密码。因而直接通过判断进行了登陆。
45.NSCTF web200(http://ctf5.shiyanbar.com/web/web200.jpg)
  进入页面后是一张图片是一个加密的自定义函数也就是我们要写出它的解密函数就能得到key。
原加密函数如下:

我写出的解密:
$str=a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws;
$a=”~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg”;
//_o=strrev($str);
//$num=strlen($_o);
$i=0;
$j=strlen($_a);
echo $j;
$_e=””;
for($i;$i<$j;$i++){
$b=substr($_a,$i,1);
$c=ord($b)-1;
$d=chr($c);
$_e=$_e.$d;
}
echo strrev($_e);
  这里说明一下,这道题我是反推过去的,我先顺着函数加密思路看一下,先假设str=abcde,反转后$_o=edcba;之后进入循环解也就是循环五次因为长度为5,第一行的substr是截取字符串,这道题我把它直接想成一个数组也就是数组$_o[]=edcba,因而就给$_c赋值从e->a.下一行是返回$_d的Ascii值并且+1,在下一行是再把这个Ascii值变成字符。第一次也就是e变成了f,然后把这个f赋值给一个最开始为””的$
.这样五次循环下来$=fedcb.然后在进行base64加密,反转rot13就是最后加密的结果。这样分析起来就简单了很多。现在结束例子用本题去写解密代码。首先为了简便先把$_算出来,$=”~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg”;
这个也很好算直接:$_=base64_decode(strrev(str_rot13($_str))),这里的str就是给出的密文。然后刚刚从例子可以看出只是反转后把每个字符都换成了下一个ASCII表中的字符而已,因而循环中把$_的每一个字符都换成上一个ASCII表中的字符即可,然后找一个最开始为””的变量存起来,存起来后再用反转函数最后得出的就是解密结果,上面我自己写的解密代码也就是这个思路,最后拿下了flag.
  summary:这道题其实思路是挺简单的,但是我做了还是挺久的有1个小时了,为什么会做这么久也是因为很久没有些C的逻辑代码了,因而一个小循环都绕半天,因而大一那时候练习C还是对现在读代码很有帮助的。还有我觉得自己很赞的一点是不会的时候活用一个简单的例子然后采用类比,就一步一步解出来了,化难为易。像这道题就是很好的例子,本来经过Base64加密的很复杂一大长串字母很多人看到头都晕了更别说解密了,我也是,因而换成简单的abcde来做相同的事,再把要解密的带进这个abcde的思路就解决了,今天get到了,嗯加油!