Java -- 代码审计

JAVA代码审计

文件下载

检查文件处理时,是否有对路径进行强限定,因为强限定路径可以避免用户恶意构建下载文件的路径

文件上传

了解文件路径

src—源代码目录(在部署的时候不会放入到容器里)

WebContent(WebApp\Web)—Web 应用,服务器部署目录,在服务器中生成当前文件同名的目录部署,表示工程根路径。如WEBDemo工程的部署,会将 WebContent改名为WEBDemo。如需要访问改目录则直接使用http://localhost:8080/WEBDemo

​ WEB-INF — WEB的配置目录或信息目录 web.xml (关键文件,可能有工程的整体配置),该目录会被服务器加载,但不能通过URL直接访问。该目录下的所 有文件如果需要访问则必须通过WEB-INF以外的页面访问它。如:WEB-INF里面有一个a.jsp,需要访问这个JSP不能通过URL:http://localho st:8080/projectName/WEB-INF/a.jsp的形式进行访问,必须在WEB-INF的外面,例如WebContent的根下面创建一个b.jsp,用URL访问 b.jsp,通过b.jsp可直接访问a.jsp或包含

​ classes — src源代码被编译以后的字节码文件

​ META-INF — 会被加载但不能被访问,一般用于存放配置文件

站外目录,非工程路径甚至非服务器路径,有可能是其它的某个盘符也有可能是其它的某个服务器。常见的单独的文件服务器

了解开发人员可能上传的路径

classes目录(根)上传—好定位,可以用代码通过当前类文件直接获取到路径甚至流

WebContent目录(根)上传—好定位

工程目录(根)上传

指定盘符上传—绝对路径

独立的文件服务器

检查文件上传路径是否在服务器可加载可编译可访问的位置上,上传在WebContent根或其它目录的路径需要修改。上传在WEB-INF目录的路径,需要更多检查是否在WebContent上可上传可包含以及检查上传路径是否可被修改。

检查文件类型,通常检查文件白名单、Content-Type和文件头
    JPEG (jpg),文件头:FFD8FFE1
    PNG (png),文件头:89504E47 
    GIF (gif),文件头:47494638 
    IFF (tif),文件头:49492A00 
    Windows Bitmap (bmp),文件头:424D 
    CAD (dwg),文件头:41433130 
    Adobe Photoshop (psd),文件头:38425053 
    Rich Text Format (rtf),文件头:7B5C727466 
    XML (xml),文件头:3C3F786D6C 
    HTML (html),文件头:68746D6C3E 
    Email [thorough only] (eml),文件头:44656C69766572792D646174653A 
    Outlook Express (dbx),文件头:CFAD12FEC5FD746F 
    Outlook (pst),文件头:2142444E 
    MS Word/Excel (xls.or.doc),文件头:D0CF11E0 
    MS Access (mdb),文件头:5374616E64617264204A 
    WordPerfect (wpd),文件头:FF575043 
    Postscript (eps.or.ps),文件头:252150532D41646F6265 
    Adobe Acrobat (pdf),文件头:255044462D312E 
    Quicken (qdf),文件头:AC9EBD8F 
    Windows Password (pwl),文件头:E3828596 
    ZIP Archive (zip),文件头:504B0304 
    RAR Archive (rar),文件头:52617221 
    Wave (wav),文件头:57415645 
    AVI (avi),文件头:41564920 
    Real Audio (ram),文件头:2E7261FD 
    Real Media (rm),文件头:2E524D46 
    MPEG (mpg),文件头:000001BA 
    MPEG (mpg),文件头:000001B3 
    Quicktime (mov),文件头:6D6F6F76 
    Windows Media (asf),文件头:3026B2758E66CF11 
    MIDI (mid),文件头:4D546864


    import java.io.File; 
    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.util.HashMap; 
    import java.util.Map; 
    public class FileTypeDetector { 
        //白名单,把能够通过的文件头都放到里面
        private static Map<String,String> head2FileType = new HashMap<String,String>(); 
        //构建白名单文件头
        static{ 
            head2FileType.put("FFD8FFE1", "jpg"); 
            head2FileType.put("89504E47", "png");
            head2FileType.put("47494638 ", "gif");
            head2FileType.put("49492A00", "tif"); 
            head2FileType.put("424D", "bmp"); 
            head2FileType.put("41433130", "dwg");
            head2FileType.put("38425053 ", "psd");
            head2FileType.put("7B5C727466", "rtf");
            head2FileType.put("3C3F786D6C", "xml");
            head2FileType.put("68746D6C3E ", "html");
            head2FileType.put("44656C69766572792D646174", "eml");
            head2FileType.put("CFAD12FEC5FD746F ", "dbx");
            head2FileType.put("2142444E", "pst");
            head2FileType.put("D0CF11E0", "xls/doc");
            head2FileType.put("5374616E64617264204A", "mdb");
            head2FileType.put("FF575043", "wpd");
            head2FileType.put("252150532D41646F6265", "eps/ps");
            head2FileType.put("255044462D312E", "pdf");
            head2FileType.put("E3828596", "pwl");
            head2FileType.put("504B0304", "zip");
            head2FileType.put("52617221", "rar");
            head2FileType.put("57415645", "wav");
            head2FileType.put("41564920", "avi");
            head2FileType.put("2E7261FD", "ram"); 
            head2FileType.put("2E524D46", "rm");
            head2FileType.put("000001BA", "mpg");
            head2FileType.put("000001B3", "mpg");
            head2FileType.put("6D6F6F76", "mov");
            head2FileType.put("3026B2758E66CF11", "asf");
            head2FileType.put("4D546864", "mid"); 
        } 
        //获取上传文件的文件头
        private static String bytesToHexString(String fileName) throws IOException{
            FileInputStream fis = null;
            StringBuilder stringBuilder = new StringBuilder();
            try{ 
                //文件流
                fis = new FileInputStream(new File(fileName));
                //构建4个byte的数组,用来读取文件头
                byte[] b = new byte[4]; 
                //读取文件头
                fis.read(b, 0, b.length);
                //计算文件头
                for (int i = 0; i < b.length; i++) { 
                    int v = b[i] & 0xFF;
                    String hv = Integer.toHexString(v);
                    if (hv.length() < 2) { 
                        stringBuilder.append(0);
                    } 
                    stringBuilder.append(hv);
               } 
           }finally{
                if(fis != null)
                    fis.close();
          } 
          //将最终计算得到的结果转大写并返回给验证方法
          return stringBuilder.toString().toUpperCase(); 
        } 
        //验证文件头是不是在白名单中
        public static String fileType(String fileName) throws IOException{
            //调用上面文件头获取的方法
            String head = bytesToHexString(fileName);
            //从白名单中通过文件头取值,如果没有取到说名文件并一在白名单中
            return head2FileType.get(head); 
        } 
        public static void main(String[] args) throws IOException { 
            System.out.println(fileType("d://aaa.png")); 
        } 
    }

类型溢出

有符号的类型,首高位用0表示正数,用1表示负数。类型溢出是指通过设计让计算结果超过类型最大限制,造成首高位变成1

常见的是int形或者Integer的类型溢出,常常出现在有两个因子进行计算的地方,如:计算总价

检查参于计算的因子是否在计算后或超过限制

在接收到两个因子后直接将因子转成更大的类型,常用BigInteger处理

XSS

保证在页面上不使用innerHTML的方法,用innerText来代替,这样可以保证输出带有编码的内容不会被编译

遵循输入验证和数据净化原则
    public static void main(String[] args) {
        String s = "\uFE64" + "script" + "\uFE65";
        //在验证前进行格式化
        s = Normalizer.normalize(s, Normalizer.Form.NFKC);
        System.out.println(s);
        Pattern pattern = Pattern.compile("[<>]");
        Matcher m = pattern.matcher(s);
        if(m.find()){
            System.out.println("输入不合法");
        }else{
            System.out.println("输入合法");
        }
    }
检查输出是否合法

SQL注入

检查SQL语句有没有拼接
检查是否使用预编译(参数模块化)
遵循下列输入验证和数据净化原则(净化穿越受信边界的非受信数据)

文件包含

检查在使用include指令或动作时,参数是否可变

检查可变参数是否受控于服务器

例如:服务器有验证

例如:以列表的形式限制可以引入的文件或页面,客户端根据选择(下列菜单)传入的并非资源名而是代表这个资源的key,通过这个key在列表中去取资源名和路径,能取到则引入取不到则取消(设置失败,白名单)

命令执行

检查Runntime.exec()方法参数是否可变
检查参数是否在白名单中,参考文件包含或文件上传的白名单,将可执行的命令控制在有效的范围内

SSRF

不要在前端暴露服务器请求的信息

    <a href="WebDemo/read-file?file=http://192.168.17.64/fileName>读取文件</a>

如果服务器有向其它服务器发送请求,那么这个请求在服务器内部处理,由服务器定位资源的路径、访问的地址等

前端只需要传入资源的名称而不能去定位资源

CSRF

在关键提交出检查是否有Token,Token是否合法
在关键提交出检查提交数据的来源Referer,这并不是最好的途径,因为Referer头可以伪造
在关键提交出严格做法将关键信息封装到session里面和Cookie里面。不要放在URL上面,用Cookie取到的和Session中的比较

XXE

检查是否有实体禁用语句

    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);

检查DTD文件,实体定义有没有违法语句

如果服务器接收用户提交的XML并过行解析,那么会由服务器定义DTD文件。

过滤用户输入的XML

检查XML中有没有实体引用的关键词

反序列化漏洞

检查序列化方法的正确签名
不要覆写readObject()方法

输入验证和数据净化

净化穿越受信边界的非受信数据

验证前规范化字符串

在验证之前标准化路径名

不要记录未经净化的用户输入

限制传递给ZipInputStream的文件大小

使用ASCII字符集的子集作为文件名和路径名

从格式字符串中排除用户输入

不要向Runntime.exec()方法传递非受信、未净化的数据

净化传递给正则表达式的非受信数据

如果没有指定适当的locale,不要使用locale相关方法处理与locale相关的数据

不要拆分两种数据结构中的字符串

在验证前去掉字符码点

在不同的字符编码中无损转换字符串数据

在文件或者网络I/O两端使用兼容的编码方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值