0x00 安全引言1、传统Web应用与新兴移动应用

(1)传统Web应用:浏览器 HTTP 服务器
(2)新兴移动应用:APP HTTP 服务器

从安全角度看,传统Web应用与新兴移动应用没有本质区别

2、Web应用安全的核心问题是什么?

用户提交的数据不可信是Web应用程序核心安全问题

用户可以提交任意输入

例如:

√ 请求参数->多次提交或者不提交
√ 修改Cookie
√ 修改HTTP信息头
√ 请求顺序->跳过或者打乱

3、Web应用防御

(1)完善的异常处理
(2)监控
(3)日志:记录重要业务、异常的详细请求信息

4、对输入的处理

建议采用:白名单
尽量避免:净化或黑名单

0x01 SQL注入1、原理:

(1)合法输入:

#!sqlid=1SELECT * FROM users WHRER;

(2)恶意注入:

#!sqlid=1' or '1'='1SELECT * FROM users WHRER or 'a'='a';2、Java代码分析(JDBC)

(1)不合规代码(SQL参数拼接)

#!javapublic class SQLInject { public static void main(String[] args)throws Exception{ //正常输入 select("1"); // 恶意输入 select("' or 'a'='a"); } public static void select(String id){ //声明Connection对象 Connection con; //驱动程序名 String driver = "com.mysql.jdbc.Driver"; //URL指向要访问的数据库名mydata String url = "jdbc:mysql://localhost:3306/mybatis"; //MySQL配置时的用户名 String user = "root"; //MySQL配置时的密码 String password = "budi"; //遍历查询结果集 try { //加载驱动程序 Class.forName(driver); //1.getConnection()方法,连接MySQL数据库!! con = DriverManager.getConnection(url,user,password); if(!con.isClosed()) System.out.println("Succeeded connecting to the Database!"); //2.创建statement类对象,用来执行SQL语句!! Statement statement = con.createStatement(); //要执行的SQL语句 String sql = "select * from users where"; //3.ResultSet类,用来存放获取的结果集!! ResultSet rs = statement.executeQuery(sql); System.out.println("-----------------"); System.out.println("执行结果如下所示:"); System.out.println("-----------------"); String age,name; while(rs.next()){ //获取stuname这列数据 name = rs.getString("name"); //获取stuid这列数据 age = rs.getString("age"); //输出结果 System.out.println(name + "\t" + age); } rs.close(); con.close(); } catch(ClassNotFoundException e) { //数据库驱动类异常处理 System.out.println("Sorry,can`t find the Driver!"); e.printStackTrace(); } catch(SQLException e) { //数据库连接失败异常处理 e.printStackTrace(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally{ System.out.println("数据库数据成功获取!!"); } }}

执行结果:

#!shellSQL Paramter:1-----------------budi 27-----------------SQL Paramter:' or 'a'='a-----------------budi 27budisploit 28-----------------

(2)合规代码(参数化查询)

#!javapublic class SQLFormat { public static void main(String[] args)throws Exception{ select("1"); select("' or 'a'='a"); } public static void select(String id){ //声明Connection对象 Connection con; //驱动程序名 String driver = "com.mysql.jdbc.Driver"; //URL指向要访问的数据库名mydata String url = "jdbc:mysql://localhost:3306/mybatis"; //MySQL配置时的用户名 String user = "root"; //MySQL配置时的密码 String password = "budi"; //遍历查询结果集 try { //加载驱动程序 Class.forName(driver); //1.getConnection()方法,连接MySQL数据库!! con = DriverManager.getConnection(url,user,password); if(!con.isClosed()) System.out.println("Succeeded connecting to the Database!"); //2.//要执行的SQL语句 String sql = "select * from users where id=?"; //3.创建statement类对象,ResultSet类,用来存放获取的结果集!! PreparedStatement stmt = con.prepareStatement(sql); stmt.setString(1, id); ResultSet rs = stmt.executeQuery(); System.out.println("-----------------"); System.out.println("执行结果如下所示:"); System.out.println("-----------------"); String age,name; while(rs.next()){ //获取stuname这列数据 name = rs.getString("name"); //获取stuid这列数据 age = rs.getString("age"); //输出结果 System.out.println(name + "\t" + age); } rs.close(); con.close(); } catch(ClassNotFoundException e) { //数据库驱动类异常处理 System.out.println("Sorry,can`t find the Driver!"); e.printStackTrace(); } catch(SQLException e) { //数据库连接失败异常处理 e.printStackTrace(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally{ System.out.println("数据库数据成功获取!!"); } }}

执行结果:

#!shellSQL Paramter:1-----------------budi 27-----------------SQL Paramter:' or 'a'='a----------------------------------3、防范建议:

√ 采用参数查询即预编译方式(首选
√ 字符串过滤

0x02 XML注入1、原理

(1)合法输入:

#!xmlquantity=1<item> <name>apple</name> <price>500.0</price> <quantity>1</quantity><item>

(2)恶意输入:

#!xmlquantity=1</quantity><price>5.0</price><quantity>1<item> <name>apple</name> <price>500.0</price> <quantity>1</quantity><price>5.0</price><quantity>1</quantity><item>2、Java代码分析

(1)不合规代码(未进行安全检查)

#!javapublic class XMLInject2 { public static void main(String[] args) { // 正常输入 ArrayList<Map<String, String>> normalList=(ArrayList<Map<String, String>>) ReadXML("D:\\JavaWorkspace\\TestInput\\src\\cn\\com\\budi\\xml\\inject\\normal.xml","price"); System.out.println(normalList.toString()); // 异常输入 ArrayList<Map<String, String>> evilList=(ArrayList<Map<String, String>>) ReadXML("D:\\JavaWorkspace\\TestInput\\src\\cn\\com\\budi\\xml\\inject\\evil.xml","price"); System.out.println(evilList.toString()); } private static List<Map<String,String>> ReadXML(String uri,String NodeName){ try { //创建一个解析XML的工厂对象 SAXParserFactory parserFactory=SAXParserFactory.newInstance(); //创建一个解析XML的对象 SAXParser parser=parserFactory.newSAXParser(); //创建一个解析助手类 MyHandler myhandler=new MyHandler(NodeName); parser.parse(uri, myhandler); return myhandler.getList(); } catch (Exception e) { e.printStackTrace(); } return null; }}

运行结果:

#!shell正常输入结果:[{price=500.0}]恶意输入结果:[{price=500.0}, {price=5.0}]