HTB - Appointment

这是HTB渗透测试先走后跑中的第一章,对于这一章,我们学习到了SQL的基本原理和进行了一次实战演练
SQL基本原理
举个例子,对于SQL来说,假设我是网站管理员,我可以进行搜索所有内容,但是普通用户或者未认证用户只能搜索正在销售的产品或者自己的信息,对于数据库来说这些表是分开的,但是对于hacker也就是攻击者来说这没有什么意义,因为可以利用类似于navicat类似的工具直接查询网络服务中sql数据库的数据

我们用上面这张图可以很好的说明一个SQL服务器的运作结构
一个例子来说明SQL服务器的运作流程,就是进行用户登录时,web应用会把登陆页面输入的用户名密码发送给sql服务,并将其与数据库中该特定用户存储的条目进行比对。如果提供的用户名和密码与数据库中的任何条目匹配,sql服务器就会把这个情况返回给web端,然后程序会让用户登录,并允许其访问网站受限制部分。登录之后,web就会用cookie或者身份验证令牌的形式为用户设置特殊权限,把他的身份和网站活动关联起来。这个cookie是双向存储的就是说在本地浏览器和网络服务器中都存储
此后,如果用户想要在页面列出的项目中搜索特定内容,他会在搜索框中输入对象名称,这将触发相同的 SQL 服务代表用户运行 SQL 查询。如果数据库中存在被搜索项目的条目(通常位于不同的表中),相关的信息就会被检索出来,并发送给网络应用程序,再以图片、文本、链接以及其他形式(如评论和评价)呈现给用户。
网站使用 MySQL、MariaDB 或其他类型数据库的原因是,它们所收集或提供的数据需要有存储的地方。这些数据可能包括用户名、密码、帖子、消息,或者更为敏感的信息,例如 PII(个人身份信息),后者受到国际数据隐私法律的保护。任何忽视保护用户 PII 的企业都可能面临国际监管机构和数据隐私机构的高额罚款。
SQL 注入是一种常见的攻击方式,针对那些使用 SQL 语句检索和存储用户输入数据的网页。如果配置不当,攻击者可以利用此漏洞进行著名的 SQL 注入攻击,这种攻击非常危险。防止 SQL 注入的方法有很多,包括输入验证、参数化查询、存储过程,以及在服务器网络边界部署 WAF(Web 应用防火墙)。然而,在某些情况下,这些防护措施并未被正确实施,因此根据 OWASP 十大 Web 漏洞列表,此类攻击仍然十分普遍。
实验案例

首先进行nmap扫描,可以看到80端口是开放的
我们一般使用如下命令扫描
nmap -sV -sC -p- --min-rate=1000 [IP]
可以访问到如上页面,那么看到这个登陆框第一个想的肯定就是弱口令爆破无疑了
当然也可以先使用字典进行目录扫描
wget https://github.com/dustyfresh/dictionaries/blob/master/DirBuster-Lists/directory-list-2.3-small.txt
# 拉去目录扫描字典
gobuster dir --url http://10.129.207.2 --wordlist directory-list-2.3-small.txt
# 进行目录扫描当然弱口令爆破比较浪费资源而且有可能被安全检测
admin:admin
guest:guest
user:user
root:root
administrator:password我们可以使用一些默认凭据进行尝试,当然会发现不行。我们用一个PHP和SQL的身份验证源码来讲解原理:
<?php
mysql_connect("localhost", "db_username", "db_password"); # Connection to the SQL
Database.
mysql_select_db("users"); # Database table where user information is stored.
$username=$_POST['username']; # User-specified username.
$password=$_POST['password']; #User-specified password.
$sql="SELECT * FROM users WHERE username='$username' AND password='$password'";
# Query for user/pass retrieval from the DB.
$result=mysql_query($sql);
# Performs query stored in $sql and stores it in $result.
$count=mysql_num_rows($result);
# Sets the $count variable to the number of rows stored in $result.
if ($count==1){
# Checks if there's at least 1 result, and if yes:
$_SESSION['username'] = $username; # Creates a session with the specified $username.
$_SESSION['password'] = $password; # Creates a session with the specified $password.
header("location:home.php"); # Redirect to homepage.
}
else { # If there's no singular result of a user/pass combination:
header("location:login.php");
# No redirection, as the login failed in the case the $count variable is not equal to 1,
HTTP Response code 200 OK.
}
?>注意:#号之后的内容都变成了注释,这是php语言中注释的方式
可以修改查询语句(即$sql变量),让查询执行本不应该执行的操作——完全绕过登录验证! 需要注意的是,我们可以通过网页上的登录表单指定用户名和密码。但这些输入会直接嵌入到执行SQL查询的$sql变量中,且没有经过输入验证。可以看到,没有任何正则表达式或函数禁止我们输入单引号或井号等特殊字符。这是一种危险的做法,因为这些特殊字符可被用来修改查询语句。一对单引号用于指定需要从SQL数据库中检索的确切数据,而#号则用于创建注释。
我们可以通过输入如下来操作查询命令:
username:admin'#我们将用那个单引号来闭合查询语句,让脚本去搜索“admin”这个用户名。通过添加井号,我们会把查询语句的其余部分注释掉,这样一来,为指定用户名 查找匹配密码的操作就变得无关紧要了。如果我们再往下看看上面的 PHP 代码,会发现只有当用户名和密码组合恰好有一个匹配结果时,代码才会批准登录。然而,由于我们跳过了查询中关于密码搜索的部分,脚本现在只会去查找是否存在用户名为“admin”的记录。在这种情况下,我们很幸运,确实存在一个名为“admin”的账户,这会让我们的 SQL 注入验证通过,并且 $count 变量会得到 1 这个值,该值会通过 if 语句的判断,使我们无需知道密码就能登录。如果没有“admin”账户,我们可以尝试其他账户(比如“administrator”“root”“john_doe”等),直到找到一个存在的账户为止。任何有效的、已存在的用户名都能让我们的 SQL 注入奏效。 在这种情况下,由于查询中关于密码搜索的部分已被跳过,我们可以在密码字段中输入任何内容,都不会有影响。
密码可以任意输入都没问题
password:123456更准确地说,下面展示了我们的输入会如何影响 PHP 代码中的查询部分。
$sql="SELECT * FROM users WHERE username='admin'#' AND password='$password'";点击登录之后我们成功进行了sql攻击
