정보를 처음부터 알고 공격을 하는가?
모의해킹 | 취약점진단 |
---|---|
시나리오 기반 | 취약점 항목 기반 |
화이트박스 기반 점검 | 블랙박스 기반 점검 |
Zero Base → 공격수행 | 담당자 정보 요청 → 정보수령 → 공격수행 |
동적진단 | 소스코드(정적)진단 |
1개 서비스 | 1개 URL |
시간 소요↑(수 개월~수 년까지) | 상대적으로 시간소요↓ |
소스코드를 활용하여 애플리케이션 내 모든 입출력 값에 대에 Data Tracing을 통해 취약점 누락을 최소화 및 상세 취약점 점검을 수행하여 보안 수준을 향상하는데 목적을 둔다.
전달받은 모든 소스 코드를 확인하여 분석할 경우 오래 걸리기 때문에 빠른 시간 내 전체 입출력 데이터를 식별/분석하기 위함
초기 키워드 추출 시 넓은 범위의 키워드 검색하기
입력 → 입력처리 → DB처리 → 출력처리 → 출력
#
SELECT * FROM users WHERE id = #{userId}
Prepared Statement의 원리
1. 컴파일
- PreparedStatement를 생성할 때 SQL 쿼리는 먼저 데이터베이스 측에서 컴파일됨.
- SQL 문장 구조를 데이터베이스가 분석→실행계획 준비
2. 파라미터화
- SQL쿼리에 파라미터를 사용하여 값을 넣을 수 있는 형태로 작성
- 여기서 파라미터는?
와 같은 Placeholder를 통해 지정됨.
3. 재사용
- 한 번 컴파일된 후 동일한 쿼리를 반복해서 실행할 때 재사용됨.
- 쿼리가 실행될 때마다 파라미터 값만 변경되고 실행 계획은 미리 준비되어 있어 빠른 실행 가능
$
SELECT * FROM users WHERE id = ${userId}
동적으로 조작한다는 것은 프로그램이 실행되는 동안에 쿼리나 데이터를 변형하거나 조작하는 것을 의미. 외부 입력값이 쿼리에 바로 삽입되어 SQL Injection 같은 보안 취약점 발생할 수 있음.
블랙리스트 검증보다 화이트리스트 검증
String fileName = request.getParameter("P")
BufferedInputStream bis = null
BufferedOutputStream bos = null
FileInputStream fis = null
try{
response.setHeader("Content Disposition", attachment;filename fileName+";")
...
fis = new FileInputStream ("C:/datas/"+fileName);
bis = new BufferedInputStream(fis)
bos = new BufferedOutputStream(response.getOutputStream());
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "--//mybatis.org//DTD Mapper 3.0//"http://mybatis.org/dtd /mybatis-3-mapper.dtd">
...
<select id="boardSearch" parameterType ="map" resultType="BoardDto">
select * from tbl_board where title like '%'||#{{keyword}||'%' order by pos asc
</select>
<% String keyword = request.getParameter ("keyword");
keyword = keyword.replaceAll ("&", "&");
keyword = keyword.replaceAll ("<", "<")"
keyword = keyword.replaceAll (">", ">")"
keyword = keyword.replaceAll ("\", """)"
keyword = keyword.replaceAll ("'", "'")"
keyword = keyword.replaceAll ("/"", "/")"
keyword = keyword.replaceAll ("(", "(")"
keyword = keyword.replaceAll (")", ")")"
검색어 : <%=keyword%>
<>
()
''
""
&
가 모두 필터링됐기 때문에if (FileUploadCtr.PostedFile.ContentType == "image/jpeg")
{
if (FileUploadCtr.PostedFile.ContentLength < 102400)
{
string fn = Path.GetFileName(FileUploadCtr.FileName);
FileUploadCtr.SaveAs(Server.MapPath("~/") + fn);
StatusLabel.Text = "Upload status: File uploaded!";
}
else
{
StatusLabel.Text = "Upload Status: The File has to be less than 100 kb!";
}
}
else
{
StatusLabel.Text = "Upload Status: Only JPEG files are accepted!";
}
악성파일 업로드
최선 : 확장자 검증(화이트 리스트 기반)
차선 : Content type / 파일크기 / 파일의 실행권한 제어 / 특수문자 검증
String id = request.getParameter("id");
String bn = request.getParameter("bn");
String rd = request.getParameter("redirect");
if (id.length() > 0) {
String sql = "select * from customer where customer_id = ? ";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if ("0".equals(rs.getString(1)) && "0".equals(rs.getString(2))) {
response.sendRedirect(rd);
}
}
String gubun = request.getParameter("gubun");
...
String sql = "SELECT * FROM board WHERE b_gubun = '"+gubun+"'";
Connection con = db.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.excuteQuery(sql);
public static void main(String[] args) throws IOException {
List<String> allowedCommands = new ArrayList<String>();
allowedCommands.add("calc");
allowedCommands.add("notepad");
String cmd = args[0];
if (!allowedCommands.contains(cmd)) {
System.err.println("Error");
return;
}
Process ps = null;
try {
ps = Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
e.printStackTrace();
}
}
string file = Request.QueryString["path"];
if(file != null){
if(file.IndexOf('\\') > -1 || file.IndexOf('/') > -1){
Response.Write("Path Traversal Attrack");
}else{
File.Delete(file);
}
}
\
와 /
를 검증하기 때문에 양호하다.<%
String Param = request.getParameter("param");
if(param != null){
param = param.replaceAll("<script>","");
param = param.replaceAll("</script>","");
}
%>
...
<p>제목 : <%=param%></p>
<%@taglibprefix="c" url="http://java.sun.com/jsp/jstl/core"%>
<%@tagliburi="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
...
<c:out value="${param.name}" escapeXml="false" />
MultipartRequest
multi = new MultipartRequest (request, sizeLimitsizeLimit," euceuc-kr ",new DefaultFileRenamePolicy());
...
String fileName=multi.getFilesystemName("filename");
...
sql="INSERT INTO board(email, r_num, w_date, pwd, content, re_step, re_num, filename)"+"values(?,0,sysdate(),?,?,?,?,?)";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, stemail);
pstmt.setString(2, stpwd stpwd);
pstmt.setString(3, stcontent);
pstmt.setStringsetString(4, stre_step step);
pstmt.setStringsetString(5, stre_num );
pstmt.setStringsetString(6, fileName );
pstmt.executeUpdate();
Thumbnail.create(savePath+"/"+fileName, savePath+"/"+"s_"+fileName,150);
import java.security
import javax.crypto.Cipher
import javax.crypto.NoSuchPaddingException
public class CryptoUtils{
public byte[] encrypt(byte[] msg , Key k){
byte[] rslt = null;
try {
Cipher c = Cipher.getInstance ("DES");
c.init(Cipher.ENCRYPT_MODE, k);
rslt = c.update(msg);
}
import java.util.Random
...
public Static int getRandomValue(int maxValue){
Random random = new Random(100);
return random.nextInt(maxValue);
}
public Static String getAuthKey(){
Random random = new Random()
String authKey = Integer.toString (random.nextInt());
...
try {
rd = new BufferedReader(new FileReader(new File(filename)));
} catch(IOException e) {
e.printStackTrace();
}
e.printStackTrace()
를 그대로 노출하고 있다. @RequestMapping(value = "/modify.do", method = RequestMethod.POST)
public ModelAndView memberModifyProcess(@ModelAttribute("MemberModel") MemberModel memberModel, BindingResult result, HttpServletRequest request, HttpSession session) {
ModelAndView mav = new ModelAndView();
String userId = (String) session.getAttribute("userId");
String password = request.getParameter("oldPUserPw");
...
if(service.modifyMember(memberModel)) {
mav.setViewName("redirect:/board/list.do");
session.setAttribute("userName", memberModel.getUserName());
return mav;
} else {
mav.addObject("errCode", 2);
mav.setViewName("/board/member_modify");
return mav;
}
}
클라우드 진단 개념 다양
플랫봄보안
기술적 진단/관리적 진단체크리스트
진단 수행Security Group VS Network ACL 차이점 및 공통점
- 공통점 : IP/Port 기반 접근제어
- 범위
- Security Group : 인스턴스 기반 IP/Port 접근제어
- Network ACL : 네트워크 기반 IP/Port 접근제어