sqli-labs 通关指南:Less 24

由于 Less 24 中每次提交参数都会切换页面,因此没有任何注入点。此处考虑的就不是暴露敏感信息了,而是进行其他的破坏,例如夺取其他账号的权限。这时就需要考虑二次注入,此时我们注入恶意的参数,它不会被马上执行而是存入数据库。当该恶意参数被网页调用时,此时的参数往往是不转义的,就会产生攻击的效果。


Second Degree Injections Real treat-Store Injections(二次注入)

判断注入类型#

打开网页看到一个登陆界面,输入正确的用户名后是修改密码的界面。改密码涉及到对数据库的记录进行替换,我们怀疑此处有一个 UPDATE 语句。

在任何界面进行注入应该都是无效的,因为操作失败时会跳转到其他页面,而没有任何例如错误的回显信息。此处考虑的就不是之前那些把敏感信息弄出来的注入了,而是考虑利用改密码操作夺取其他账号的控制权。

二次注入#

此处我们考虑二次注入,首先我们构造一个特殊的用户,该用户的用户名为 “admin'#”,密码随便设。

用这个特殊的用户进行登录,可以看到网页回显了用户名。

此时我们修改密码,改成什么密码随意,只要修改成功就像。

此时如果将这个用户作为过滤条件实现记录的修改,该用户名后面的 “'#” 不仅能闭合字段,也能把后面的内容注释掉。而且成功闭合后,我们实际上操作的用户名应该是 “admin”。修改密码成功之后,使用用户名 “admin” 和我们修改的密码进行登录,发现我们夺去了该用户的密码,登录成功。

网页源码#

登录界面#

首先看一下登录界面的源码,源码首先使用 POST 方法读取输入的用户名和密码,然后执行一个 SELECT 查询。如果查询成功,就返回查询到的第一个记录。

Copy Highlighter-hljs
function sqllogin(){ $username = mysql_real_escape_string($_POST["login_user"]); $password = mysql_real_escape_string($_POST["login_password"]); $sql = "SELECT * FROM users WHERE username='$username' and password='$password'"; //$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'"; $res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( '); $row = mysql_fetch_row($res); //print_r($row) ; if ($row[1]) { return $row[1]; } else { return 0; } }

调用登录函数,如果有查询到记录就分配一下 cookie,然后跳转到 logged-in.php 页面上。如果登录失败就输出失败信息,从中我们可以看到这里是没有注入点的。

Copy Highlighter-hljs
$login = sqllogin(); if (!$login== 0) { $_SESSION["username"] = $login; setcookie("Auth", 1, time()+3600); /* expire in 15 Minutes */ header('Location: logged-in.php'); } else { ?> <tr><td colspan="2" style="text-align:center;"><br/><p style="color:#FF0000;"> <center> <img src="../images/slap1.jpg"> </center> </p></td></tr> <?PHP }

注册页面#

注册界面使用 SELECT 语句对用户名进行查找,如果查找不到记录就可以使用 INSERT 语句插入记录。mysql_escape_string() 函数用于对字符串进行转义,因此此处也是不能注入的,同时插入数据库中的特殊字符也会被转义。

Copy Highlighter-hljs
if (isset($_POST['submit'])) { # Validating the user input........ //$username = $_POST['username'] ; $username = mysql_escape_string($_POST['username']) ; $pass = mysql_escape_string($_POST['password']); $re_pass = mysql_escape_string($_POST['re_password']); echo "<font size='3' color='#FFFF00'>"; $sql = "select count(*) from users where username='$username'"; $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( '); $row = mysql_fetch_row($res); //print_r($row); if (!$row[0] == 0) { ?> <script>alert("The username Already exists, Please choose a different username ")</script>; <?php header('refresh:1, url=new_user.php'); } else { if ($pass == $re_pass) { # Building up the query........ $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")"; mysql_query($sql) or die('Error Creating your user account, : '.mysql_error()); echo "</br>"; echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>"; //echo "<h1>User Created Successfully</h1>"; echo "</br>"; echo "</br>"; echo "</br>"; echo "</br>Redirecting you to login page in 5 sec................"; echo "<font size='2'>"; echo "</br>If it does not redirect, click the home button on top right</center>"; header('refresh:5, url=index.php'); } else { ?> <script>alert('Please make sure that password field and retype password match correctly')</script> <?php header('refresh:1, url=new_user.php'); } } }

密码修改页面#

在这个页面中,使用 UPDATE 语句修改记录,以用户名和原密码作为过滤条件来过滤。

Copy Highlighter-hljs
if (isset($_POST['submit'])) { # Validating the user input........ $username = $_SESSION["username"]; $curr_pass = mysql_real_escape_string($_POST['current_password']); $pass = mysql_real_escape_string($_POST['password']); $re_pass = mysql_real_escape_string($_POST['re_password']); if($pass == $re_pass) { $sql = "UPDATE users SET PASSWORD ='$pass' where username ='$username' and password='$curr_pass' "; $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( '); $row = mysql_affected_rows(); echo '<font size="3" color="#FFFF00">'; echo '<center>'; if($row == 1) { echo "Password successfully updated"; } else { header('Location: failed.php'); //echo 'You tried to be smart, Try harder!!!! :( '; } } else { echo '<font size="5" color="#FFFF00"><center>'; echo "Make sure New Password and Retype Password fields have same value"; header('refresh:2, url=index.php'); } }

注入原理#

观察上述源码中出现的所有 SQL 语句,都没有明显的注入点,因为没有任何的回显信息。但是观察到在密码修改的 UPDATE 语句前,用户名是没有进行转义的,也就是用户名本身可以夹带一些其他字符。

Copy Highlighter-hljs
UPDATE users SET PASSWORD ='$pass' where username ='$username' and password='$curr_pass'

如果用户名是 “admin'#”,则 SQL 语句会变成这样。

Copy Highlighter-hljs
UPDATE users SET PASSWORD ='$pass' where username ='admin'#' and password='$curr_pass'

由于此时符号没有转义,因此该用户名的 “#” 在 SQL 语句中会当做是注释,也就是这样。

Copy Highlighter-hljs
UPDATE users SET PASSWORD ='$pass' where username ='admin'#

此时发现,我们并不需要原密码进行验证,并且直接修改了其他用户的密码。这就是所谓的 二次注入,这种注入发生在用户提交的值被存储在数据库中,这个值可能被转义过。当这个值被其他模块调用时,会使用而不转义的原来的数据,如果这个数据是恶意注入,在不转义的情况下就会生效。

posted @   乌漆WhiteMoon  阅读(1111)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示
CONTENTS