Samsung CTF Quals 2018 - Scan (565 pts.)

먼저 문제를 풀기위해서는 ONOS app (.oar) 파일을 만들어야 하는데 docker로 설치하는 방법이 문제 사이트에 친절히 설명되어있어서 좋았습니다.
https://web.archive.org/web/20180831061125/http://sdn.eatpwnnosleep.com/start (추후에 문제 사이트가 닫힐 것으로 예상하여 archive url로 대체했습니다.)

Scan 문제 자체는 포트를 스캐닝 하는 트래픽을 처단 하면 되는 문제입니다.

그냥 생각나는대로 10.0.0.1의 서버로 접근하는 src ip중 다양한 port로 접속한다면 그냥 return처리하여 서버까지 패킷이 가지 않게 했더니 됐습니다.

문제를 풀면서 힘들었던건.. JAVA를 너무 오랜만에 써봐서 다 검색해서 쓰느라 힘들었네요 ㅋㅋ;;

그래도 sdn문제는 예선, 본선때 정말 재밌는 경험이었습니다. ONOS를 언제 만져볼지..

AppComponent.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.myapp;


import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.TCP;

import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.topology.TopologyService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// added
import java.util.*;

@Component(immediate = true)
public class AppComponent {

// added
HashMap<String, HashSet<Integer>> ip_table = new HashMap<String, HashSet<Integer>>();

private final Logger log = LoggerFactory.getLogger(getClass());

@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;

@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;

@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;

@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;

private ApplicationId appId;
private MyPacketProcessor processor = new MyPacketProcessor();

@Activate
protected void activate() {
// Print log to the ONOS screen.
log.info("Started");
appId = coreService.registerApplication("com.example.myapp");

// Make all IPv4 packets to pass through this app.
packetService.addProcessor(processor, PacketProcessor.director(2));
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.build();
packetService.requestPackets(selector, PacketPriority.REACTIVE, appId);
}

@Deactivate
protected void deactivate() {
log.info("Stopped");
if (processor != null) {
packetService.removeProcessor(processor);
processor = null;
}
}

private class MyPacketProcessor implements PacketProcessor {
// This method is invoked whenever we receive a packet
// that is not matched in the routing tables.
@Override
public void process(PacketContext context) {
// Return if another app has already dealt with this packet.
if (context.isHandled())
return;

InboundPacket pkt = context.inPacket();
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null)
return;
// Forward LLDP and ARP.
if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
allowPacket(context, ethPkt);
return;
}
// Forward ICMP (ping).
IPv4 ip = (IPv4) ethPkt.getPayload();
if (ip.getProtocol() == IPv4.PROTOCOL_ICMP) {
allowPacket(context, ethPkt);
return;
}

if (ip.getProtocol() != IPv4.PROTOCOL_TCP)
return;
TCP tcp = (TCP)ip.getPayload();

// begin added code
String dst_ip = ipToString(ip.getDestinationAddress());
String src_ip = ipToString(ip.getSourceAddress());

if (dst_ip.equals("10.0.0.1")) {
int dst_port = tcp.getDestinationPort();

HashSet<Integer> ports = new HashSet<Integer>();

if (ip_table.containsKey(src_ip))
ports = ip_table.get(src_ip);

ports.add(dst_port);
ip_table.put(src_ip, ports);

if (ports.size() > 15)
return;
}
// end added code

onPacket(context, ethPkt, ip, tcp);
}

private void allowPacket(PacketContext context, Ethernet ethPkt) {
HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
Host dst = hostService.getHost(dstId);
// If we don't know where it's heading for, just broadcast it.
if (dst == null) {
if (topologyService.isBroadcastPoint(
topologyService.currentTopology(),
context.inPacket().receivedFrom())) {
context.treatmentBuilder().setOutput(PortNumber.FLOOD);
context.send();
}
else {
context.block();
}
}
// Forward packet to its destination.
else {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(dst.location().port())
.build();
OutboundPacket packet = new DefaultOutboundPacket(
dst.location().deviceId(),
treatment,
context.inPacket().unparsed());
packetService.emit(packet);
}
}

private String ipToString(int ip) {
return String.format("%d.%d.%d.%d",
(ip >> 24 & 0xff), (ip >> 16 & 0xff), (ip >> 8 & 0xff), (ip & 0xff));
}

private void dumpPacket(IPv4 ip, TCP tcp) {
String flagsString = "";
short flags = tcp.getFlags();
if ((flags & (1 << 0)) != 0) flagsString += " FIN";
if ((flags & (1 << 1)) != 0) flagsString += " SYN";
if ((flags & (1 << 2)) != 0) flagsString += " RST";
if ((flags & (1 << 3)) != 0) flagsString += " PSH";
if ((flags & (1 << 4)) != 0) flagsString += " ACK";

log.info(String.format("Got %s:%d -> %s:%d seq=%08x ack=%08x flags=%s",
ipToString(ip.getSourceAddress()), tcp.getSourcePort(),
ipToString(ip.getDestinationAddress()), tcp.getDestinationPort(),
tcp.getSequence(), tcp.getAcknowledge(), flagsString));
}

private void onPacket(PacketContext context, Ethernet ethPkt, IPv4 ip, TCP tcp) {
dumpPacket(ip, tcp);
allowPacket(context, ethPkt);
}
}
}
Share